【问题标题】:How to create Rails models with multiple complex associations/joins?如何创建具有多个复杂关联/连接的 Rails 模型?
【发布时间】:2011-01-24 06:04:02
【问题描述】:

我正在尝试弄清楚如何创建具有可以产生与此 SQL 查询相同结果的关联的 ActiveRecord 模型:

SELECT login, first_name, last_name, email_address 
FROM accounts 
INNER JOIN people ON person.id = accounts.person_id
INNER JOIN email_address_people ON person.id = email_address_people.person_id 
INNER JOIN email_addresses ON email_address.id = email_address_people.email_address_id
INNER JOIN email_address_types ON email_address_types.id = email_address_people.email_address_type_id 
WHERE email_address_types.email_address_type = 'account';

表结构如下,并假设每个表都有一个id 每个正常的 ActiveRecord 约定:

帐户
id : 整数
person_id : 整数
登录:字符串


id : 整数
名字:字符串
姓氏:字符串

email_address_people
id : 整数
person_id : 整数
email_address_id : 整数
email_address_type_id : int

电子邮件地址
id : 整数
电子邮件地址:字符串

email_address_types
id : 整数
email_address_type:字符串

我需要模型功能齐全,不受 :find_by_sql 之类的限制。

如何创建使这成为可能的关联模型?

谢谢!
克里斯·本森
chris@chrisbenson.com

【问题讨论】:

    标签: ruby-on-rails activerecord associations join


    【解决方案1】:

    试试这个:

    你的模型类:

      class EmailAddress < ActiveRecord::Base
      end
    
      class EmailAddressType < ActiveRecord::Base
      end
    
      class People < ActiveRecord::Base
        has_many :accounts
        has_many :email_address_people
        has_many :email_addresses, :through => :email_address_people
    
        has_many :account_email_address_people, 
                       :class_name => "EmailAddressPeople", 
                       :conditions => "email_address_type = 'account'"
    
        has_many :account_email_addresses, 
                       :through => :account_email_address_people
    
      end
    
      class EmailAddressPeople < ActiveRecord::Base
        belongs_to :person
        belongs_to :email_address
        belongs_to :email_address_type
      end
    

    您的帐户模型:

      class Account < ActiveRecord::Base
        belongs_to :person
    
        # now to the actual method
        def account_emails
          person.account_email_addresses.map do |email|
            [login, person.first_name, person.last_name, email.email_address]
          end
        end
    
        # Brute force SQL if you prefer
        def account_emails2
           sql = "YOUR SQL HERE"
           self.connection.select_values(sql)
        end
    
      end
    

    假设您手头有 Account 对象 account.account_emails 进行两次数据库调用:

    • 使用 id 获取人员

    • 获取此人的帐户电子邮件

    直接进入数据库(即account.account_emails2)是最快的选择,但不是 Rails 方式。

    【讨论】:

      【解决方案2】:

      我认为最好的办法是先给你文档:http://railsbrain.com/api/rails-2.3.2/doc/index.html
      查找“has_many”(注意 :through)和“belongs_to”,以及“has_one”,虽然我认为您不会使用后者。
      This blog post 将帮助您处理 has_many :通过概念 - 我认为在那之后,你会被设置。让我们知道是否有任何不清楚的地方!

      class Account < ActiveRecord::Base
        belongs_to :person
      end
      
      class Person < ActiveRecord::Base
        has_many :accounts
        has_many :email_addresses :through => :email_address_people
      end
      
      class EmailAddress < ActiveRecord::Base
        belongs_to :email_address_type
        belongs_to :person
        has_one :email_address_type
      end
      
      class EmailAddressType < ActiveRecord::Base
        has_many :email_addresses :through => :email_address_people
      end
      

      我会开始的。它没有经过测试,但如果我们看到有什么问题,那么我们可以修复它.. :)

      【讨论】:

      • 谢谢,但我已经这样做了。熟悉所有这些——belongs_to、has_one、HABTM、HM:T。已经全部使用它们,但无法弄清楚如何使这种情况正常工作。还没有在网上找到任何迎合这种复杂性的例子。真的可以使用一些示例模型代码,显示至少 4-5 个归一化表连接并在标准查询中使用它们。
      • 编辑了我的答案(不确定您是否会收到警告)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 2013-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多