Как сохранить связывающую запись между классами has-many в Ruby on Rails

StackOverflow https://stackoverflow.com/questions/1472869

Вопрос

Я создал три класса для представления Книги, Люди, и КнигаКредиты.Хотя я могу показать связь людей с книгами через BookLoans, я заполняю свою базу данных.

Теперь мне нужно сохранить оформление заказа на книгу.Я намеревался выполнить это действие через контроллер книги.В частности, создание действия кредита в BooksController.Хотя теоретически это имеет для меня смысл, мне очень трудно реализовать соответствующий синтаксис.

Я добавил возможность одалживать книгу из режима показа книги.Это представление теперь содержит форму, которая использует действие ссуды контроллера книги для записи ссуды.

Я добавил в свою модель Book, как мне кажется, подходящие методы.С помощью IV Я зафиксировал соответствующую информацию в контроллере.К сожалению, когда я нажимаю «Ссуда» в режиме просмотра книги, запись book_loan не записывается.

Что мне не хватает?

Модель книги

class Book < ActiveRecord::Base
  has_many :book_loans
  has_many :borrowers, :through => :book_loans, :source => :person

  accepts_nested_attributes_for :book_loans, :allow_destroy => true

  def loaned?
    book_loans.exists?(:return_date => nil)
  end

  def current_borrower
    if loaned?
      book_loans.first(:order => "out_date desc").person
    end
  end

  def add_loan (person_id)
      book_loans.create(:book_id => id,
                        :person_id => person_id,
                        :out_date => Date.current)
  end
end

Метод кредита от BooksController

def loan
  @book.add_loan(params[:book_loan][:person_id])

  redirect_to :action => 'book', :id => params[:id]
end

Просмотр книжной выставки с формой займа

<p>
  <b>Title:</b>
  <%=h @book.title %>
</p>
<p>
  <b>Isbn10:</b>
  <%=h @book.isbn10 %>
</p>
<p>
  Currently loaned to:
  <%=h borrower_name(@book) %>
</p>

<% form_for(@book) do |x| %>
  <p>
    <%= x.label :loan_person_id %><br/>
    <%= collection_select(:book_loan, :person_id,
      Person.find(:all, :order => 'name ASC'), :id, :name) %>
    <%= x.submit 'Loan', :action => 'loan' %>
  </p>
<% end %>

Модель BookLoan

class BookLoan < ActiveRecord::Base
  belongs_to :book
  belongs_to :person
end

Модель человека

class Person < ActiveRecord::Base
  has_many :book_loans
  has_many :books, :through => :book_loans
end

Журнал разработки

Processing BooksController#update (for 127.0.0.1 at 2009-09-24 13:43:05) [PUT]
  Parameters: {"commit"=>"Loan", "authenticity_token"=>"XskHLuco7Q7aoEnDfVIiYwVrMEh5uwidvJZdrMbYYWs=", "id"=>"1", "book_loan"=>{"person_id"=>"3"}}
  [4;35;1mBook Columns (3.0ms)[0m   [0mSHOW FIELDS FROM `books`[0m
  [4;36;1mBook Load (4.0ms)[0m   [0;1mSELECT * FROM `books` WHERE (`books`.`id` = 1) [0m
  [4;35;1mSQL (0.0ms)[0m   [0mBEGIN[0m
  [4;36;1mBook Load (1.0ms)[0m   [0;1mSELECT `books`.id FROM `books` WHERE (`books`.`title` = BINARY 'Dreaming in Code: Two Dozen Programmers, Three Years, 4,732 Bugs, and One Quest for Transcendent Software' AND `books`.id <> 1) LIMIT 1[0m
  [4;35;1mSQL (1.0ms)[0m   [0mCOMMIT[0m
Redirected to http://localhost:3000/books/1
Completed in 19ms (DB: 10) | 302 Found [http://localhost/books/1]
  [4;36;1mSQL (0.0ms)[0m   [0;1mSET NAMES 'utf8'[0m
  [4;35;1mSQL (0.0ms)[0m   [0mSET SQL_AUTO_IS_NULL=0[0m
Это было полезно?

Решение

Когда ты has_many модели, вы получаете доступ к нескольким дополнительным методам, в частности двум collection.build и collection.createbuild как new, create как create :).Взгляните на имеет много документации.В этом случае вы можете переписать add_loan как

def add_loan (person_id)
  book_loans.create(:book_id   => id,
                    :person_id => person_id,
                    :out_date  => Date.current)
end

или что-то подобное.

Чтобы ответить на ваш вопрос о том, что представление будет отправлять контроллеру, оно отправит params хэш, как обычно, но если вы просто хотите передать person_id к add_loan, вы можете извлечь это.Предполагая, что часть представленного выше представления заключена в форму для выдачи книги напрокат, вы можете получить доступ к этому человеку, выполнив params[:book_loan][:person_id].Вам также нужно сначала выполнить поиск в этом действии, иначе @book будет равен нулю.

Надеюсь это поможет.Ваше здоровье.

РЕДАКТИРОВАТЬ:Я не уверен, что то, что у вас есть сейчас, работает, но я думаю, вы хотите изменить свое Person модель для чтения

class Person < ActiveRecord::Base
  has_many :book_loans
  has_many :books, :through => :book_loans
end

РЕДАКТИРОВАТЬ 2:В вашем журнале разработки указано, что вы на самом деле не попадаете loan, ты бьешь update.Несколько вещей, которые вы могли бы сделать:проверьте, чтобы убедиться, что у вас есть loan как указанный ресурс в ваших маршрутах;объединить loan действие в update действие — может начать становиться беспорядочным, поэтому я не знаю, лучший ли это подход.Я уверен, что их больше, но это первое, что приходит на ум.Кроме того, я не знаю, можете ли вы добавить :action => 'loan' в тег отправки.Я думаю, что это будет выглядеть так, как будто это опция HTML.Возможно, вы захотите изменить свой form_for читать

<% form_for(@book), :url => { :action => 'loan' } do |x| %>

как только вы убедитесь, что маршруты в порядке.Но, как я уже говорил ранее, я почти уверен, что при этом действии вы получите сообщение об ошибке, поскольку вы не определили Book.find для этого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top