假设我有一个具有一个Foo和多个Bars的模型Item。
Foo和Bar可以在搜索项目时用作参数,因此可以像这样搜索项目:
www.example.com/search?foo=foovalue&bar[]=barvalue1&bar[]=barvalue2
我需要生成一个能够保存这些搜索参数的Query
对象。我需要以下关系:
我现在建立了这种关系:
class Query < ActiveRecord::Base
belongs_to :foo
has_and_belongs_to_many :bars
...
end
Query还有一个方法,它返回一个这样的哈希:{ foo: 'foovalue', bars: [ 'barvalue1', 'barvalue2' }
,它可以很容易地将这些值传递给url帮助器并生成搜索查询。
一切正常。
我的问题是,这是否是建立这种关系的最佳方式。我还没有看到任何其他单向HABTM关系的例子,所以我想我可能在这里做错了。
这是HABTM的可接受用途吗?
答案 0 :(得分:3)
功能上是,但语义上没有。以“片面”方式使用HABTM将实现您想要的。不幸的是,HABTM的名称暗示了一种并非总是如此的互惠关系。同样地,belongs_to :foo
在这里没有什么直观意义。
不要陷入HABTM和其他关联的语义,而只是考虑您的ID需要坐在哪里才能正确有效地查询数据。请记住,效率考虑首先应考虑到您的工作效率。
我将冒昧地创造一个比你的泡沫和酒吧更具体的例子...说我们有一个引擎,可以让我们查询某个池塘中是否存在某些鸭子,我们想跟踪这些问题。
<强>可能性强>
在查询记录中存储鸭子有三种选择:
您自己已经回答了联接表用例,如果“[Duck]或[Pond]都不需要了解有关Query的任何内容”,那么使用单向关联应该会导致您没有问题。您需要做的就是创建一个ducks_queries
表,ActiveRecord将提供其余的表。如果您需要做任何花哨的事情,您甚至可以选择使用has_many :through
关系。
有时数组比使用连接表更方便。您可以将数据存储为serialized整数数组,并添加处理程序以访问类似于以下内容的数据:
class Query
serialize :duck_ids
def ducks
transaction do
Duck.where(id: duck_ids)
end
end
end
如果您的数据库中有本机阵列支持,则可以在数据库中执行相同操作。类似。
使用Postgres的本机阵列支持,您可以进行如下查询:
SELECT * FROM ducks WHERE id=ANY(
(SELECT duck_ids FROM queries WHERE id=1 LIMIT 1)::int[]
)
您可以在SQL Fiddle
上播放上述示例权衡
query.bars
,query.bars=
,query.bars.where()
)在一天结束时,您的用例会有所不同。除此之外,我会说你应该坚持你的“片面”HABTM实施:否则你会丢失很多Rails赠送的礼物。