简体   繁体   中英

How do I use a controller method in the main layout?

I have built a 'NewsItem' controller that contains a method called 'top'. This is called by a javascript request to update a DIV on the page every 10 seconds. This is all working well.

def top(number = false)

 # set the default value to use for the number
 default_number = 10;

 # perform checks on the variable
 if number == false
   if params.include?(:number)
     number = params[:number]
   else
     number = default_number
   end
 end

 # Run query to get the required news items
 items = NewsItem.all( :order => ("created_at DESC"), 
                        :include => [:profile], 
                        :limit => number)

 # iterate around the items that have been returned
 @top_news = ""
 items.each do |item|
   @top_news += render_to_string :partial => "partials/news_item", :locals => {:item => item}
 end

respond_to do |format|
 format.html { render :partial => "partials/news_top"}
end
end

This is called with '/news/top' or '/news/top/20' to change the number of items that are returned.

The problem is that when the page is first loaded the 'news' DIV is empty for 10 seconds, until the JavaScript runs to update the DIV. So I want to ensure that the DIV is already populated by calling this function.

Now as I want the 'news' DIV to be available in all pages it is defined in the 'layouts/application.html.erb' template. So I need to call the 'top' method in the 'NewsItem' controller so that it can be rendered into the initial HTML. This is where I am struggling as I cannot work out how to use the 'helper_method' to make this available at this stage.

I have a feeling that I am missing something here and not understanding the whole process.

Thanks very much for any assistance.

Regards, Russell

Try separating out the logic. Maybe you make a method called top_news that returns the value you use in top_news. And since you're passing back a partial, use it to build the string. Partials are meant to be used to iterate over a list.

def index
  @top_news = top_news
end

def top
  @top_news = top_news

  respond_to do |format|
    format.html { render :partial => "partials/news_top"}
  end
end

private

def top_news(number = false)

 # set the default value to use for the number
 default_number = 10;

 # perform checks on the variable
 if number == false
   if params.include?(:number)
     number = params[:number]
   else
     number = default_number
   end
 end

 # Run query to get the required news items
 items = NewsItem.all( :order => ("created_at DESC"), 
                        :include => [:profile], 
                        :limit => number)

 # iterate around the items that have been returned
 return render_to_string :partial => "partials/news_item", :collection => items, :as => :item 

end

The other solution you can follow is to not render any partials in the controller at all except for your one javascript method and instead make a method in your model to do exactly what you're doing here.

class NewsItem

  def top_news(number=20) # pass in number with default 20
    NewsItem.where( :order => ("created_at DESC"), 
                    :include => [:profile], 
                    :limit => number)
  end
end

Then just call it from your controllers to get that so you can use it in your views and iterate over it using partials in your views.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM