recursos rails formularios anidados ruby-on-rails strong-parameters

ruby-on-rails - anidados - formularios en ruby on rails



Rieles: cómo rellenar el Id. De objeto padre utilizando atributos anidados para el objeto hijo y parámetros potentes. (1)

Entonces, el problema con el que se está encontrando es que los objetos secundarios no pasan la validación, ¿verdad? Cuando los objetos secundarios se crean al mismo tiempo que el elemento primario, es posible que los objetos secundarios no puedan conocer la identificación de sus padres para pasar la validación, es cierto.

Aquí es cómo puedes resolver ese problema. Cambie sus modelos de la siguiente manera:

# app/models/survey.rb class Survey belongs_to :user has_many :questions, :inverse_of => :survey accepts_nested_attributes_for :questions end # app/models/question.rb class Question validates :survey, :presence => true belongs_to :survey end

Las diferencias aquí son las siguientes :inverse_of pasado a la asociación has_many , y que la Question ahora valida en just :survey lugar de :survey_id .

:inverse_of hace de modo que cuando un objeto secundario se crea o construye usando la asociación, también recibe una referencia retrospectiva al padre que lo creó. Esto parece algo que debería suceder automáticamente, pero desafortunadamente no lo hace a menos que especifiques esta opción.

Validar en :survey lugar de en :survey_id es una especie de compromiso. La validación ya no es simplemente verificar la existencia de algo que no esté en blanco en el campo survey_id; ahora realmente comprueba la asociación por la existencia de un objeto principal. En este caso, es conocido por :inverse_of , pero en otros casos tendrá que cargar la asociación de la base de datos usando el id para validar. Esto también significa que los identificadores que no coinciden con nada en la base de datos no pasarán la validación.

Espero que ayude.

Tengo una situación muy parecida a la presentada en Railscast 196-197: Formulario de modelo anidado . Sin embargo, he encontrado un conflicto entre este enfoque y los parámetros fuertes. No puedo encontrar una buena forma de rellenar el campo de identificación de registro padre en el objeto hijo, ya que no quiero que se pueda asignar a través del formulario (para evitar que los usuarios asocien registros secundarios a registros principales que no son de su propiedad) ) Tengo una solución (vea el código a continuación) pero parece ser el tipo de cosas que Rails podría tener una manera inteligente y fácil de hacer por mí.

Aquí está el código ...

Hay un objeto principal (llámalo Encuesta) que tiene muchos objetos secundarios (llámalos Preguntas):

# 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

Hay un formulario que permite a los usuarios crear una encuesta y las preguntas de esa encuesta al mismo tiempo (para simplificar, el código siguiente trata las encuestas como si solo tuvieran una pregunta):

# 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 %>

El problema es el controlador. Quiero proteger el campo survey_id en el registro de preguntas a través de parámetros potentes, pero al hacerlo, las preguntas no pasan la validación, ya que survey_id es un campo obligatorio.

# 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 única forma en que puedo pensar para resolver este problema es crear las preguntas por separado de la encuesta como esta:

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)

ACTUALIZAR

Tal vez la mejor manera de manejar este problema es factorizar un "objeto de formulario" como se sugiere en esta publicación del blog Code Climate . Sin embargo, estoy dejando la pregunta abierta, ya que tengo curiosidad por otros puntos de vista