Multiple Layouts in One Ruby on Rails Site - ruby-on-rails

I have a website that is already up and running. I would like to add a new page on my Ruby on rails Website and would like to make the page look completely different.
Different Layout, Different Theme, Everything.
I have created a new scaffold for these pages. but am unsure how to achieve the desired results.

You can create the assets for your theme to make the page look completely different. Rails uses the default app layout at app/views/layouts/application.html.erb
However, you can create another layout with your theme and render the view using:
render layout: "<your-layout-name>"

For different ways to render different layouts, you can also refer to this railscast
Yes, you can do this by passing some params from controller action and checking in application.html.erb
Suppose you have users_controller and home as controller action as your root path
Then in users controller
def home
params.store(:diff_page, true)
end
In application.html.erb
In your application content is the id for main div inside body then
#content{:class => (params[:diff_page] ? "back-black" : "back-gradient")}
back-black and back-gradient both are css classes which you can define different style and page, background image anything you want
You can also call different partial too, based on params
- if params[:diff_page]
= render :partial => 'users/new_page'
- else
= render :partial => "layouts/page"

We do this on one of the sites i help manage: we have two completely different domains, each of which with its own totally unique look and feel, running off the same rails app. The second domain is called "cmw" within our project structure, and is set up as follows.
routes
You can put a condition on routes which looks at the request domain, and only runs that route if the domain matches the condition. So, we put all the cmw routes at the top of the routes file, all with the same condition. Then, underneath, the regular site routes. When we get a request to "cmwdomain.com", it will trigger one of the cmw routes. Requests to "maindomain.com" will fall through all the cmw routes, because they have the condition, which fails for this domain, and hit one of the routes below which are for the main site.
eg
#################### START OF CMW ROUTES: ALL HAVE A CONDITION ON THEM TO DIFFERENTIATE THEM FROM REGULAR ROUTES ###############
cmw = { :host => CMW_HOST_REGEX }
map.resources :licenses, :controller => "cmw/licenses", :conditions => cmw
map.resources :users, :controller => "cmw/users", :conditions => cmw
#REGULAR ROUTES
map.resources :licenses, :controller => "licenses"
map.resources :users, :controller => "users"
controllers
The above system sends all of the cmw requests through to controllers in the app/controllers/cmw folder. Normally, all controllers would extend ApplicationController. In our case, we have a CmwController which extends ApplicationController, and is kind of like the CMW-specific version of ApplicationController. This has its own default layout and various protected methods and helpers which are specific to the cmw site. Then, all the cmw controllers extend CmwController instead of ApplicationController.
views
To match the views to controllers, we have a folder app/views/cmw where all of the different cmw controllers' corresponding view folders live.
This system is nice and clean. The second "cmw" site has its own routes, controllers and views, but accesses the same models and database as the main site: two faces of the same app.

Related

In Rails, won't url_for pick up the route from the routes file?

I have a situation where there are lots of models and I am using STI in rails to help minimize the creation of so many models that share similar attributes.
However, I am trying to dynamically generate routes without having to duplicate controller logic.
I am using url_for(controller: controller_name, action: :show) or whatever the url should be. However, I would simply like these routes to be listed in the routes file and not have to create controller files for each. But looks like url_for expects the actual controller file to be created. Otherwise, it would generate the wrong url (its generating some auth/failure url, which, I have no idea why it is doing). How can I make it pick up the route in the routes file and not have a separate controller file?
I would take a look at Rails Routing and become familiar with resources.
I believe you could use the one controller for the different models. So in your routes.rb:
resources :sti_model1, :controller => 'sti_controller'
resources :sti_model2, :controller => 'sti_controller'
resources :sti_model3, :controller => 'sti_controller'

Rails controller and routes configuration for website

I have an application in RAILS, it is composed of a set of API, a basic website, and an admin dashboard.
For the API routing I have no problems, as they belong to a model and a controller and are compliant with the RAILS RESTful pattern (a controller for each model, and a method for each HTTP method).
What I'm not comfortable with is writing routes and controllers for website.
The main website is at / so the default route is root :to => "home#index"and I have
Routes for the website pages which look like
get "home/index"
get "map/index"
get "api/index"
get "cgu/index"
get "legal/index"
Which I think it is not good, as I have a controller per view and I need to define a get for each views.
Now for the dashboard I tried a different approach.
It is at /dashboard, the default route is match "dashboard" => "dashboard#index" and here is few pages as an examples
get "dashboard/index"
get "dashboard/users"
get "dashboard/users_stats"
get "dashboard/routes"
get "dashboard/routes_stats"
get "dashboard/charts"
get "dashboard/financial"
So for the dashboard I have a massive dashboard_controller, which contains a def method for each dashboard pages. IE:
#dashboard/users
def users
#users = User.all
respond_to do |format|
format.html {render :layout => 'dashboard'}
end
end
the controller of the dashboard is at /controller but for views and assets I have put it in /folder/dashboard/
Here is 2 questions:
What is the best way to build the home website and dashboard ? Should I have a controller per page or a global controller where I have a method per pages ? (Which I find very convenient, less code).
How should I organize my routes to avoid to set a get "something/something" for each page ?
Or it is normal with RAILS that I have a route defined for each of my page ? I'm fairly new.
EDIT:
To clarify, the dashboard is built around an existing application with API that follow RESTFul Rails pattern:
resources :users
resources :routes
But the dashboard is not tied to any existing resources, it only do stats about those resources.
If you have custom controller action names, then yes, you'll need to define every route. If you use Restful routes, then you can define them easily as
resources :users
which will automatically create routes for actions: index, show, edit, update, create and destroy.
This might be helpful: http://guides.rubyonrails.org/routing.html
For your dashboard, which probably is bringing together a lot of resources, so they'll probably be custom methods. I'd suggest focusing on building your app by individual resource. Then, once you've defined them all, build your dashboard.
I agree with everything that other people have said here. You should definitely try to be more RESTful and create more routes like this:
resources :users
However, there is usually a controller that is not RESTful (usually called pages or static) that serves pages such as Privacy, About Us, etc, etc. For those routes, I usually do this:
['api', 'privacy', 'us'].each do |p|
get p, :controller => 'pages', :action => p
end
check this guide out if you haven't;
I think you haven't embraced the MVC concept of Rails.
For example, say you have "users". You should have users_controller.rb, users.rb (model), /views/users (view) under the app directory.
users_controller contains the index, show, create, etc default actions and your custom actions like stats
user.rb contains instance/static/helper methods
/views/users/ contains templates that corresponds to actions in the controller.

rails controller action routing

I'm looking to "automatically" generate routes based on actions defined in a controller. resources routing (as far as I know) only automatically generates routes & helpers for http verbs. In this instance I'm serving mostly static pages using rails and have no need for http verbs in my controller.
Specifically:
In a controller I have defined actions which refer to those mostly static pages.
def action
end
In the routes file I have a bunch of
match "/url" => 'controller#action'
I'd like all those matched routes to be generated automatically based on the actions in the controller. Something CONCEPTUALLY along the lines of:
for actions in controller.erb do |action|
'match "/action" => "controller#action"
end
Is this possible? Would I write the code in the routes file directly?
I also have some nested actions to consider... a controller action may be:
def action
def nested_action
end
end
I'd appreciate any thoughts on this matter. Thanks.
What's wrong with the normal /:controller/:action idea?
That won't deal with nested actions, but... I'm having a difficult time understanding why you'd ever want that.
You can do something like this:
controller :controller_name do
get "path/action" => :method_name, :as => :path_action
post "path/save" => :method_name, :as => :path_save
end
That is, you can group different routes within a controller using the method above.

Rails3: Appropriate use of routing and resources

I've recently joined the world of Rails app development (Rails3) and I may be abusing resourceful routing.
The default resourceful routing makes some really convenient helper methods for the URLs which I use constantly. My problem is that I have controllers that I specified the routing as resourceful simply to take advantage of those helper methods. I have some basic site navigation that has no business with resources.
resource :home do
member do
get 'main'
get 'about'
get 'login'
get 'help'
end
end
Is there a better way to do what I've been doing? Anything that doesn't require that I manually add routing entries each time I have a new controller action?
Just to clarify, I want to specify routing for a controller without having to explicitly add any new actions but I also want it to auto-generate helper methods. So far, I have to explicitly add routes for each action I want that for. I can get something similar by doing this (in a non-resourceful way),
match 'home/about' => 'home#about'
But I don't want to have to write that very every route that doesn't fall into the convention.
Here's another simpler one. Just add a generic route to the bottom of your routes.rb
match ":controller/:action"
and it will map directly to the specified action of the specified controller. You can be a bit more specific if you like. For example, using get instead of match to restrict to HTTP GET requests, specifying the applicaple controllers etc.
get ":controller/:action", :constraints => { :controller => /home|help/ }
You can look into your controller for public instance methods and generate routes automatically.
# routes.rb
HomeController.public_instance_methods(false).select{|m| !(m.to_s =~ /^_/)}.each do |m|
match "home/#{m}", :action => m, :controller => HomeController, :as => "home_#{m}"
end
This will take the explicit(non-inherited) public instance methods from your controller, and select the ones that don't begin with an underscore(because underscored ones are generated methods for filters, the rest are actual actions). Then it will generate a named route for each.
Keep in mind that routes.rb is processed only at server startup so you will have to restart the server after you add new actions.

rails restful routing - single index with nesting

I'm working on a rails application which is built around a tree data structure. As such, the index of the controller displays the root node of said structure. Demonstration is probably easier to explain what I want:
/place/1 == place
can I restfully define such that
/place/1/photos == place/photos
and
/place/1/photos/1 == place/photos/1
etc?
Ideally what I'd like is that the articles url and its nested resource urls work by default such that I don't need to change a whole bunch of stuff and conditionally generate paths all over the place.
Thanks in advance for any help. :)
You could have the usual nested restful routes (it's good to keep them as the baseline, and to use them for the non-sexy urls like update, create, etc) and then add some custom routes for your 'pretty' urls:
map.nested_photo "/place/photos/:id", :controller => "photos", :action => "show"
map.edit_nested_photo "/place/photos/:id/edit", :controller => "photos", :action => "edit"
you could then add a bit of logic into the photos controller to make sure you have the place even if you didn't get params[:place_id], eg
if params[:place_id]
#place = Place.find(params[:place_id])
else
#place = #photo.place
end
The main thing to watch out for in custom urls is that you don't create any conflict with a) the regular restful urls or b) your other custom urls.

Resources