Rails - Abstract/Shared Views

2019-08-26 09:25发布

I have a few objects that are incredibly similar. In fact, they use STI and store all of the data in the same table in the DB. Currently, every time I add a feature or fix a bug, I have to update it in 3 different places, so I would like to DRY my code a little bit. The most common code duplication is in the views. I have seen people using render :template => 'shared/something' to render their common views, the problem is, I have many of these, but only for one particular object (Shipments), so I would prefer something like render :template => 'shipments/shared/something' or render :template => 'abstract_shipments/something'. More importantly though, I would like any of the actual classes to be able to override the template if it needs to.

Do y'all have any suggestions on how to go about this? Thanks very much for any answers!

2条回答
女痞
2楼-- · 2019-08-26 10:01

The inherit_views plugin might do the job: http://github.com/ianwhite/inherit_views/tree/master. I've used it successfully before.

You could then have a common base controller class for all controllers needing to render shipments and have any common templates in that base controller's views folder with any specific overrides in the individual controllers' views folders.

查看更多
萌系小妹纸
3楼-- · 2019-08-26 10:06

Classes (models at least) don't - or shouldn't - know anything about how they're displayed. That's fundamental to the separation of concerns provided by the MVC pattern.

I think I'd try something like this:

Use a single controller for all the STI models, ShipmentsController or something similar. Apart from it seeming a logical thing to do, all your views will end up in the same place, which ought to help.

As for views, how about a "main" one for the common parts, and one partial for each set of subclass-specific fields? Use a case in your view, or probably more cleanly, a helper method, something like

def partial_name_for_subclass(obj)
  if obj.is_a?(CrudeOilShipment) # or kind_of? or test the type column or use respond_to?
    'crude_oil_shipment'
  # etc
  end
end

DRYer, consider using a convention (Rails loves conventions):

<%= render :partial => @shipment.class.name.downcase, :locals => { :item => @shipment } %>

where you have a partial for each subclass.

Hope some of that helps/makes sense...

查看更多
登录 后发表回答