Rails opcional pertenece a


Estoy escribiendo una interfaz Rails para la gestión de inventario. Quiero que los usuarios puedan registrar productos, así que tengo:

class User < ActiveRecord::Base
  has_many :products
  # <snip>
end

Y

class Product < ActiveRecord::Base
  belongs_to :user
  # <snip>
end

El problema es que los productos se crean antes de ser registrados por un usuario. Es decir, es perfectamente aceptable llamar a Product.create y simplemente establecer el user_id a nil. Como se puede imaginar, sin embargo, Rails no soporta esto fuera de la caja:

> Product.create!
   (0.3ms)  SELECT COUNT(*) FROM "products" WHERE "products"."type" IN ('Product')
   (0.1ms)  begin transaction
   (0.1ms)  rollback transaction
ActiveRecord::RecordInvalid: Validation failed: User can't be blank
    from ~/.rvm/gems/ruby-2.0.0-p0/gems/activerecord-3.2.13/lib/active_record/validations.rb:56:in `save!'

He pensado en un montón de soluciones de kludgey, el más atractivo de que es tener una subclase NullUser User y usarla para crear productos. Pero eso todavía parece un truco. ¿Cuál es el camino de los Rieles con esto?

Gracias.


La migración pertinente:

class AddUseridToProducts < ActiveRecord::Migration
  def change
    add_column :products, :user_id, :integer
  end
end

Y posteriores:

class Changeuseridtobeoptionalforproducts < ActiveRecord::Migration
  def change
    change_column :products, :user_id, :integer, null: true
  end
end
Author: tsm, 2013-05-22

3 answers

¿ Tiene una validación que requiere que el usuario esté presente? Si es así, quita eso.

 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-22 19:24:33

Solo una actualización para rails 5, si quieres este tipo de comportamiento tendrás que pasar esta opción:

belongs_to :user, optional: true

En Rails 5, siempre que definamos una asociación belongs_to, es necesario tener el registro asociado presente por defecto.

 146
Author: Alexis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-09 00:28:56

Rails absolutamente soporta esto fuera de la caja, marque su migración, ¿ha incluido una restricción como :null => false en la línea user_id? Si es así, ¡sácalo!

Editar: O como dice @Rodrigo Dias, invertirlo a :null => true.

Además, compruebe que no tiene ninguna validación en la relación de usuario en el modelo de Producto.

 3
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-22 19:25:29