Comment sauvegarder un enregistrement dans l'association entre-a de nombreuses classes dans Ruby on Rails
-
16-09-2019 - |
Question
J'ai créé trois classes pour représenter Livres , Les gens et BookLoans . Alors que je suis en mesure de démontrer l'association des gens à travers Livres BookLoans Je suis ensemencement ma base de données.
Je dois maintenant enregistrer une caisse d'un livre. Mon intention était de faire cette action par le contrôleur de livre. Plus précisément, la création d'une action de prêt dans le BooksController. Bien que cela me semble logique en théorie j'ai un mal fou à mettre en œuvre la syntaxe appropriée.
J'ai ajouté la possibilité de prêter un livre à la vue du spectacle d'un livre. Ce point de vue contient maintenant une forme qui utilise l'action de prêt du contrôleur comptable pour enregistrer le prêt.
J'ai ajouté ce que je crois, sont les méthodes appropriées à mon modèle de livre. Avec l'aide de theIV J'ai capturé les informations appropriées dans le contrôleur. Malheureusement, quand je presse prêt sur le salon du livre de visualiser un document book_loan est pas enregistré.
Qu'est-ce que je suis absent?
Modèle livre
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
Méthode de prêt de BooksController
def loan
@book.add_loan(params[:book_loan][:person_id])
redirect_to :action => 'book', :id => params[:id]
end
Réserver Afficher la vue w / Formulaire de prêt
<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 Modèle
class BookLoan < ActiveRecord::Base
belongs_to :book
belongs_to :person
end
Personne modèle
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
Développement 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
La solution
Lorsque vous has_many
un modèle, vous aurez accès à quelques méthodes supplémentaires, deux en particulier sont collection.build
collection.create
et build
- est comme new
, create
est comme create
:). Jetez un oeil à la a beaucoup de documentation . Dans ce cas, vous pouvez réécrire add_loan comme
def add_loan (person_id)
book_loans.create(:book_id => id,
:person_id => person_id,
:out_date => Date.current)
end
ou quelque chose de similaire.
Pour répondre à votre question sur ce que la vue va envoyer au contrôleur, il envoie le hachage params
comme d'habitude, mais si vous voulez juste passer le person_id
à add_loan
, vous pouvez extraire cela. En supposant que la partie de la vue que vous avez ci-dessus est enroulé sous une forme d'un prêt de livres, vous pouvez accéder à la personne par params[:book_loan][:person_id]
. Vous aurez également besoin de faire une trouvaille dans cette première action, ou bien @book
va être nulle.
Espérons que cela aide. Vive.
EDIT: Je ne sais pas si la façon dont vous avez cela fonctionne en ce moment, mais je pense que vous voulez changer votre modèle Person
à lire
class Person < ActiveRecord::Base
has_many :book_loans
has_many :books, :through => :book_loans
end
EDIT 2: Votre journal de développement dit que vous n'êtes pas réellement frapper loan
, vous frappez update
. Quelques choses que vous pouvez faire: vérifier pour vous assurer que vous avez loan
comme une ressource indiquée dans vos itinéraires; fusionner l'action loan
dans l'action pourrait commencer à obtenir update
genre de désordre, donc je ne sais pas si cela est la meilleure approche. Je suis sûr qu'il ya plus, mais ce sont les premières choses qui sautent à l'esprit. De plus, je ne sais pas si vous pouvez ajouter à un :action => 'loan'
soumettre étiquette. Je pense qu'il suffit de regarder que comme si elle était une option html. Vous pouvez modifier votre form_for
lire
<% form_for(@book), :url => { :action => 'loan' } do |x| %>
une fois que vous avez fait en sorte que les routes sont en ordre. Mais comme je le disais plus tôt, je suis sûr que vous serez jeté une erreur sur cette action parce que vous n'avez pas défini Book.find
pour elle.