Come salvare un record che associa tra ha-molte classi in Ruby on Rails
-
16-09-2019 - |
Domanda
Ho creato tre classi per rappresentare Libri , La gente e BookLoans . Mentre io sono in grado di mostrare l'associazione delle persone ai libri attraverso BookLoans Sono stato semina il mio database.
Ora ho bisogno di salvare un checkout di un libro. Era mia intenzione di fare questa azione attraverso il controller libro. In particolare, la creazione di un'azione di prestito in BooksController. Anche se questo ha senso per me, in teoria, io sto avendo un tempo terribile attuare la sintassi appropriata.
Ho aggiunto la capacità di prestito un libro dalla vista spettacolo di un libro. Questo punto di vista ora contiene una forma che utilizza l'azione di prestito del controller libro per registrare il prestito.
Ho aggiunto che cosa credo sono i metodi appropriati per il mio modello Libro. Con l'aiuto di theIV ho catturato le informazioni appropriate nel controller. Purtroppo, quando si preme di prestito nello show libro visualizzare un record book_loan c'è essere registrati.
Che cosa mi manca?
Prenota Modello
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
Prestito Metodo da BooksController
def loan
@book.add_loan(params[:book_loan][:person_id])
redirect_to :action => 'book', :id => params[:id]
end
Prenota Mostra vista w / Prestito Modulo
<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 Modello
class BookLoan < ActiveRecord::Base
belongs_to :book
belongs_to :person
end
Persona Modello
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
Sviluppo Log
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
Soluzione
Quando si has_many
un modello, è possibile accedere a un paio di metodi di troppo, due in particolare sono collection.build
e collection.create
build
- è come new
, create
è come create
:). Date un'occhiata alla ha molte documentazione . In questo caso, si potrebbe riscrivere add_loan come
def add_loan (person_id)
book_loans.create(:book_id => id,
:person_id => person_id,
:out_date => Date.current)
end
o qualcosa di simile.
Per rispondere alla tua domanda su ciò che la vista sarà l'invio al controller, invierà l'hash params
come al solito, ma se si desidera solo per passare il person_id
a add_loan
, è possibile estrarre questo. Supponendo che la parte della vista che avete sopra è avvolto in una forma di un prestito del libro, è possibile accedere alla persona da params[:book_loan][:person_id]
. Si potrà anche fare un ritrovamento in quell'azione prima, altrimenti @book
sta per essere nullo.
Spero che questo aiuti. Cin cin.
EDIT: Non sono sicuro se il modo in cui lo avete in questo momento funziona, ma penso che si desidera cambiare il vostro modello Person
di leggere
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
EDIT 2: Il registro sviluppo dice che non sono in realtà colpire loan
, si sta colpendo update
. Un paio di cose che si potrebbero fare: controllare per assicurarsi di aver loan
come una risorsa quotata in vostri itinerari; unire l'azione loan
nel update
azione potrebbe iniziare a ricevere sorta di disordinato in modo da non so se questo è l'approccio migliore. Sono sicuro che ci sono più, ma queste sono le prime cose che compaiono in mente. Inoltre, non so se è possibile aggiungere :action => 'loan'
a un tag inviare. Penso che sarà basta guardare che, come se si trattasse di un'opzione HTML. Si potrebbe desiderare di cambiare la vostra form_for
di leggere
<% form_for(@book), :url => { :action => 'loan' } do |x| %>
una volta che hai fatto in modo che i percorsi sono in ordine. Ma, come ho detto prima, sono abbastanza sicuro che si sarà gettato un errore che l'azione perché non avete definito un Book.find
per esso.