Восстановление расширенного примера has_many - PullRequest
2 голосов
/ 13 марта 2010

Моя пользовательская модель имеет три отношения для одной и той же модели сообщений и использует сырой SQL: / Есть ли лучший способ для достижения того же результата?

Может ли внешний ключ быть изменен динамически? например, User.messages.sent (внешний ключ = author_id) и User.messages.received (внешний ключ = получатель). Я пытался переместить часть логики в области в модели сообщений, но user.id недоступен из модель сообщения ...

Есть мысли?

Таблица раскладки:

  create_table "messages", :force => true do |t|
    t.string   "subject"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "author_id"
    t.integer  "recipient_id"
    t.boolean  "author_deleted",    :default => false
    t.boolean  "recipient_deleted", :default => false
  end

Это мои отношения с моей моделью пользователя:

  has_many :messages_received, :foreign_key => "recipient_id", :class_name => "Message", :conditions => ['recipient_deleted = ?', false]
  has_many :messages_sent, :foreign_key => "author_id", :class_name => "Message", :conditions => ['author_deleted = ?', false]
  has_many :messages_deleted, :class_name => "Message", :finder_sql => 'SELECT * FROM Messages WHERE
                                                                        author_id = #{self.id} AND author_deleted = true OR
                                                                        recipient_id = #{self.id} AND recipient_deleted = true'

С наилучшими пожеланиями. Асбьерн Морелл

1 Ответ

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

Да, используйте named_scope для сортировки удаленных и не удаленных сообщений.

class User < ActiveRecord::Base
  has_many :messages_received, :foreign_key  => 'recipient_id'
  has_many :messages_sent, :foreign_key => 'author_id'
end

class Messages < ActiveRecord::Base
  named_scope :deleted, :conditions => 'author_deleted = TRUE OR recipient_deleted = TRUE' 
  named_scope :not_deleted, :conditions => 'author_deleted = FALSE OR recipient_deleted = FALSE'
end

# Example user
user = User.first
user.messages_received.deleted
user.messages_received.not_deleted
user.messages_sent.deleted
user.messages_sent.not_deleted

Кроме того, вы можете пойти еще дальше и упростить сопоставление, используя user_id в качестве внешнего ключа и указав тип сообщения.

create_table "messages", :force => true do |t|
  t.string   "subject"
  t.text     "body"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "message_type"
  t.integer  "user_id"
  t.boolean  "deleted", :default => false
end

class User < ActiveRecord::Base
  has_many :messages
end

class Messages < ActiveRecord::Base
  MESSAGE_TYPES = %w[Recipient Author]

  belongs_to :user

  named_scope :recipient, :conditions => {:message_type => 'Recipient'}
  named_scope :author, :conditions => {:message_type => 'Author'}
  named_scope :deleted, :conditions => {:deleted => true}
  named_scope :not_deleted, :conditions => {:deleted => false}

  # Convenience class methods
  def self.sent
    author.not_deleted
  end

  def self.received
    recipient.not_deleted
  end
end

# Example usage
user = User.first
user.messages.sent
user.messages.received
user.messages.deleted

Этот подход является преимуществом, потому что:

  1. Еще один столбец.
  2. Выдвижная. Добавление дополнительного типа сообщения в будущем тривиально (например, черновики).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...