undefined method `layout' for #<HelloController:0x101d7edb0> from Controller - ruby-on-rails

I was trying to switch the layout using Ruby on Rails but I am getting the error: undefined method `layout' for #. I am using Rails 2.3.5 Am I missing an include?
Here is the code:
class HelloController < ApplicationController
def index
layout 'standard'
#message = "Goodbye!"
#count = 3
#bonus = "This is the bonus message!"
end
end

If you are using layout as such, it goes in the Class definition, not an action.
class HelloController < ApplicationController
layout 'standard'
def index
...
This is saying that you want to use this layout for rendering all actions in this controller.
If you want a specific layout for that one action, you would use render :layout as so:
def index
#message =
...
render :layout => 'standard'
end
EDIT: the docs (towards the bottom) seem to suggest that you need to specify the action, as well as the layout when using a specific layout for one action. I don't remember that being the case, but if it is, the above would be render :action => 'index', :layout => 'standard'.

Related

rails render action with that's params

My route for pages in routes.rb
get ":slug", to: 'site#pages'
my actions in site_controller.rb
def pages
render #page.page_template
end
def about
end
def contact
end
def content
end
def local_news
end
def global_news
#newscasts = Newscast.published.paginate(page: params[:page], per_page: 5)
end
and it's my error :)
Not see global_news action my #newscasts parameter
You need to define #newscasts inside pages method
#newscasts = Newscast.published.paginate(page: params[:page], per_page: 5)
Or you can write this in your controller above your methods.
before_action :global_news, only: [:pages]
Before action will run your global_news methods before every action defined inside only: in your case you can write (:pages) you can mention as many methods you want. If you remove only then global_news will run before every method.
This cast an error because you are just rendering the global_news. With render you are not executing the controller action. So #newscast is never set.
You can either use a before filter as in the other answer or call the method manually, because I think you are doing something dynamically here, right?
for example
def pages
global_news
render #page.page_template
end

Rails Set Layout Based on URL Params

So I am trying to change the layout of a view based on url params.
So far, I figured out I have to set the layout in the controller. In my controller under the show action I have:
if params['iframe'] == 'true'
render :layout => 'vendored'
end
The layout 'vendored' exists in views/layouts. I am getting the dreaded rendering multiple times. Here is the rest of the show action in my controller:
def show
#event = Event.find(params[:id])
#user = current_user
#approved_employers = current_user.get_employers_approving_event(#event) if user_signed_in?
respond_with(#event)
The problem is that I don't see another render. I don't see another one in the entire controller. Of course, there is a render somewhere because it is rendering my default application layout, is that causing the problem? I read in the rails docs that I can add
and return
to the end and that should fix the problem, but not sure where to put that since the two renders are not next to each other. I also don't see any other redirect_to's either. Where should I be looking for this other render? Is that the problem?
Alternatively, I think this is easier to understand:
class YourController < ApplicationController
layout :iframe_layout
private
def iframe_layout
params['iframe'] ? "vendored" : "application"
end
end
See this answer. For your case:
before_filter :set_layout, :only => [:show]
private
def set_layout
self.class.layout ( params['iframe'] == 'true' ? 'vendored' : 'application')
end

bypass application.html.erb in Rails app

I have an application.html.erb file which sets out layout for every pages in my app (header, footer etc.) like a typical Rails app.
However, I would like to have a landing page which I don't want to use this file. How should I bypass application.html.erb?
Thank you.
Use
render :layout => false
or
render :layout => 'whatever'
in your action. If you are using a separate LandingController you simply can create a app/views/layouts/landing.html.erb which will be picked up or you can override the layout via
class LandingController < ApplicationController
layout 'whatever'
...
end
You can set a layout in your render function:
render {other arguments}, :layout => :homepage
You can also set that option to false to not use any layout at all.
You can do something similar if you want an entire controller to use a custom layout:
class MyController < ApplicationController
layout :homepage
#...
end
Hope that helps!
In the controller that renders the view, change the render to:
render :layout => false
You can read more about options to render and how to work with layouts at the Rails guide to render and layouts.

How do I use an instance variable assigned in a helper_method from a helper?

I've been drying up one of our controllers in our rails 2.3 app, and I've run up against a problem using an instance variable assigned in a helper_method. Originally, the situation was like this:
home_controller.rb:
class HomeController < ActionController::Base
def index
end
def popular
#popular_questions = PopularQuestion.paginate :page => params[:page],
<some complex query>
end
end
home_helper.rb:
module HomeHelper
def render_popular_questions
#popular_questions = PopularQuestion.paginate :page => 1,
<some complex query>
render :partial => 'popular'
end
end
home/index.html.haml
-cached do
.popular=render_popular_questions
home/popular.html.haml
=render :partial => 'popular'
home/_popular.html.haml
-if #popular_questions.length > 0
<show stuff>
hitting either / or /popular showed the appropriate box of popular questions.
Now, since the query was pretty much duplicated, and since paginate will use the correct page by default, I refactored this as:
home_controller.rb:
class HomeController < ActionController::Base
helper_method :get_popular_questions
def index
end
def popular
get_popular_questions
end
private
def get_popular_questions
#popular_questions = PopularQuestion.paginate :page => params[:page],
<some complex query>
end
end
home_helper.rb:
module HomeHelper
def render_popular_questions
get_popular_questions
render :partial => 'popular'
end
end
now when I go to /, I get
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.length
being raised in line 1 of home/_popular.html.haml
It seems that variables set from within helper_methods called from within helpers aren't accessible to the template. Have I made a mistake somewhere? If not, how do I use an instance variable assigned in a helper_method from a helper?
Pass them as parameters and local-variables:
home_controller.rb:
class HomeController < ActionController::Base
helper_method :get_popular_questions
def index
end
def popular
#popular_questions = get_popular_questions
end
private
def get_popular_questions
# remember that the final statement of a method is also the return-value
PopularQuestion.paginate :page => params[:page],
<some complex query>
end
end
home_helper.rb:
module HomeHelper
def render_popular_questions
questions = get_popular_questions
render :partial => 'popular', :locals => {:questions => questions}
end
end
now in your partial, use "questions" instead of "#popular_questions"
Just make sure that the main template for "popular" also need to populate this local variable too.

Ruby on Rails layouts...except and only bug

I have a controller with the following layout logic
layout 'sessions', :except => :privacy
layout 'static', :only => :privacy
The issue is that Rails seems to ignore the first line of code and the layout "sessions" is not applied for any actions. It simply thinks to render the static layout for privacy and no layout for the rest.
Anyone know how to fix this?
The reason this doesn't work is because you can only have global one layout declaration per controller. The :only and :except conditions just differentiate between actions that should get the specified layout and the ones that are excluded get rendered without a layout. In other words, a layout declaration always affects all actions that use default rendering.
To override you simply specify a layout when you render like one of the following examples inside an action:
render :layout => 'static'
render :action => 'privacy', :layout => 'static'
render :layout => false # Don't render a layout
Another option is to define a method for your layout call, like so:
layout :compute_layout
and then
def compute_layout
action_name == "privacy" ? "static" : "sessions"
end
However this is really only useful when you want to determine the layout at runtime based on some runtime parameter (like a variable being set). In your example, that does not seem to be necessary.
You can just specify layout :static where you need it.
You can also dynamically determine the layout within your controller:
class SampleController < ApplicationController
layout Proc.new { |controller| (controller.action_name == 'privacy') ? 'static' : 'sessions' }
...
end
If more actions within the controller are sharing the same layout:
class SampleController < ApplicationController
layout Proc.new { |controller| ['action1', 'action2'].include?(controller.action_name) ? 'layout1' : 'layout2' }
...
end
Source: https://guides.rubyonrails.org/layouts_and_rendering.html#using-render

Resources