我可以与HABTM建立单向关系吗? [英] Can I have a one way HABTM relationship?

查看:47
本文介绍了我可以与HABTM建立单向关系吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个拥有一个Foo和许多Bars的模型Item。

Say I have the model Item which has one Foo and many Bars.

在搜索项目时,Foo和Bar可以用作参数,因此可以像这样搜索项目:

Foo and Bar can be used as parameters when searching for Items and so Items can be searched like so:

www.example.com/search?foo=foovalue&bar[]=barvalue1&bar[]=barvalue2

我需要生成一个 Query 对象,该对象能够保存这些搜索参数。我需要以下关系:

I need to generate a Query object that is able to save these search parameters. I need the following relationships:


  • 查询需要访问一个Foo和许多Bar。

  • 一个Foo可以被许多不同的查询访问。

  • 许多不同的查询可以访问一个Bar。

  • Bar和Foo都不需要了解有关查询的任何信息。

  • Query needs to access one Foo and many Bars.
  • One Foo can be accessed by many different Queries.
  • One Bar can be accessed by many different Queries.
  • Neither Bar nor Foo need to know anything about Query.

我目前这样建立这种关系:

I have this relationship set up currently like so:

class Query < ActiveRecord::Base
  belongs_to :foo
  has_and_belongs_to_many :bars
  ...
end

查询还具有返回如下哈希值的方法: {foo:'foovalue',bars:['barvalue1','barvalue2'} 可以轻松地将这些值传递到url助手中并生成搜索查询。

Query also has a method which returns a hash like this: { foo: 'foovalue', bars: [ 'barvalue1', 'barvalue2' } which easily allows me to pass these values into a url helper and generate the search query.

这一切都很好。

我的问题是,这是否是建立这种关系的最佳方法。我还没有看到任何其他单向HABTM关系示例,所以我认为我在这里做错了什么。

My question is whether this is the best way to set up this relationship. I haven't seen any other examples of one-way HABTM relationships so I think I may be doing something wrong here.

这是可以接受的HABTM使用吗?

推荐答案

在功能上是,但在语义上不是。以单面方式使用HABTM可以完全实现您想要的。不幸的是,HABTM这个名称确实暗示着一种互惠的关系,这种情况并非总是如此。同样, belongs_to:foo 在这里几乎没有直观意义。

Functionally yes, but semantically no. Using HABTM in a "one-sided" fashion will achieve exactly what you want. The name HABTM does unfortunately insinuate a reciprocal relationship that isn't always the case. Similarly, belongs_to :foo makes little intuitive sense here.

不要被HABTM的语义所困扰以及其他关联,而只需考虑您的ID需要坐在哪里才能正确有效地查询数据。请记住,效率方面的考虑应该首先考虑到您的生产率。

Don't get caught up in the semantics of HABTM and the other association, instead just consider where your IDs need to sit in order to query the data appropriately and efficiently. Remember, efficiency considerations should above all account for your productivity.

我将自由地创建一个比您的foos和bar更具体的示例...说我们有一个使我们能够查询给定池塘中是否存在某些鸭子的引擎,并且我们希望跟踪这些查询。

I'll take the liberty to create a more concrete example than your foos and bars... say we have an engine that allows us to query whether certain ducks are present in a given pond, and we want to keep track of these queries.

可能性

您可以使用三种选择在查询记录中存储鸭子:

You have three choices for storing the ducks in your Query records:


  1. 联接表

  2. 鸭子id的本地数组

  3. 鸭子id的序列化数组

您已经亲自回答了联接表用例,并且如果确实是 [Duck]和[Pond]都不需要了解查询,那么使用单侧关联应该不会给您带来任何问题。您需要做的就是创建一个 ducks_queries 表,其余的将由ActiveRecord提供。如果您需要做任何花哨的事情,甚至可以选择使用 has_many:through 关系。

You've answered the join table use case yourself, and if it's true that "neither [Duck] nor [Pond] need to know anything about Query", using one-sided associations should cause you no problems. All you need to do is create a ducks_queries table and ActiveRecord will provide the rest. You could even opt to use has_many :through relationship if you need to do anything fancy.

有时数组是比使用联接表更方便。您可以将数据存储为序列化整数数组并添加用于访问数据的处理程序,如下所示:

At times arrays are more convenient than using join tables. You could store the data as a serialized integer array and add handlers for accessing the data similar to the following:

class Query
 serialize :duck_ids
 def ducks
   transaction do 
     Duck.where(id: duck_ids)
   end
 end
end

如果数据库中具有本机阵列支持,则可以在数据库中执行相同的操作。

If you have native array support in your database, you can do the same from within your DB. similar.

有了Postgres的本机数组支持,您可以进行如下查询:

With Postgres' native array support, you could make a query as follows:

SELECT * FROM ducks WHERE id=ANY(
  (SELECT duck_ids FROM queries WHERE id=1 LIMIT 1)::int[]
)

您可以在 SQL提琴

权衡


  1. 联接表:


    • 优点:约定优于配置;您会获得所有的Rails好东西(例如 query.bars query.bars = query现成的.bars.where()

    • 缺点:您已经为数据层增加了复杂性(例如,另一个表,更密集的查询);缺乏直觉

  1. Join table:
    • Pros: Convention over configuration; You get all the Rails goodies (e.g. query.bars, query.bars=, query.bars.where()) out of the box
    • Cons: You've added complexity to your data layer (i.e. another table, more dense queries); makes little intuitive sense

  • 优点:语义上不错;您可以直接使用数据库中与阵列相关的所有功能;可能具有更高的性能

  • 缺点:您必须推出自己的Ruby / SQL或使用ActiveRecord扩展,例如 postgres_ext ;不是与数据库无关的;再见Rails好东西

  • Pros: Semantically nice; you get all the DB's array-related goodies out of the box; potentially more performant
  • Cons: You'll have to roll your own Ruby/SQL or use an ActiveRecord extension such as postgres_ext; not DB agnostic; goodbye Rails goodies

  • 优点:语义很好不可知的数据库

  • 缺点:您必须使用自己的Ruby;您将失去直接通过数据库进行某些查询的功能;序列化很糟糕;再见Rails好东西

最终,您的用例使一切区别。除此之外,我要说的是,您应该坚持使用单面 HABTM实施:否则,您将失去很多Rails赠送的礼物。

At the end of the day, your use case makes all the difference. That aside, I'd say you should stick with your "one-sided" HABTM implementation: you'll lose a lot of Rails-given gifts otherwise.

这篇关于我可以与HABTM建立单向关系吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆