validar rails polimorficas formulario asociaciones ruby-on-rails validation models nested-forms

ruby-on-rails - polimorficas - rails asociaciones



Rails: validar la presencia de parent_id en la asociaciĆ³n has_many (7)

Creo que tienes el mismo problema que traté. Tengo dos modelos, Cuenta y Usuario, y cuando se crea la cuenta, el primer usuario se crea a través de @account.users.build . El modelo de usuario tiene una validates_presence_of :account validación de validates_presence_of :account .

Para hacer la primera validación de paso de usuario, agregué el siguiente código a mi modelo de Cuenta:

before_validation_on_create :initialize_users def initialize_users users.each { |u| u.account = self } end

Tengo un recurso de proyectos que tiene muchas tareas. Quiero asegurarme de que cada tarea tenga un project_id de proyecto agregando validates_presence_of :project_id al modelo de tareas.

Sin embargo, al crear un nuevo proyecto con tareas, el project_id no estará disponible hasta que el registro se guarde, por lo tanto no puedo usar validates_presence_of :project_id .

Entonces, mi pregunta es, ¿cómo validar la presencia de project_id en el modelo de tarea? Quiero asegurar que cada tarea tenga un padre.

...

class Project < ActiveRecord::Base has_many :tasks, :dependent => :destroy accepts_nested_attributes_for :tasks, :allow_destroy => true

...

class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project_id


En realidad necesitas tanto:

validates_presence_of project validates_presence_of project_id

De esa manera, la tarea no se guardará en ninguno de los siguientes casos, suponiendo que solo haya 2 proyectos válidos en la base de datos, es decir, el ID del proyecto 99 no es válido:

task.project_id = 99 task.save task.project = Project.new task.save

Espero que esto sea de ayuda para alguien.



Tal vez no entiendo algo, pero parece que estás intentando engañar a los carriles. ¿Por qué no haces esto así?

class Task < ActiveRecord::Base belongs_to :project validate_presence_of :project end


Tu código funciona:

  • Si valida_presence_of: project, entonces mientras el proyecto esté allí, se validará. Pero si su proyecto no está guardado, aún podría guardar la tarea.
  • Si valida_presence_of: project_id, entonces el entero debe estar allí, indicando un valor guardado.

Aquí está rSpec que demuestra el punto. Si valida: project_id, no puede guardar una tarea sin guardar el proyecto.

class Task < ActiveRecord::Base belongs_to :project end

/specs/model_specs/task_spec.rb

require File.dirname(__FILE__) + ''/../spec_helper'' describe Task do before(:each) do @project = Project.new end it "should require a project_id, not just a project object" do task = Task.new task.project = @project Task.instance_eval("validates_presence_of :project_id") task.valid?.should == false end it "should not be valid without a project" do task = Task.new task.project = @project Task.instance_eval("validates_presence_of :project") task.valid?.should == false task.save.should == false end end


Tu clase de Project debe definir

accepts_nested_attributes_for :tasks

Consulte el Formulario modelo anidado en Railscasts para obtener más detalles sobre cómo realizar el formulario.

EDITAR:

En tu formulario deberías tener algo como esto:

_form.html.erb

<% form_for @project do |f| %> # project fields... <% f.fields_for :tasks do |builder| %> <%= render ''task_fields'', :f => builder %> <% end %> <p><%= link_to_add_fields "Add task", f, :tasks %></p> <%= f.submit %> <% end %>

_task_fields.html.erb

<%= f.label :name, "Task name:" %> <%= f.text_field :name %> # task fields... <%= link_to_remove_fields "Delete task", f, :tasks %>

link_to_add_fields y link_to_remove_fields son métodos definidos en application_helper para agregar / eliminar campos dinámicamente.


Vea here para la respuesta definitiva:

class Project < ActiveRecord::Base has_many :tasks, :dependent => :destroy, :inverse_of => :project accepts_nested_attributes_for :tasks, :allow_destroy => true class Task < ActiveRecord::Base belongs_to :project validates_presence_of :project

No es tan elegante si me preguntas ... Debe validar de forma transparente.