【问题标题】:has_many :through Rails 3.1.1has_many :通过 Rails 3.1.1
【发布时间】:2012-01-11 00:22:26
【问题描述】:

已更新问题,因为原始问题过于简单,感谢 Aaron McLeod aka AGMCLEOD 帮助强调这一点


我的问题不是我不能让它工作,而是让它按我想要的方式工作。

问题

想象 3 个模型,一个 Company、Branch 和一个 Contact,它们通过 CompanyContacts 模型或查找表链接在一起。

company_contacts 表如下所示:

+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+

我将联系人与分支机构和公司联系起来的理想陈述应该是:

update company_contacts set contact_id = x where branch_id = y AND company_id = z

那么问题来了,这怎么可能使用 ActiveRecord?您是否创建自定义方法来一次性设置它?

我的模型中有什么

公司联系模型

belongs_to :company, :class_name => "Company", :foreign_key => :company_id
belongs_to :branch,  :class_name => "Branch",  :foreign_key => :branch_id
belongs_to :contact, :class_name => "Contact", :foreign_key => :contact_id

公司模式

has_many :company_contacts
has_many :branches,  :through => :company_contacts, :source => :branches
has_many :contacts,  :through => :company_contacts, :source => :contacts 

分支模型

has_many :company_contacts
has_many :companies, :through => :company_contacts, :source => :companies
has_many :contacts,  :through => :company_contacts, :source => :contacts 

我希望能够执行以下操作,但这是不可能的

has_one :company, :through => :company_contacts, :source => :company

当然可以模拟

def branch
  Branch.companies.first
end

联系模特

has_many :company_contacts
has_many :branches, :through => :company_contacts, :source => :branches
has_many :companies, :through => :company_contacts, :source => :companies

理想情况下,我希望拥有 has_one 分公司和 has_one 公司

我在创建联系人和

+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+
| 1          | 1         | nil        |
+------------+-----------+------------+
| nil        | 1         | 1          |
+------------+-----------+------------+

什么时候,其实我想要实现的是:

+------------+-----------+------------+
| company_id | branch_id | contact_id |
+------------+-----------+------------+
| 1          | 1         | 1          |
+------------+-----------+------------+

我能想到的唯一方法是创建一个自定义方法

我将继续尝试解决我的问题并发布我的发现 期待您的回复

提前致谢。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord ruby-on-rails-3.1


    【解决方案1】:

    好吧,在发布了这个问题之后,我发现了这个关于类似问题的很棒的答案,然后又进行了更多的挖掘。 zetetic 提供了一个非常详细的答案,我更深入地阅读了如何解决这个问题。

    首先灵感:has_many :through multiple has_one relationships?

    现在答案是:

    在您的 ContactController 的 create 方法中,神奇的 1 行代码是:

    @contact.company_contacts.build(:company_id => @company.id, :branch_id => @branch.id)
    

    所以在ContactController的create方法中完整:

    # fetch the branch and company ids first
    
    @contact = Contact.new(params[:contact])
    @contact.company_contacts.build(:company_id => @company.id, :branch_id => @branch.id)
    @contact.save
    

    它正是我想要实现的目标:

    INSERT INTO "company_contacts" ("branch_id", "company_id", "contact_id") VALUES (?, ?, ?)  [["branch_id", 2], ["company_id", 4], ["contact_id", 12]]
    

    唷 - 不知何故花了我一段时间,看起来很简单!

    【讨论】:

      【解决方案2】:

      要解决此问题,您可以执行以下操作。假设您正在通过表单传递分支 id 和公司 id,或者如果您已经在 url 中。

      def create
        @contact = Contact.new(params[:contact])
        if @contact.save
          cc = CompanyContact.new(:contact_id => @contact.id, :branch_id => params[:branch_id], :company_id => params[:company_id])
          cc.save
          redirect_to contacts_url, :notice => "Contact saved"
        else
          render :action => "new"
        end
      end
      

      您可能需要调整参数名称等,但这应该可以。因为它有点三向连接,我不确定是否有办法在联系人对象上构建它。

      【讨论】:

      • 实际上完全同意你的看法,但实际上模型是不同的。换个角度想想,例如公司、分支机构、联系人——我想这会是一个更好的例子,因为我显然已经过度简化了问题。我这样做的原因是为了提高效率和减少查询。
      • 嗯,好吧,那更有意义。您仍然可以发布您在控制器中使用的代码吗?我是一个非常有眼光的人,这可能会有所帮助。不过,我会根据我的想法调整我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 2013-11-18
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多