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
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top