DRYing up Rails Views with Nested Resources
What is your solution to the problem if you have a model that is both not-nested and nested, such as products:
a "Product" can belong_to say an "Event", and a Product can also just be independent.
This means I can have routes like this:
map.resources :products # /products
map.resources :events do |event|
event.resources :products # /events/1/products
end
How do you handle that in your views proper开发者_运维问答ly?
Note: this is for an admin panel. I want to be able to have a "Create Event" page, with a side panel for creating tickets (Product), forms, and checking who's rsvp'd. So you'd click on the "Event Tickets" side panel button, and it'd take you to /events/my-new-event/tickets
. But there's also a root "Products" tab for the admin panel, which could list tickets and other random products. The 'tickets' and 'products' views look 90% the same, but the tickets will have some info about the event it belongs to.
It seems like I'd have to have views like this:
- products/index.haml
- products/show.haml
- events/products/index.haml
- events/products/show.haml
But that doesn't seem DRY. Or I could have conditionals checking to see if the product had an Event (@product.event.nil?
), but then the views would be hard to understand.
How do you deal with these situations?
Thanks so much.
I recommend you to make separate admin controller with it's own views to administrate everything you want. And your customer's logic stayed in products contoller.
I don't have good and clean solution for this problem. Usualy if views doesn't differ to much, I use single view and add some code like @product.event.nil?
. You can always add some variable, or helper that will make this method shorter, on example has_event?
- then your view will look cleaner. And use it in code like this:
<% if has_event? %>
some html
<% end %>
or for single line:
<%= link_to 'Something special', foo_path if has_event? %>
On the other side, you can create few partials that are the same for both views, put them in some folder, on example /shared/products/...
and render them from your views like this:
<%= render :partial => '/shared/products/info' %>
and so on.
But if they don't differ too much, I really would use if
version.
The views will be handled by the ProductsController
. You can alter the logic in your controller depending on the nesting of the resource.
# app/controller/products_controller.rb
# ...some code...
def index
@event = Event.find_by_id(params[:event_id]) if params[:event_id]
@products = @event ? @event.products : Product.all
end
The view will be handled by the usual product view
# app/views/products/index.html.haml
- unless @products.blank?
- @products.each do |product|
%p= product.some_attribute
精彩评论