“虚拟关系”在 Rails 中
我正在尝试在 Rails 中建立“虚拟关系”(我称之为 - 不知道是否有真正的术语)。这是我拥有的绝对有效的:地址属于业务和业务 has_many 地址。 地址有一个“类别”列:邮寄或物理。理论上,企业可以拥有任意数量的每种类型,但实际上每种类型只有一个。所以我的模型看起来像这样:
class Address < ActiveRecord::Base
belongs_to :business
end
class Business < ActiveRecord::Base
has_many :addresses
has_one :physical_address, :class_name => 'Address', :conditions => ["category = ?", "Physical"]
has_one :mailing_address, :class_name => 'Address', :conditions => ["category = ?", "Mailing"]
end
因此,我有两个“虚拟”has_one,这样我就可以方便地访问其中一个(作为 business.physical_address 或 business.mailing_address),而无需必须自己完成将它们分开的工作。
现在我正在尝试做类似的事情,但是使用 has_many :through。这是我的新场景。我有一个简单的多对多连接关系。假设A有许多J,B也有许多J,并且J 同时属于A和B。然而,A 还拥有_许多 B 到 J。所以我可以通过 a.bs 访问它们。
然而,B 中的条目也有一个“类别”。与上面的业务/地址示例一样,我希望在A中拥有“虚拟”单向/多向关系,因此我不必手动按类别分隔B。我尝试了类似的操作(假设 A 恰好有一个 B 且类别='Type 1'):
class A < ActiveRecord::Base
has_many :js
has_many :bs, :through => js
has_one :b_type1, :class_name => 'B', :through => :js, :conditions => ["category = ?", "Type 1"]
end
但是,当我在 A< 上进行查找时/em> 的结果对象中没有 b_type1 属性。
甚至有可能做我想做的事吗?任何帮助表示赞赏。
编辑:我需要将其序列化到 Adobe Flex 前端(使用 RestfulX 框架)。根据 此线程,我不能仅使用 @Andrew 那样的方法下面建议,因为如果不进行一些繁重的工作,结果对象将无法正确序列化。
I'm trying to do a "virtual relationship" (what I call it - don't know if there's a real term for it) in Rails. Here's one that I have that is definitely working: Address belongs_to Business and Business has_many Addresses. Addresses have a 'category' column: either Mailing or Physical. In theory, a business could have any number of each type, but in practice they have exactly one of each. So my models look like this:
class Address < ActiveRecord::Base
belongs_to :business
end
class Business < ActiveRecord::Base
has_many :addresses
has_one :physical_address, :class_name => 'Address', :conditions => ["category = ?", "Physical"]
has_one :mailing_address, :class_name => 'Address', :conditions => ["category = ?", "Mailing"]
end
Thus, I have two "virtual" has_one's, so that I can conveniently access either one (as business.physical_address or business.mailing_address) without having to do the work of separating them myself.
Now I'm trying to do something similar, but with a has_many :through. Here's my new scenario. I have a simple many-to-many relationship with a join. Let's say A has many J's, B also has many J's, and J belongs_to both A and B. However, A also has_many B's through J. So I can access them as a.bs.
However, the entries in B also have a 'category'. So as with the Business/Address example above, I want to have "virtual" has-one/many-through relationships in A, so I don't have to manually separate the B's by category. I tried something like this (assuming A's have exactly one B with category='Type 1'):
class A < ActiveRecord::Base
has_many :js
has_many :bs, :through => js
has_one :b_type1, :class_name => 'B', :through => :js, :conditions => ["category = ?", "Type 1"]
end
However, when I do a find on A's, the resulting objects do not have a b_type1 property in them.
Is it even possible to do what I'm trying to do?? Any help is appreciated.
Edit: I am needing this to be serialized to an Adobe Flex frontend (using the RestfulX framework). According to this thread, I can't use just a method as @Andrew suggests below because the resulting object will not get properly serialized without some heavy-duty effort.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您编写的 has_one 关联应该完全按照您想要的方式工作,但是 Rails 将无法从 :b_type1 猜测该字段。
正如您显式指定类名一样,尝试指定源:
我测试了一个类似的查找器,它的工作方式正如您所期望的那样。
The has_one association you wrote should work exactly as you want it, however Rails won't be able to guess the field from :b_type1.
Just as you explicitly specified the class name, try specifying the source:
I tested a similar finder and it worked as you would expect it to.
我可以想到两种“railsier”方法来解决这个问题。
第一种方法:为什么不直接使用这些方法呢?
在您给出的第一个示例中,请在 Business 类中尝试此操作:
现在调用
business.physical_address
将返回地址对象。您可以通过 HABTM 协会以同样的方式做到这一点。现在调用
a.type_1
将返回类别为“Type_1”的单个 B(如果有多个类别,则返回第一个)。第二种方式:如果您认为给定的“虚拟关系”会有多个匹配项,则更有用,您可以将这些条件设为范围。因此,对于第二个示例:
现在,如果您调用
a.bs.type_1.first
,您将得到您正在寻找的 B。如果您永远不会有多个,您也可以将.first
放入范围中。要强制只有一个,您还可以创建 唯一性验证,验证给定父对象的类别的唯一性。
在我看来,使用这些选项中的任何一个都比构建这些“虚拟”关系更接近解决问题的“Rails 方式”。也许这只是我。
请尝试这个,如果您有任何问题请告诉我:)
There are two "railsier" ways I can think of to solve this.
First Way: Why not just make these methods?
In the first example you gave, try this in your Business class:
Now calling
business.physical_address
would return the address object. In the same way you can do this with your HABTM association.Now calling
a.type_1
would return the single B having a category of 'Type_1' (or the first if there were more than one).Second Way: More useful if you thought there would ever be more than one match for a given 'virtual relationship', you could just make these conditions a scope. So, for the second example:
Now if you called
a.bs.type_1.first
you'd get the B you were looking for. You could also put.first
in the scope if you will never have more than one.To enforce there being only one you can also create a uniqueness validation, validating uniqueness of a category with a given parent object.
Using either of these options seems to me to be much closer to the "Rails Way" of solving your problem than building these "virtual" relationships is. Maybe it's just me though.
Please try this and let me know if you have any trouble :)