Best way to create views based on a theme - ruby-on-rails

I need to create separate view pages for a controller that I have.
I have a CustomerController that, based on the customer I need to create custom pages, these pages have to be stored as a file not from the db.
So normally I would have this:
class CustomerController < ApplicationController
def show
#customer = Customer.find(param["id"])
end
end
And the views would be located at:
/views/customer/show.html.erb
What I want to do is have the view pages like:
/views/customer/1/show.html.erb
/views/customer/2/show.html.erb
/views/customer/3/show.html.erb
How can I reference the specific view pages to load from within the action?
Is there a way to just pass the value 1,2,3 to the view folder path?

You can specify a template to render in the show action. Rails, without you explicitly calling render, will render the template that corresponds to that specific action...so, in your case, it will automatically render customers/show.html.erb (Note: Your controller should be plural...ie CustomersController, not CustomerController)
To override this, you can do something like this
def show
#customer = Customer.find(params[:id])
render "customers/#{#customer.id}/show.html.erb"
end

Related

Rails how to render partial with data form database

i have a view called week.haml and a controller action called def week in which I get all my todos for this week. I want to render a partial called _events.haml inside week.haml which displays all events that week.
I did it like this:
inside week.haml:
= render partial: 'events`
inside _events.haml
%p= 'Events this week:'
#events.each do |event|
# stuff to show events
end
inside the todo controller:
def events
#events = Event.where(some query)
end
But i always get the error message #events not defined. How can i load events into the event partial? and i don't want to do it inside def week if possible...
I also created a route:
resources :todo do
get 'events', action: :events, as: :events
end
The week.haml file works fine, just the partial doesn't work.
It is bad practice to use instance variables in partials, pass locals instead. Instance variables are for views
In your week view
= render partial: 'events`, events: week.events
And in partial _events
events.each do |event|
# stuff to show events
end
If you're in the controller action week, you'll need to get the events there or share #events between the different controller actions. If you're in the same scope (same controller in this case), you could create a private method for getting data that's similar between different views.
class TodoController < ApplicationController
before_action :get_events, only: [:week, :events]
def week
# Stuff for the week view
end
def events
# Stuff for the events view
end
private
def get_events
#events = Event.where(...)
end
end
In this example, the #events variable is available for both actions week and events. The before_action at the top runs get_events to load the #events variable before executing any other code in the controller action. Since it's an instance variable, it can be shared between different methods in the same class. Calling get_events at the top of both week and events would achieve the same result, but a before_action is usually cleaner IMO.
And just to be clear, all of this is assuming that you have separate views events.haml and week.haml. If not, creating a route and a controller method with the name of the partial does nothing. Just load the events in the week controller action and you're good to go! You could essentially think of a controller method as corresponding to a single view (of the same name usually), and a partial is just an extension of that view (and any other views that use the same partial). You load any data you might need for the view or any of its partials in the controller action, and then share whatever's needed with the partial. Instance variables (starting with "#") are shared automatically, but anything else you would need to pass to the partial explicitly.
Partials are meant for things you need to render multiple times (and/or in multiple places). The Rails docs have a pretty thorough section about them. If you're only rendering events for a single week in week.haml, you probably don't even need the partial, unless you want to use it in other views.

Calling 2 different views in controller rails

I have 2 versions of the same pages in my rails app and I would like for them to alternately load when the same page is called.
So for example: On page load index view comes up. On reload or refresh the alt_index page loads. How can I accomplish this? I am sure it can be accomplished in a controller action but not sure how.
class ComingSoonController < ApplicationController
def index
render('alt_index' || 'index')
end
end
This only renders the alt_index page I need it to alternate.
I suggest that you randomly select one of the templates to render with Array#sample instead of trying to alternate between them:
render ['alt_index', 'index'].sample

Calling REST index action from Dashboard

Hello Everyone I have a model 'Project' in my rails application which is a REST resource.
I also have a non REST controller 'home' with a method 'dashboard'.
I want the dashboard to render all the Projects. This means, I need to call index action on Project. There are two ways I can think of for doing this:
1.
Have a link_to to Project#Index in my dashbaord template, then as both
dashboard and Index share same layout, user can see list of Projects.
However this needs an extra click.
2.
As all other view elements for Dashboard lie in the layout file, I
could manually set the #projects instance in dashboard action and
render the index template.
This also looks like a wrong way to approach things.
What I have two models 'Project' and say 'Cookie' and I want to list them all in my dashboard? How to go about implementing it in the neatest way possible?
class HomeController < ApplicationController
def dashboard
#projects = Project.all
#cookies = Cookie.all
end
end
In your views/home/dashboard you represent those collections as you need.
If you have a partial in your views/projects/ directory, that is currently used within the projects index action to render the project collection, then you can use that view in your dashboard by calling something like:
<%= render partial: 'projects/list', locals: { projects: #projects } %>
Sounds like in your ProjectController's dashboard method you should be calling something like
projects = Project.find_all
then rendering projects in your corresponding view.

Groupon Alert Rails

I am new to rails so please be patient. I am open to suggestions on how to do this differently.
I would like to render 2 separate controller actions in one layout in rails.
I have 2 controllers: Coupons, and MainAlert. In the body of my application wide layout page I have a <yield > which loads the index action of Coupons or MainAlerts depending on the request (e.i. localhost/coupons or localhost/MainAlerts).
However, I would like to load the index action of Coupons or MainAlert or other controller (depending on request) but ALWAYS load the _form(where user creates new alert) at the very top on a I will hide and show.
"Get deals by email (+)" option at groupon.com
How do I load both controller action (index from Coupons and the _form (new? create?) from MainAlerts in the layout. The values of the MainAlert form need to be save to the DB if user hits submit.
I am open to suggestions on how to do this differently.
Thank you for you time everyone. =)
I'm kind of a newbie too, so expect more nifty answers.
But one way to solve this would be to use an before_filter in the Application Controller to always set up a new MainCoupon instance variable as every action is serviced. After that you could use render 'maincoupon/form' to render the form in the layout. The form should work as intended because the need instance variable was set up by the before_filter.
It could look something like this:
# application_controller.rb
class ApplicationController < ActionController::Base
# other stuff
before_filter :new_coupon
# other stuff
def new_coupon
#maincoupon = MainCoupon.new
end
end
In the layout you could have
<% = render 'maincoupons/form' %>
Or better yet, using HAML, just:
= render 'maincoupons/form'
In general your new action is associated with a view where the user enters information into a form. The new action in the controller creates a new object #maincoupon = MainCoupon.new of the desired to type, which is used as a "scaffold" for building the form.
When the user submits, the form information is packaged sent as a parameter to the create action, which takes the information sent from the form and uses it to create a new object of the desired type.
#maincoupon = MainCoupon.new(params[:maincoupon])
After that it uses the #maincoupon.save method to save it the to the database.
You can try the corresponding model methods out yourself in the console (rails console).
For example:
> A = User.new
Would create a new user, but doesn't save it to the db.
You could continue like this:
> A.name = "Apa"
> A.save
This will create and save it straight away.
> User.create(:name => "Apa")

Ruby on Rails - How to manage layouts in admin interface?

I have a very simple site setup using awesome_nested_set and a single table called Pages.
I would like the ability to select different layouts in the admin when creating and updating Pages. What I envisioned is a drop down on the Pages form that allowed me to select a layout/template.
The only thing I know about layouts is you are required to add them to /views/layouts/ and specify the layout at the top of the controller. I need a way to manage layouts on a per Page basis inside the app itself.
Is that even possible? If so, can you explain on a high level how that might be done so I can have a starting point?
edit
Something like this:
You can easily change the layout at render by supplying the :layout key like so:
def some_action
#... stuff
render "some_action", :layout => "custom_layout"
end
You can also set layout to a symbol in the controller definition, and the controller will run the associated method to decide what layout to choose
class UsersController < ApplicationController
layout :decide_layout
private
def decide_layout
some_boolean ? "layout1" : "layout2"
end
end
You can also replace the symbol with a proc if you don't want the method located away from the usage. Finally, you can also call #layout in an action itself.
Assuming you have files in views/layouts called something like one_column.html.erb, two_column.html.erb, etc., and an attribute called layout on you page model, you could just do:
def show
#page = Page.find(params[:id])
render :action => "show", :layout => #page.layout
end
Is that what you're looking for?

Resources