查找嵌套或非嵌套资源的路径

时间:2012-05-25 02:31:51

标签: ruby-on-rails ruby-on-rails-3 activerecord routes

在Rails 3.2中工作,我是一个多态订阅模型,其subscribable_type可能是也可能不是嵌套资源。我正在尝试在电子邮件视图中显示完整的URL链接,但不知道该资源是否嵌套。

当我在嵌套资源上尝试url_for @model时,它会失败,期待url_for [@parent, @model]。不幸的是,我不知道如何发现Routes表中定义的父级。

有没有办法识别嵌套资源的路径路径?如果我可以将模型与路线匹配,我可以填写必要的ID。

截至目前,我已经在我的模型中定义了一个名为parent_resource :model的方法,可以遍历,但我希望有更好的方法。

在我的routes.draw

  resources :projects do
    resources :topics do
      resources :comments
    end
  end

  resources :subscriptions

(我意识到我不应该如此深深地筑巢)

修改:其他信息

我的订阅模型是我用来管理通知的资源。可订阅类型提供了一个链接,用于在该subscribable_type / subscribable_id上​​打开或关闭该用户的订阅。

然后我通过提供订阅实例的Notifier < ActionMailer::Base,并邮寄用户。

通过该设置,我正在尝试获取subscription.subscribable的完整网址,这可能是主题或项目。

我意识到我可以通过辅助方法来解决这个小案例中的条件,但我很想知道如果有几十个嵌套模型对会如何处理这个问题。

2 个答案:

答案 0 :(得分:0)

您提到订阅但您的路线完全不同。我猜你给的路线只是一个例子。我将首先尝试摆脱您创建的自定义parent_resource方法。你可以通过添加belongs_to来更简单地做同样的事情,如果你需要的话可能还有条件:

belongs_to :projects, :through => :topics, :conditions => ['whatever your conditions are']

我有一种每父类型,所以我可以这样做:

object.project.present? 

从那里我可以很容易地知道它是否嵌套,并通过让rails进行父遍历来简化事情。这应该简化到足以让你至少可以轻松找出你的订阅类型的地方。接下来,我可能会添加一些匹配的路线或尝试填写:as =&gt; 'somename'进入我的路线,所以我可以在确定嵌套部分后直接调用它们。一种选择是这样的:

match "projects/subscription/:id" => "projects#subscription", :as => :project_subscription
match "other/subscription/:id" => "other#subscription", :as => :other_subscription

所以很明显,你可以通过以下方式指定你想要的网址:

if @object.project.present? 
  project_subscription_path(@object)
else
  other_subscription_path(@object)
end

答案 1 :(得分:0)

这可能不是完成我正在做的事情的最好方法,但这对我现在很有用。

这将从最短的有效路由助手中构建一个嵌套的资源数组,并生成一个URL:

(在rails console中测试)

resource = Comment.first
resource_name = resource.class.to_s.downcase 

helper = Rails.application.routes.named_routes.helpers.grep(/.*#{resource_name}_path$/).first.to_s.split('_')
built = helper.slice!(-2,2) # Shortest possible valid helper, "comment_path"

while !(app.respond_to?(built.join("_").to_sym)) 
  built.unshift helper.pop
end

built.pop # Get rid of "path"
resources = built.reverse.reduce([]) { |memo, name| 
  if name == resource_name
    memo << resource
  else
    memo <<  memo.last.send(name.to_sym) # comment.topic, or topic.project (depends on belongs_to)
  end
}
resources.reverse!

app.polymorphic_url(resources) # "http://www.example.com/projects/1/topics/1/comments/1"