开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜