Rails — comment remplir parent id de l'objet utilisant des attributs de l'objet enfant et des paramètres de poids?
J'ai une situation semblable est présenté dans Railscast 196-197: Niché Modèle De Formulaire. Cependant, j'ai rencontré un conflit entre cette approche et des paramètres de poids. Je ne peux pas trouver un bon moyen pour remplir le parent de l'id d'enregistrement de domaine sur l'enfant objet, depuis je n'en veux pas à être cédés par le biais du formulaire (pour empêcher les utilisateurs d'associer des enregistrements enfants à des enregistrements parents qu'ils ne possèdent pas). J'ai une solution (voir le code ci-dessous), mais cela semble être le genre de chose Rails de pourrait avoir un intelligent, facile de le faire pour moi.
Voici le code...
Il y a un objet parent (appelez ça de l'Enquête) que has_many les objets enfants (appel des Questions):
# app/models/survey.rb
class Survey
belongs_to :user
has_many :questions
accepts_nested_attributes_for :questions
end
# app/models/question.rb
class Question
validates :survey_id, :presence => true
belongs_to :survey
end
Il y a un formulaire qui permet aux utilisateurs de créer un sondage et les questions sur l'enquête en même temps (pour des raisons de simplicité, le code ci-dessous traite des enquêtes qu'ils ont seulement la question):
# app/views/surveys/edit.html.erb
<%= form_for @survey do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.fields_for :questions do |builder| %>
<%= builder.label :content, "Question" %>
<%= builder.text_area :content, :rows => 3 %><br />
<% end %>
<%= f.submit "Submit" %>
<% end %>
Le problème est le contrôleur. Je veux protéger la survey_id de terrain sur la question de l'enregistrement via des paramètres de poids, mais ce faisant, les questions ne passe pas la validation, depuis le survey_id est un champ obligatoire.
# app/controllers/surveys_controller.rb
class SurveysController
def edit
@survey = Survey.new
Survey.questions.build
end
def create
@survey = current_user.surveys.build(survey_params)
if @survey.save
redirect_to @survey
else
render :new
end
end
private
def survey_params
params.require(:survey).permit(:name, :questions_attributes => [:content])
end
end
La seule façon que je peux penser pour résoudre ce problème est de construire les questions séparément à partir de l'enquête comme ceci:
def create
@survey = current_user.surveys.build(survey_params)
if @survey.save
if params[:survey][:questions_attributes]
params[:survey][:questions_attributes].each_value do |q|
question_params = ActionController::Parameters.new(q)
@survey.questions.build(question_params.permit(:content))
end
end
redirect_to @survey
else
render :new
end
end
private
def survey_params
params.require(:survey).permit(:name)
end
(Rails 4 beta 1, Ruby 2)
Mise à JOUR
Peut-être la meilleure façon de traiter ce problème est de factoriser un "objet de Formulaire" comme suggéré dans ce Code Climatique post de blog. Je suis en laissant la question ouverte, même si, comme je suis curieux de savoir à d'autres points de vue
- avez-vous comprendre comment résoudre ce problème à l'aide d'un formulaire imbriqué?
Vous devez vous connecter pour publier un commentaire.
Donc, le problème que vous rencontrez est que l'enfant objets ne passe pas la validation, à droite? Lorsque l'enfant les objets sont créés en même temps que le parent, l'enfant des objets, ne pouvait pas connaître le numéro d'identification de leur mère afin de passer de la validation, c'est vrai.
Ici est de savoir comment vous pouvez résoudre ce problème. Modifier vos modèles comme suit:
Les différences ici sont les
:inverse_of
passé à lahas_many
association, et que la Question est maintenant valide sur:survey
au lieu de:survey_id
.:inverse_of
qu'il fait en sorte que lorsqu'un enfant de l'objet est créé ou construit à l'aide de l'association, il reçoit également une référence arrière à la mère qui l'a créé. Cela semble être quelque chose qui doit se produire automatiquement, mais il n'est malheureusement pas, sauf si vous spécifiez cette option.Validation sur
:survey
au lieu de:survey_id
est une sorte de compromis. La validation n'est plus simplement de vérifier l'existence de quelque chose de non-vide dans le survey_id champ; il fait désormais de vérifications de l'association pour l'existence d'un objet parent. Dans ce cas, il est utile d'connue en raison du:inverse_of
, mais dans d'autres cas, il sera en fait la charge de l'association de la base de données à l'aide de la pièce d'identité pour valider. Cela signifie aussi que les id ne correspond pas à quoi que ce soit dans la base de données de validation.Espère que ça aide.
inverse_of
parce que notre relation estpolymorphic
?