web-dev-qa-db-fra.com

Rails 4 Forme: has_many à travers: cases à cocher

Question d'origine

Deux ressources: users et animals. Lors de la création d'un utilisateur, le client coche les cases pour indiquer le nombre d'animaux qu'il possède.

Lorsque le formulaire utilisateur est soumis, il doit non seulement créer un nouvel enregistrement user, mais il doit également créer un groupe d'enregistrements dans le animal_users table de jointure riche pour représenter chacune des cases à cocher sélectionnées par le client.

Je pense que le problème est que je ne spécifie pas quelque chose correctement pour la partie case à cocher dans le formulaire. J'ai regardé le checkbox_tag API , le Rails Guides on Forms , et de nombreux sites Web et publications stackOverflow.

Merci d'avance, code ci-dessous:

Code d'origine (code de réponse plus bas):

modèles:

#models/user.rb
class User < ActiveRecord::Base
  has_many :animals, through: :animal_users
  has_many :animal_users
  accepts_nested_attributes_for :animal_users, allow_destroy: true
end

#models/animal.rb
class Animal < ActiveRecord::Base
  has_many :users, through: :animal_users
  has_many :animal_users
end

#models/animal_user.rb
class AnimalUser < ActiveRecord::Base
  belongs_to :animal
  belongs_to :user
end

La forme user:

#views/users/_form.html.erb
    <%= form_for(@user) do |f| %>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>

  <div>
    <% Animal.all.each do |animal| %>
    <label>
        <%= check_box_tag "user[animal_ids][]", animal.id, f.object.animals.include?(animal) %>
        <%= animal.animal_name %>
    <% end %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Paramètres puissants dans users_controller.rb

def user_params
      params.require(:user).permit(:name, animal_users_attributes: [:_destroy, :id, :user_id, :animal_id])
end

Répondez ici :

modèles:

#models/user.rb
class User < ActiveRecord::Base
  has_many :animals, through: :animal_users
  has_many :animal_users
end

#models/animal.rb
class Animal < ActiveRecord::Base
  has_many :users, through: :animal_users
  has_many :animal_users
end

#models/animal_user.rb
class AnimalUser < ActiveRecord::Base
  belongs_to :animal
  belongs_to :user
end

La forme user:

#views/users/_form.html.erb
<%= form_for(@user) do |f| %>
  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>

  # Checkbox part of the form that now works!
    <div>
      <% Animal.all.each do |animal| %>
        <%= check_box_tag "user[animal_ids][]", animal.id, f.object.animals.include?(animal) %>
        <%= animal.animal_name %>
      <% end %>
    </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

Paramètres puissants dans users_controller.rb

  def user_params
    params.require(:user).permit(:name, animal_ids: [])
  end

Et juste pour être complet, voici ce qui est transmis au serveur lors de la soumission du formulaire:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"xyz=", "user"=>{"name"=>"Neil", "animal_ids"=>["1", "3"]}, "commit"=>"Create User"}
 Animal Load (0.2ms)  SELECT "animals".* FROM "animals"  WHERE "animals"."id" IN (1, 3)
  (0.1ms)  begin transaction
 SQL (0.2ms)  INSERT INTO "users" ("created_at", "name", "updated_at") VALUES (?, ?, ?)  [["created_at", "2015-03-26 15:29:00.478767"], ["name", "Neil"], ["updated_at", "2015-03-26 15:29:00.478767"]]
 SQL (0.1ms)  INSERT INTO "animal_users" ("animal_id", "created_at", "updated_at") VALUES (?, ?, ?)  [["animal_id", 1], ["created_at", "2015-03-26 15:29:00.479833"], ["updated_at", "2015-03-26 15:29:00.479833"]]
 SQL (0.0ms)  INSERT INTO "animal_users" ("animal_id", "created_at", "updated_at") VALUES (?, ?, ?)  [["animal_id", 3], ["created_at", "2015-03-26 15:29:00.480644"], ["updated_at", "2015-03-26 15:29:00.480644"]]
 SQL (0.1ms)  UPDATE "animal_users" SET "updated_at" = ?, "user_id" = ? WHERE "animal_users"."id" = 6  [["updated_at", "2015-03-26 15:29:00.481362"], ["user_id", 8]]
 SQL (0.1ms)  UPDATE "animal_users" SET "updated_at" = ?, "user_id" = ? WHERE "animal_users"."id" = 7  [["updated_at", "2015-03-26 15:29:00.482062"], ["user_id", 8]]
  (2.4ms)  commit transaction
36
Neil
<% Animal.all.each do |animal| %>
   <label>
      <%= check_box_tag "user[animal_ids][]", animal.id, f.object.animals.include?(animal) %>
      <%= animal.name %>
   </label>
<% end %>

et vous devez accepter un hachage avec un tableau d'ID sur les paramètres de votre contrôleur, quelque chose comme

{  animal_ids: [] }

peut-être que lire ceci peut aider: http://millarian.com/programming/Ruby-on-Rails/quick-tip-has_many-through-checkboxes/

33
Santiago Suárez

collection_check_boxes est une meilleure option:

<%= f.collection_check_boxes(:animal_ids, Animal.all, :id, :name) do |animal| %>
  <%= animal.label { animal.check_box } %>
<% end %>
34
webster