J'essaie de suivre Ryan Bates RailsCast # 196: Modèle imbriqué partie 1 . Il y a deux différences apparentes avec la version Ryans: 1) j'utilise un échafaudage intégré et pas astucieux comme il l'utilise, et 2) je lance Rails 4 (je ne le fais pas sais vraiment quelle version Ryans utilise dans son casting, mais ce n'est pas 4).
Voici donc ce que j'ai fait
Rails new survey2
cd survey2
bundle install
Rails generate scaffold survey name:string
rake db:migrate
Rails generate model question survey_id:integer content:text
rake db:migrate
Ensuite, j'ai ajouté les associations aux modèles comme ça
class Question < ActiveRecord::Base
belongs_to :survey
end
et donc
class Survey < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions
end
Ensuite, j'ai ajouté la partie vue imbriquée
<%= form_for(@survey) do |f| %>
<!-- Standard Rails 4 view stuff -->
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.fields_for :questions do |builder| %>
<div>
<%= builder.label :content, "Question" %><br/>
<%= builder.text_area :content, :rows => 3 %>
</div>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
et enfin le contrôleur pour que 3 questions soient créées chaque fois qu'une nouvelle enquête est instanciée
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
# Standard Rails 4 index and show
# GET /surveys/new
def new
@survey = Survey.new
3.times { @survey.questions.build }
Rails.logger.debug("New method executed")
end
# GET /surveys/1/edit
def edit
end
# Standard Rails 4 create
# PATCH/PUT /surveys/1
# PATCH/PUT /surveys/1.json
def update
respond_to do |format|
if @survey.update(survey_params)
format.html { redirect_to @survey, notice: 'Survey was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @survey.errors, status: :unprocessable_entity }
end
end
end
# Standard Rails 4 destroy
private
# Use callbacks to share common setup or constraints between actions.
def set_survey
@survey = Survey.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit(:name, questions_attributes: [:content])
end
end
Donc, créer une nouvelle enquête avec trois questions est très bien. Cependant, si j'essaie de modifier l'une des enquêtes, les trois questions d'origine sont conservées, tandis que trois autres supplémentaires sont créées. Donc, au lieu d'avoir 3 questions pour le sondage édité, j'en ai maintenant 6. J'ai ajouté
Rails.logger.debug("New method executed")
à la nouvelle méthode dans le contrôleur, et pour autant que je sache, elle n'est pas exécutée lorsque je fais une opération d'édition. Quelqu'un peut-il me dire ce que je fais mal?
Toute aide est grandement appréciée!
Alors je l'ai compris. Je devais ajouter :id
aux paramètres autorisés dans le survey_params
méthode. Cela ressemble maintenant à ceci:
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit(:name, questions_attributes: [:id, :content])
end
qui fonctionne parfaitement. Je suis un débutant RoR, alors veuillez prendre mon analyse avec un grain de sel, mais je suppose que ces nouveaux identifiants ont été générés au lieu d'être transmis à l'action de mise à jour. J'espère que cela aide quelqu'un d'autre là-bas.
En utilisant cocoon
gem sur Rails 4, je recevais toujours des champs en double même après avoir ajouté :id
À la liste autorisée lors de la modification. Remarqué ce qui suit également
Unpermitted parameters: _destroy
Unpermitted parameters: _destroy
J'ai donc ajouté le champ :_destroy
Au champ model_attributes:
Autorisé et les choses se sont bien déroulées après cela.
Par exemple...
def survey_params
params.require(:survey).permit(:name, questions_attributes: [:id, :content, :_destroy])
end