2

我正在尝试在 Rails 中建立“虚拟关系”(我称之为 - 不知道是否有真正的术语)。这是我拥有的一个绝对有效的方法: Address belongs_to BusinessBusiness has_many Addresses地址有一个“类别”列:MailingPhysical。理论上,一家企业可以拥有任意数量的每种类型,但实际上它们只有一种。所以我的模型看起来像这样:

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也有很多JJ属于AB。但是,A也有很多BJ。所以我可以作为a.bs访问它们。

但是,B中的条目也有一个“类别”。因此,与上面的Business/Address示例一样,我希望在A中具有“虚拟”具有单通/多通关系,因此我不必按类别手动分隔B 。我试过这样的事情(假设A正好有一个B的 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

但是,当我在A上进行查找时,生成的对象中没有b_type1属性。

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

编辑:我需要将其序列化为 Adob​​e Flex 前端(使用RestfulX框架)。根据这个线程,我不能只使用@Andrew 在下面建议的方法,因为如果没有一些繁重的工作,生成的对象将无法正确序列化。

4

2 回答 2

2

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

就像您明确指定类名一样,请尝试指定源:

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

我测试了一个类似的查找器,它可以按您的预期工作。

于 2011-06-14T04:35:20.817 回答
1

我可以想到两种“更有效”的方法来解决这个问题。

第一种方式:为什么不直接制作这些方法?

在您给出的第一个示例中,在您的商务课程中尝试此操作:

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 方式”。也许这只是我。

请试试这个,如果你有任何问题,请告诉我:)

于 2011-06-14T04:55:59.457 回答