Как создать Rails-модели с несколькими сложными ассоциациями / объединениями? - PullRequest
4 голосов
/ 05 марта 2010

Я пытаюсь выяснить, как создавать модели ActiveRecord с ассоциациями, которые могут дать те же результаты, что и этот запрос SQL:

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: int
person_id: int
логин: строка

people
id: int
first_name: string
last_name: string

email_address_people
id: int
person_id: int
email_address_id: int
email_address_type_id: int

email_addresses
id: int
email_адрес: строка

email_address_types
id: int
email_address_type: string

Мне нужно, чтобы модели были полностью функциональными и не ограничивались такими вещами, как : find_by_sql .

Как создать связанные модели, которыесделать это возможным?

Спасибо!
Крис Бенсон
chris@chrisbenson.com

Ответы [ 2 ]

3 голосов
/ 05 марта 2010

Попробуйте это:

Ваша модель классов:

  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 делает два вызова базы данных:

  • Получить человека, используя идентификатор

  • Получить учетные записи электронной почты для человека

Переход непосредственно к базе данных (т. Е. account.account_emails2) - самый быстрый вариант, но это не путь Rails.

0 голосов
/ 05 марта 2010

Я думаю, что лучше всего сначала дать вам документацию: http://railsbrain.com/api/rails-2.3.2/doc/index.html
Найдите "has_many" (обращая внимание на: through) и "own_to", а также "has_one", хотяЯ не думаю, что вы будете использовать позже.
Этот пост в блоге поможет вам с концепцией has_many: through - и я думаю, что после этого вы будете настроены.Дайте нам знать, если что-то не ясно!

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

Я бы начал с этого.Это не проверено, но если мы увидим, что ломается, то мы можем это исправить ..:)

...