2012-05-25 62 views
1

在Rails 3.2中工作,我是一个多形的Subscription模型,其subscribable_type可能是嵌套资源,也可能不是嵌套资源。我试图在电子邮件视图中显示完整的URL链接,但不知道该资源是否嵌套。查找嵌套或非嵌套资源的路径

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

有没有一种方法来确定嵌套资源的路径路径?如果我可以将模型匹配到路线,我可以填写必要的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的完整网址,这可能是主题或项目。

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

+0

你能也将从路由添加相关的部分文件? – zsquare

+0

当然,马上就来。 – Dan

回答

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" 
0

你提到订阅,但你的路线是完全不同的。我猜你的路线只是一个例子。我会开始尝试摆脱您创建的自定义parent_resource方法。你也许可以做同样的事情更简单的通过,并可能与条件添加belongs_to的,如果你需要太:

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

我有那些父母每一种类型的,所以我可以做这样的事情:

object.project.present? 

从那里我可以很容易地知道它的嵌套与否,并通过让rails进行父级遍历来简化事情。这应该使事情足够简化,以至于你至少能够很容易地弄清楚什么类型的订阅。接下来,我可能会添加一些匹配的路线或尝试将a:as =>'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 
+0

谢谢。我已经进一步澄清了我的问题。我正在寻找更多的知道如何通常找到父代,而不是显式命名父代的类名,即'@ object.project'。 – Dan

+0

我知道路由系统可以将多个路径路由到单个控制器,所以我明白为什么没有直接的方法来做到这一点。但是,我仍然想知道是否有方法通过ActionDispatch :: Route中的名称来识别路由,并且构建它?还是让事情比需要更复杂? – Dan