Wie ein Assoziieren Datensatz speichern zwischen hat-viele Klassen in Ruby on Rails
-
16-09-2019 - |
Frage
ich drei Klassen erstellt haben zu repräsentieren Bücher Menschen und BookLoans . Während ich bin in der Lage, die Vereinigung von Menschen zu Büchern durch BookLoans zu zeigen, ich habe meine Datenbank gewesen Impfen.
Ich brauche jetzt eine Kasse eines Buches zu speichern. Es war meine Absicht, diese Aktion durch das Buch Controller zu tun. Insbesondere ein Darlehen Aktion in dem BooksController zu schaffen. Während dies macht Sinn für mich in der Theorie ich eine schreckliche Zeit habe die entsprechende Syntax implementieren.
Ich habe die Möglichkeit hinzugefügt, ein Buch aus der Show Ansicht eines Buchs zu leihen. Diese Ansicht enthält nun eine Form, die das Darlehen Aktion des Buches Controller verwendet das Darlehen aufzunehmen.
Ich habe hinzugefügt, was ich glaube, dass die entsprechenden Methoden zu meinem Buch Modell sind. Mit Hilfe von theIV Ich habe die entsprechenden Informationen im Controller erfasst. Leider, wenn ich Loan auf dem Buch zeigen drücke ein book_loan Datensatz anzuzeigen aufgezeichnet kein Wesen.
Was bin ich fehlt?
Buch Modell
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
Loan-Methode von BooksController
def loan
@book.add_loan(params[:book_loan][:person_id])
redirect_to :action => 'book', :id => params[:id]
end
Buch Show View w / Leihformular
<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 Modell
class BookLoan < ActiveRecord::Base
belongs_to :book
belongs_to :person
end
Person Modell
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
Entwicklung 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
Lösung
Wenn Sie ein Modell has_many
, haben Sie Zugriff auf ein paar zusätzliche Methoden bekommen, zwei insbesondere sind collection.build
und collection.create
- build
ist wie new
, create
ist wie create
:). Haben Sie einen Blick auf die viele Dokumentation hat . In diesem Fall könnte man umschreiben add_loan als
def add_loan (person_id)
book_loans.create(:book_id => id,
:person_id => person_id,
:out_date => Date.current)
end
oder etwas ähnliches.
Um Ihre Frage zu beantworten, was die Sicht wird an die Steuerung das Senden, wird es den params
Hash wie gewohnt schicken, aber wenn Sie nur die person_id
add_loan
übergeben wollen, können Sie das extrahieren. Unter der Annahme, dass der Teil der Ansicht, die Sie oben haben in einer Form für ein Buch Darlehen gewickelt sind, können Sie die Person, die von params[:book_loan][:person_id]
zugreifen können. Sie wollen auch zuerst einen Fund in dieser Aktion zu tun, sonst @book
ist gleich Null sein wird.
Hoffe, das hilft. Prost.
EDIT: Ich bin nicht sicher, ob die Art und Weise Sie es gerade jetzt funktioniert, aber ich denke, Sie Person
Modell ändern möchten, lesen
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
EDIT 2: Ihre Entwicklung log sagt, Sie sind nicht wirklich loan
schlagen, Sie schlagen update
. Ein paar Dinge, die Sie tun können: überprüfen, um sicherzustellen, dass Sie als börsennotierte Ressource in Ihren Routen loan
; verschmelzen die loan
Aktion in die update
aktions könnte beginnen Art chaotisch bekommen, damit ich weiß nicht, ob dies der beste Ansatz ist. Ich bin sicher, es gibt mehr, aber das sind die ersten Dinge, die den Sinn Pop. Auch ich weiß nicht, ob Sie :action => 'loan'
zu einem einreichen Tag hinzufügen können. Ich denke, es wird nur das betrachten, als ob es sich um eine HTML-Option waren. Vielleicht möchten Sie Ihre form_for
ändern lesen
<% form_for(@book), :url => { :action => 'loan' } do |x| %>
, wenn Sie sich vergewissert haben, dass die Wege in Ordnung sind. Aber wie ich bereits sagte, ich bin ziemlich sicher, dass Sie auf diese Aktion ein Fehler ausgelöst werden, da Sie kein Book.find
für sie definiert haben.