Ruby on rails 我可以把一个关系的双方都加入到一个关系中吗?

Ruby on rails 我可以把一个关系的双方都加入到一个关系中吗?,ruby-on-rails,activerecord,relationship,activesupport-concern,Ruby On Rails,Activerecord,Relationship,Activesupport Concern,编辑:回想起来,这不是一个好主意。您正在将属于ZipWithCBSA的功能放入其他模型中。收到问题的模型按其预期的方式运行,ZipWithCBSA响应:存储位置的事实在ZipWithCBSA的某些容量中应该是显而易见的。这与其他型号/问题无关。向Robert Nubel致敬,感谢他通过潜在的解决方案使这一点变得显而易见。 是否可能在一个企业中同时拥有多个关系和属于多个关系 概述 我有一个表ZipWithCBSA,基本上包含了一堆邮政编码元信息 我有两种型号有邮政编码:StoreLocation和

编辑:回想起来,这不是一个好主意。您正在将属于ZipWithCBSA的功能放入其他模型中。收到问题的模型按其预期的方式运行,
ZipWithCBSA
响应
:存储位置
的事实在
ZipWithCBSA
的某些容量中应该是显而易见的。这与其他型号/问题无关。向Robert Nubel致敬,感谢他通过潜在的解决方案使这一点变得显而易见。

是否可能在一个企业中同时拥有多个关系和属于多个关系

概述 我有一个表
ZipWithCBSA
,基本上包含了一堆邮政编码元信息

我有两种型号有邮政编码:
StoreLocation
PriceSheetLocation
。基本上:

class ZipWithCBSA < ActiveRecord::Base
  self.primary_key = :zip
  has_many :store_locations, foreign_key: :zip
  has_many :price_sheet_locations, foreign_key: :zip
end

class StoreLocation< ActiveRecord::Base
  belongs_to :zip_with_CBSA, foreign_key: :zip
  ...
end

class PriceSheetLocation < ActiveRecord::Base
  belongs_to :zip_with_CBSA, foreign_key: :zip
  ...
end
所以,我补充说

after_save :store_cbsa_data_locally, if: ->(obj){ obj.zip_changed? }
private
def store_cbsa_data_locally
  if zip_with_cbsa.present?
    update_column(:cbsa_name, zip_with_cbsa.cbsa_name)
    update_column(:cbsa_state, zip_with_cbsa.cbsa_state)
  else
    update_column(:cbsa_name, nil)
    update_column(:cbsa_state, nil)
  end
end
我希望将这些问题转化为关注点,因此我做了:

# models/concerns/UsesCBSA.rb

module UsesCBSA
  extend ActiveSupport::Concern

  included do
    belongs_to :zip_with_cbsa, foreign_key: 'zip'

    after_save :store_cbsa_data_locally, if: ->(obj){ obj.zip_changed? }

    def store_cbsa_data_locally
      if zip_with_cbsa.present?
        update_column(:cbsa_name, zip_with_cbsa.cbsa_name)
        update_column(:cbsa_state, zip_with_cbsa.cbsa_state)
      else
        update_column(:cbsa_name, nil)
        update_column(:cbsa_state, nil)
      end
    end

    private :store_cbsa_data_locally

  end
end


# ~~models~~
class StoreLocation < ActiveRecord::Base
  include UsesCBSA
end

class PriceSheetLocation < ActiveRecord::Base
  include UsesCBSA
end
而且

# models/concerns/uses_cbsa.rb
...
ZipWithCBSA.has_many self.name.underscore.to_sym, foregin_key: :zip
...
但两者都不起作用。我猜这与这些关系在模型本身的初始化过程中没有添加有关。。。但是是否可以在单独的文件中定义模型的关系?


我对Ruby的元编程还不是很熟练。

您最好的选择可能是在将您的问题包含到相关模型中时,在模型类本身上使用
class\u exec
将关系添加到ZipWithCBSA模型中。例如,在您关注的
包含的
块中,添加:

relation_name = self.table_name
ZipWithCBSA.class_exec do
  has_many relation_name, foreign_key: :zip
end

实际上,它并没有那么好用——我发现自己处于无限循环中……我已经修复了递归问题,并适当地调整了原始问题。我也不需要对
self.
的所有引用,所以我删除了它们来帮助清理它。我最终收到:
NoMethodError:undefined method`price\u sheet\u locations',for
,这与我在尝试上述其他方法时遇到的问题相同。就像ZipWithCBSA类没有注册关系方法一样。。。。或者是关系……我知道发生了什么!在实际使用接收模型之前,不会实际加载关注点中的代码。e、 g.ZipWithCBSA上的这种关系在我至少进行PriceSheetLocation.connection之前是不存在的。这意味着如果我尝试执行
ZipWithCBSA.find('90210').price\u sheet\u locations
——至少在我完成
PriceSheetLocation.first
连接之后,它才会注册。非常感谢课堂执行技巧——它最终完成了我原来的问题。不幸的是,还有其他关于时间安排的新问题。@Mr.Tim有很多方法可以解决。我的第一个建议是在ZipWithCBSA中添加关系。。。元编程在编写时很有趣,但在调试时却很可怕。如果您真的想保持它的魔力,您可以a)强制Rails在引导时急切地加载所有模型,这是一种激进的方法;或者b)在ZipWithCBSA上使用方法missing hack,迫使它在放弃之前解析您的模型;类似于,
def method_missing(method,*args);方法:使单一化、资本化、恒定化、拯救零;超级(*args);结束
。可能需要调整。是的,我完全同意你的看法。谢谢你今天抽出时间!
# models/concerns/uses_cbsa.rb
...
def ZipWithCBSA
  has_many self.name.underscore.to_sym, foregin_key: :zip
end
...
# models/concerns/uses_cbsa.rb
...
ZipWithCBSA.has_many self.name.underscore.to_sym, foregin_key: :zip
...
relation_name = self.table_name
ZipWithCBSA.class_exec do
  has_many relation_name, foreign_key: :zip
end