2016-05-13 42 views
1

我有一个多对多的多态的关系:提取params哈希表相关模型

class DocumentTask < ActiveRecord::Base 
    belongs_to :task 
    belongs_to :document, polymorphic: true 
end 

class Task < ActiveRecord::Base 
    has_many :documents, through: :document_tasks 
end 

class Contact < ActiveRecord::Base 
    has_many :tasks, though: :document_tasks, as: :document  
end 

class Service < ActiveRecord::Base 
    has_many :tasks, through: :document_tasks, as: :document 
end 

我有一个看起来像这样的将信息发送到服务器的URL:

/contacts/1/tasks?status_id_is=1&user_id_is=1 

但有时它可以看起来像这样(因为存在多态关系):

/services/1/tasks?status_id_is=1&user_id_is=1 

在我的控制中r,我需要获得多态关系的对象。通常情况下,我可以做到以下几点:

document_id = params.detect {|name,_| name =~ /(.+)_id/} 
@document = document_id[0].gsub("_id","").capitalize.constantize.find(document_id[1]) 

然而,当URL包含查询字符串,这将无法工作,因为status_id_is和user_id_is将匹配正则表达式。一个明显的解决方案是将正则表达式更改为/^(.+)_id$/,但谁知道可能会出现多少其他用例。

有没有一种很好的方式来实现我想要的?例如,请求对象中的某些内容如request.association_parameterparams.association_parameter

+0

什么是'status_id_is'和'user_id_is'?它们是指“文档”对象的'status_id'和'user_id'属性?等价地,我在问是否所有的Task,Contact和Service模型都有'status_id'和'user_id'属性,您打算使用这些参数进行过滤。 –

+0

status_id_is和user_id_is只是与任务相关的过滤器参数。它们与文档无关。没有一个模型具有status_id或user_id属性。同时,我希望有一个灵活的解决方案,不会轻易打破。一个便宜的解决方案是使用像/^(.+)_id$/这样的正则表达式,但是谁知道呢,它可能会在以后的某个时候中断。 – Donato

+0

我还没见过'.detect'在{}块中有两个参数。它有什么作用?只是这样我才能理解代码试图做什么。 –

回答

0

对于集合上的过滤 - 像搜索或参数你必须过滤任务 - 我可以建议一种替代方法,它将使用params[:q]来代替过滤。

这与“一些”约定API过滤,像ransack(GEM)和ElasticSearch如何使用qquery PARAMS,这是作用域的包装PARAM线。

等价的,如果采取这一方式,你会像下面

/contacts/1/tasks?q[status_id_is]=1&q[user_id_is]=1 

这样,你现在在你的params.detect因为status_id_isuser_id_is将里面PARAMS循环没有问题[:Q]并因此在散列中更深入一级,其中params.detect循环将不再考虑。因此任何MODEL_id参数都适用于多态路由。

+0

这看起来不错。 – Donato

+0

您提到了“API过滤的约定”。这些约定是否记录在任何地方?如使用:q? – Donato

+0

哦,你说得对,从技术上说,我应该说,“他们”使用像“q”或“查询”这样的param包装的惯例。我还没有看过它,如果使用包装器参数实际上是一个过滤惯例。如果有人知道或发现,请通知我满足我的好奇心。 –