“虚拟关系”在 Rails 中

发布于 2024-11-15 02:10:59 字数 1738 浏览 4 评论 0原文

我正在尝试在 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_addressbusiness.mailing_address),而无需必须自己完成将它们分开的工作。

现在我正在尝试做类似的事情,但是使用 has_many :through。这是我的新场景。我有一个简单的多对多连接关系。假设A有许多JB也有许多J,并且J 同时属于AB。然而,A 还拥有_许多 BJ。所以我可以通过 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 属性。

甚至有可能做我想做的事吗?任何帮助表示赞赏。

编辑:我需要将其序列化到 Adob​​e 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

阿楠 2024-11-22 02:10:59

您编写的 has_one 关联应该完全按照您想要的方式工作,但是 Rails 将无法从 :b_type1 猜测该字段。

正如您显式指定类名一样,尝试指定源:

has_one :b_type1, :class_name => 'B', :through => :js, :source => bs, :conditions => ["category = ?", "Type 1"]

我测试了一个类似的查找器,它的工作方式正如您所期望的那样。

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:

has_one :b_type1, :class_name => 'B', :through => :js, :source => bs, :conditions => ["category = ?", "Type 1"]

I tested a similar finder and it worked as you would expect it to.

书间行客 2024-11-22 02:10:59

我可以想到两种“railsier”方法来解决这个问题。

第一种方法:为什么不直接使用这些方法呢?

在您给出的第一个示例中,请在 Business 类中尝试此操作:

def physical_address
   self.address.where(:category => 'physical').first
end

现在调用 business.physical_address 将返回地址对象。您可以通过 HABTM 协会以同样的方式做到这一点。

class A < ActiveRecord::Base
  ...
  def type_1
    self.bs.where(:category=>'type_1').first
  end
  ...
end

现在调用 a.type_1 将返回类别为“Type_1”的单个 B(如果有多个类别,则返回第一个)。

第二种方式:如果您认为给定的“虚拟关系”会有多个匹配项,则更有用,您可以将这些条件设为范围。因此,对于第二个示例:

class B < ActiveRecord::Base
  ...
  scope :type_1 { where(:category=>'type_1') }
  ...
end

现在,如果您调用 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:

def physical_address
   self.address.where(:category => 'physical').first
end

Now calling business.physical_address would return the address object. In the same way you can do this with your HABTM association.

class A < ActiveRecord::Base
  ...
  def type_1
    self.bs.where(:category=>'type_1').first
  end
  ...
end

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:

class B < ActiveRecord::Base
  ...
  scope :type_1 { where(:category=>'type_1') }
  ...
end

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 :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文