Rails 3: как обновить has_one и has_many, указывающие на одну и ту же таблицу одновременно - PullRequest
0 голосов
/ 12 июля 2011

Спасибо за помощь нубу. У меня есть следующие отношения в двух моделях:

class Reader < ActiveRecord::Base
  has_many :books, :dependent => :destroy
  has_one :last_book, :class_name => "Book"
end

class Book < ActiveRecord::Base
  belongs_to :reader
end

Я хочу, чтобы last_book была самой последней книгой, связанной с читателем.

Прямо сейчас в контроллере книги я создаю книгу следующим образом с похожим кодом в обновлении

def create
  @reader = Reader.find(params[:reader_id])
  @book = @reader.books.new (params[:book])
  @reader.last_data = @book
end

Я думаю, это приводит к тому, что мы дважды пишем книгу в базу данных. Есть ли более чистый / более эффективный способ сделать это?

Ответы [ 2 ]

3 голосов
/ 12 июля 2011

Я не думаю, что ваши ассоциации действительно будут работать так, как вы этого хотите. При настройке ассоциаций модель Reader не сможет определить, какая книга является last_book, поскольку все книги, связанные с конкретным читателем, будут иметь одинаковый идентификатор reader_id. Назначение книги для читателя с помощью reader.last_book = book - это просто установка столбца reader_id на этой модели книги для идентификатора читателя. Это то же самое, что произойдет, когда вы добавите книгу в reader.books, так что здесь нет никакого отличительного фактора, чтобы определить, какую книгу вы имеете в виду, когда звоните last_book.

Возможно, вам будет лучше просто определить метод для last_book ассоциации, которую вы пытаетесь смоделировать. Если я понимаю, что вы пытаетесь сделать правильно, last_book должна быть последней созданной книгой для читателя. В вашей модели Reader сделайте примерно так:

def last_book
  books.order('created_at desc').first
end

и удалите эту строку

has_one :last_book, :class_name => "Book"

Это должно позволить вам сделать что-то вроде reader.last_book, и оно захватит самую последнюю созданную книгу в ассоциации книг. Таким образом, у вас никогда не будет причин явно назначать last_book, вы просто добавляете книгу в reader.books, а когда вам нужна последняя книга, просто звоните reader.last_book.

1 голос
/ 12 июля 2011

has_one допускает предложение :order, поэтому вы можете сделать это:

class Reader < ActiveRecord::Base
  has_many :books, :dependent => :destroy
  has_one :last_book, :class_name => "Book", :order => "books.created_at desc"
end

Тогда в вашем действии контроллера вы отбросите одно из ваших назначений

def create
  @reader = Reader.find(params[:reader_id])
  @book = @reader.books.new (params[:book])
end

ДжеффОтвет Смита также верен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...