0

我创建了三个类来表示BooksPeopleBookLoans。虽然我能够通过 BookLoans 显示人与书籍的关联,但我一直在为我的数据库播种。

我现在需要保存一本书的结帐。我打算通过图书控制器执行此操作。具体来说,在 BooksController 中创建一个贷款操作。虽然这在理论上对我来说很有意义,但我在实施适当的语法时遇到了可怕的事情。

我添加了从书的显示视图借书的功能。这个视图现在包含一个表单,它使用账簿控制器的贷款操作来记录贷款。

我已经在我的 Book 模型中添加了我认为合适的方法。在theIV的帮助下,我在控制器中捕获了适当的信息。不幸的是,当我在图书展示视图上按贷款时,没有记录 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 %>

图书贷款模式

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
4

1 回答 1

1

当你has_many是一个模型时,你可以访问一些额外的方法,特别是两个是collection.buildcollection.create-build就像newcreate就像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_idto 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为它定义 a 。

于 2009-09-24T18:09:03.657 回答