I have two layout:
Dashboard (Where logged user can Add/EDIT/Delete new Post)
Public view (where anybody can read Posts)
I would like to get urls like:
dashboard_post_path and
post_path
but I don't want to have two different controllers (eg. PostController and DashboardPostController), because I want to share the same code and switch only the layout ('dashboard' layout OR 'default' layout).
I've tried this
namespace :dashboard do
resources :posts
end
but I get
because it looks for dashboard/posts#index controller
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:edit, :update, :destroy, :new]
layout 'dashboard'
//...
end
You can write conditional layout like below
Conditional Layouts
Layouts specified at the controller level support the :only and :except options. These options take either a method name, or an array of method names, corresponding to method names within the controller:
class EventsController < ApplicationController
layout :resolve_layout
def resolve_layout
case action_name
when "show"
"post_layout"
when "index"
"dashboard_layout"
else
"default_layout"
end
end
end
Are you looking something like this?
Related
I have a controller with the default RESTful route actions (index new create show edit update destroy) and also several other actions. I want to set a before_action that only runs on the default routes.
I know I can add before_action :set_x, only: [:index, :new, :create, :show, :edit, :update, :destroy] to the top of the controller but is there a quicker way to do this? I'd like to do this for multiple controllers, so I cannot do before_action :set_x, except: [:foo, :bar, :baz] because the actions change in each controller and new actions are added all the time.
Thanks!
Options:
define the before_action in the ApplicationController
write skip_before_action in those controllers that do not need it
define another "controller"-class, that derives from ApplicationController, add the before_action and only those controllers that need it, will inherit from that class
create a module with only the before_action and include it
I'm working on an app with controller that have lots of before_actions. Most of them are connected with each other by instance variables that they set. For example:
def first_action
#first_variable = Something.new
end
def second_action
if #first_variable
#second_variable = Other.new
end
end
Controller looks like this:
class ExampleController < ApplicationController
before_action :first_action, only: [:index, :show, :create]
before_action :second_action, only: [:index, :show, :create]
before_action :third_action, only: [:index, :show, :create]
before_action :fourth_action, only: [:index, :show, :create]
before_action :fifth_action, only: [:index, :show, :create]
before_action :sixth_action, only: [:index, :show, :create]
before_action :seventh_action, only: [:index, :show, :create]
def index
# some code
end
def show
# some code
end
def create
# some code
end
private
# all of the before_action methods
end
It's really hard to understand from mine point of view. Each of those method has lots of code. Additionaly there are controllers that inherits from this one and also use part or all of those actions.
I heard that it's better to be explicit about loaded variables in each method but this:
class ExampleController < ApplicationController
def index
first_action
second_action
third_action
fourth_action
fifth_action
sixth_action
seventh_action
# some code
end
def show
first_action
second_action
third_action
fourth_action
fifth_action
sixth_action
seventh_action
# some code
end
def create
first_action
second_action
third_action
fourth_action
fifth_action
sixth_action
seventh_action
# some code
end
private
# all of the before_action methods
end
doesn't look much better. Is there a way to refactor it for more readability or should I stick with current solution?
Your current solution is okay. You can use like to avoid multiple method calls
before_action :first_action, :second_action, :third_action, :fourth_action, :fifth_action, :sixth_action, :seventh_action, only: [:index, :show, :create]
There is nothing wrong with having multiple before_actions - but it looks more like you have a case where they could be collected into one action?
Say I have a module name Server that was created with a scaffold. I want the url 'www.example.com/server/' to be redirected to the first Server object that exists. So for example to be redirected to 'www.example.com/server/2'.
How could this be done with routes.rb (or any other way)?
route.rb:
Rails.application.routes.draw do
resources :servers
end
Server controller:
class ServersController < ApplicationController
before_action :set_server, only: [:show, :edit, :update, :destroy]
# GET /servers
# GET /servers.json
def index
#servers = Server.all
end
....
your can put
redirect_to server_path(Server.first) and return
inside your index method it'll redirect you when ever index action is called.
and just to extent #richfisher's answer (which might be a more appropriate way to do it.)
resources :servers, except: [:index] # this won't generate redundant routes
get '/servers/' => 'servers#first' #note this is now accessible via "server_path" instead of "servers_path" helper.
For what it's worth, I'd do this:
#config/routes.rb
resources :servers, except: :index do
get "", action: :show, id: Server.first.id, on: :collection
end
This will allow you to use the show action in place of index in a super efficient setup:
#app/controllers/servers_controller.rb
class ServersController < ApplicationController
def show
#server = Server.find params[:id]
end
end
I have installed devise and would like to restrict access to certain pages depending on whether the user has authenticated.
My first approach was to open each view, and add:
<% if mpuser_signed_in? %>
#rest of code
<%end>
(My model is called mpusers)
But I thought there maybe is a more elegant solution?
Dario
Set before_filter :authenticate_user! in the controller for the actions that require an authenticated user. In this example, we need the user to be authenticated for creation, edit and destroy actions.
class YourController < ApplicationController
before_filter :authenticate_user!, only: [:new, :edit, :update, :destroy]
I am new to Rails and I need to create a simple Rails project with these conditions:
there must be page with some articles (title + body)
anyone can read those articles
only authenticated users can create/edit/delete those articles
I used scaffold to generate a controller for articles and the gem Devise to create the authentication system. But I dont know how to implement the necessary conditions.
Thanks for the reply.
If your user model is called user, then you would include the following in your controller:
before_filter :authenticate_user!
If it not called user, you would replace the word user in authenticate_user with whatever it is.
You would add this directly under your controller declaration, like so:
class ArticlesController < ApplicationController
before_filter :authenticate_user!
#rest of code
end
If you want to restrict only certain actions in the controller to logged in users, you can use except to exclude some actions. Here, index and show can be seen by anyone:
before_filter :authenticate_user!, :except => [:index, :show]
or only to include specific actions. Here, only authenticated users can do the listed actions:
before_filter :authenticate_user!,
:only => [:new, :edit, :create, :update, :delete]