In rails is it possible to load class layout dynamically? - ruby-on-rails

I need message to have a different layout in project, is it possible in rails to do something like this?
Class Messages::New < #project? ProjectLayout : NormalLayout
end #i treid this, don't work, since #project has not been initiated.
thanks

this may help you
class MessagesController < ApplicationController
layout :get_layout
def get_layout
#project? ? 'ProjectLayout' : 'NormalLayout'
end
end

Also, since the question is unclear, you can also set layout for only one action with the render option.
render :action => 'new', :layout => 'layoutname'

You can only apply layouts at the Controller level:
class MessagesController < ApplicationController
layout :project
end
Layout method documentation has an example on how to do conditional layouts

You can only apply the rails layouts at controller level and individual action levels.
Unique layout in for each controller
class MessagesController < ApplicationController
layout "admin"
def index
# logic
end
end
** The above line layout "admin" will load the admin layout each time the message controller gets invoked. For that, you must have a layout created in your layouts/admin.html.rb file.**
Dynamic layout for each controller
class MessagesController < ApplicationController
layout :dynamic_layout
def index
# logic
end
protected
def dynamic_layout
if current_user.admin?
"admin" # Show admin layout
else
"other_layout" # Show other_layout
end
end
end
# Individual Action Level Layouts
If you want to display different layouts for each action you can do that.
class MessagesController < ApplicationController
layout :dynamic_layout
def index
# logic
render :action => 'index', :layout => 'index_layout'
end
def show
# logic
render :action => 'show', :layout => 'show_layout'
end
end

Decide the layout in the controller rather then the model. Your ProjectsController can use it's own ProjectLayout and MessagesController can then use the normal layout if you wish.

My two cents in ApplicationController:
before_action :layout_by_action
##actions = %w(new edit create update index)
def layout_by_action
if ##actions.include? params[:action]
self.class.layout 'admin'
else
self.class.layout 'application'
end
end

You can use a Proc:
layout -> {
if something?
'my-layout'
else
'my-other-layout'
end
}

Related

Rails - layout won't apply to desired action

I am trying to apply a specific layout to one action in a controller in my Rails (v. 4.2.5) app, but it will not work. Oddly (or maybe not so oddly), the layout will be used used to render an action if that action is part of the 'resources' route, but not to the action that I need this to work for, which is not part of 'resources'. Sorry if that seems confusing, here's the relevant code and explanation...
routes.rb - here I have the standard resources routes for my entries controller, as well as a an additional route for 'inputs'
get '/entries/inputs' => 'entries#inputs.html'
resources :entries
entries_controller.rb - here I'm trying to apply the layouts/cached.html.erb to the 'inputs' action
class EntriesController < ApplicationController
layout "cached", only: [:inputs]
def inputs
end
def index
#entry = Entry.all
end
end
As it is, layouts/cached.html.erb does not get applied to the 'inputs' action. However, if I swap out the second line of code in the controller for this:
layout "cached", only: [:index]
the layout is successfully rendered for the 'index' action.
What am I missing here? Why will this layout apply to one action but not the other?
Use this code:
class EntriesController < ApplicationController
layout :resolve_layout
def inputs
end
def index
#entry = Entry.all
end
private
def resolve_layout
case action_name
when "inputs"
"cached"
else
"application"
end
end
end
And in Routes:
get 'entries/inputs' => 'entries#inputs'

How to make a specific view not inherit from application.html.erb?

I have one specific view that I don't want to "inherit" the code from layouts/application.html.erb. How should it do this?
One way to do this is to include in application.html.erb:
<% except current_page?(page_path) %>
content
<% end %>
But it feels to me more like something you should specify in the specific view. What would be the convention for this matter?
For one action, you can try:
class TestController < ApplicationController
def method_name
render :layout => 'another_layout'
end
end
For all actions in controller, you can do:
class TestController < ApplicationController
layout 'another_layout'
#action methods here
end
If you don't want a layout to apply to a specific action you can disable layout rendering at the controller level. For example if you want MyController#some_action view to not be rendered within the layout, you can do this:
class MyContorller < ApplicationController
def some_action
# Your logic here
render layout: false
end
end
This way your view (app/views/my_controller/some_action.html.erb) doesn't inherit from the application.html.erb and is rendered containing only what's inside the view file. For more information on rendering you can take a look here
For selected actions you can try like this ......
class MyContorller < ApplicationController
layout 'other_layout_name', only: [:method_1, :method_2, :method_4]
#action methods here
end

How to not use application.html.erb file for a particular page in application?

I want a particular page in the application to have different layout, while all others will have pretty much the same layout. However, the application.html.erb file is rendered for all the pages in application. How do I not use the application.html.erb file for a particular page?
Rails version : 3.2.1
You can make another layout and specify and in your action you can simply use that as follow
class ReportsController < ApplicationController
before_filter :authenticate_affiliate_user!
def daily_breakdown
render :layout => 'admin_layout'
end
end
to you different layout in all of the action you can do as follow
class ReportsController < ApplicationController
layout 'reporting_affiliate'
before_filter :authenticate_affiliate_user!
# your code here
end
Hi you can use layout option or specify particular layout in action
Class SomeControlle < ...
layout :admin_layout,:only=>[:some_action]
def some_action
#or
render :layout=>'admin_layout'
end
end
Use render :layout => 'special_layout' in your controller where you render.

Use a layout for a specific action

If I would like to use a layout for a certain action (say, the show action) that is different from the layout declared at the top of the controller.rb file, how could I do this? This must be possible in rails, but I cannot seem to find anything about it.
render :layout => 'otherlayout'
layout 'layout', :only => [:first_action, :second_action]
layout 'second_layout', :only => [:third_action, :fourth_action]
Don's is right as well, just depends on your application which is more DRY (or DRY-er?)
EDIT
My previous code is mistaken. You cannot specify the layout function multiple times. I found this solution online for dynamic layout rendering:
class OrdersController < BaseController
layout :determine_layout
private
def determine_layout
%w(new).include?(action_name) ? "some_layout" : "public"
end
end
Source: apidock.com/rails/Actio...
Following example applies desired layout to specific action, otherwise, it uses default layout (layouts/application.html.erb).
class ArticlesController < ApplicationController
layout "article_editor", only: [:new, :edit]
def index
# default layout
end
def new
# article_editor layout
end
def edit
# article_editor layout
end
end

Completely different home page

I have an application where my homepage is significantly different from other pages. SO can you suggest how I should use my layout?
You can change the layout for all actions in a controller with the following code:
class ThingsController < ApplicationController
layout "my_layout"
...
end
You can change the layout for a specific action using the following code:
def ThingsController < ApplicationController
def action
...
# to render "app/views/things/action"
render :layout => "my_layout"
# or to render a specific view
render "pages/something", :layout => "my_layout"
end
end
If I got it right you are asking about how to manage multiple layouts for your project. What you could do is simply adding your layouts inside the layout directory and by referencing the one you want to use by adding this line to the controller:
layout "name_of_your_layout"

Resources