开发者

Automatically add parent model id in nested resources

With nested resource routes in Rails 3, such as the following:

resources :magazines do
  resources :开发者_JAVA技巧ads
end

helpers such as magazine_ad_path are defined, to which I have to pass both a magazine and the ad, which is inconvenient if I just have a reference to the ad:

magazine_ad_path(@ad.magazine, @ad)

Is there a nice way to set up an ad_path helper that takes the @ad and returns the appropriate address including the magazine ID? (This would also then allow the use of link_to @ad, redirect_to @ad, etc., which automatically call the ad_path helper corresponding to the model class.)


Shallow Routing seems to be what you're looking for. You can implement shallow nesting as below :

resources :magazines do
  shallow do
    resources :ads
  end
end

OR

resources :magazines, :shallow => true do
  resources :ads
end

Only the index and the new actions are nested.

Using nested resources tends to generate long URLs, shallow nesting helps remove parts (that contain the parent resource route as well) that aren't necessarily required for certain actions(since a parent resource can be derived from a persisted child record).


One possible but ugly solution is:

module RoutesHelper
  def ad_path(ad)
    magazine_ad_path(ad.magazine, ad)
  end

  def ad_url(ad)
    magazine_ad_url(ad.magazine, ad)
  end

  def edit_ad_path(ad)
    edit_magazine_ad_path(ad.magazine, ad)
  end

  def edit_ad_url(ad)
    edit_magazine_ad_url(ad.magazine, ad)
  end

  ...
end

[ActionView::Base, ActionController::Base].each do |m|
  m.module_eval { include RoutesHelper }
end

Unfortunately, this has the disadvantage that I have to define different helpers for _path and _url because redirect_to uses the _url helpers, I have to write the edit_ helpers manually (and maybe I'm missing some; not sure on that), and it's just plain ugly.


One solution i like to use in this case is to make the instance returning his own path, like this:

class Ad
  def path action=nil
    [action, magazine, self]
  end
end

Then in your view you can use this array as a polymorphic route:

link_to @ad.path
link_to @ad.path(:edit)

Of course it also work with redirect_to, etc

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜