Rails необязательно принадлежит_to

Я пишу интерфейс Rails для управления запасами. Я хочу, чтобы пользователи могли регистрировать продукты, поэтому у меня есть:

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

а также

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

Проблема в том, что продукты создаются до регистрации пользователем. То есть вполне приемлемо вызвать Product.create и просто установить user_id в nil. Однако, как вы можете себе представить, Rails не поддерживает это из коробки:

> 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!'

Я думал о связке kludgey обходов, наиболее привлекательным из которых является иметь NullUser подклассов User и использовать его для создания продуктов. Но это все еще кажется взломом. Что такое Rails Way с этим?

Благодарю.


Соответствующая миграция:

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

и позже:

class Changeuseridtobeoptionalforproducts < ActiveRecord::Migration
  def change
    change_column :products, :user_id, :integer, null: true
  end
end

Ответ 1

У вас есть проверка, требующая присутствия пользователя? Если это так, удалите это.

Ответ 2

Просто обновление для rails 5, если вы хотите такое поведение, вам нужно будет передать эту опцию:

belongs_to :user, optional: true

В Rails 5 всякий раз, когда мы определяем ассоциацию own_to, требуется, чтобы соответствующая запись присутствовала по умолчанию.

Обновить
Если вы по-прежнему хотите использовать старое поведение по умолчанию, вы можете добавить конфигурацию в файл application.rb.

# /config/application.rb
config.active_record.belongs_to_required_by_default = false

обратите внимание: в ранних выпусках Rails 5 с этой конфигурацией были некоторые проблемы, но в настоящее время это исправлено, протестировано на версии-кандидате 5.2.3.

Ответ 3

Rails абсолютно поддерживает это из коробки, проверьте свой перенос, включили ли вы ограничение, например :null => false в строке user_id? Если да, вытащите его!

Изменение: Или, как утверждает @Rodrigo Dias, отмените его на :null => true.

Кроме того, убедитесь, что у вас нет валидации в отношении пользователя в модели продукта.