Как установить значение по умолчанию has_one в ActiveRecord? - PullRequest
2 голосов
/ 18 сентября 2010

У меня есть что-то вроде этого:

class User < ActiveRecord::Base
  has_one :profile
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

user = User.new
user.profile.something #=> ERROR

Каков правильный способ установки объекта профиля по умолчанию в этом случае? Я пробовал это:

class User < ActiveRecord::Base
  default_scope :include => :profile
  has_one :profile

  def after_initialize
    self.profile ||= Profile.new(:user => self)
  end
end

... но это создает N + 1 запросов. Есть идеи?

Обновление

Это то, что у меня сейчас, работает нормально, все еще ищу что-то получше:

class User < ActiveRecord::Base
  default_scope :include => :profile
  has_one :profile, :autosave => true

  def after_initialize
    self.profile = Profile.new(:user => self) if new_record?
  end
end

Таким образом, у вас будет профиль, когда вы наконец create станете вашим пользователем. В противном случае единственным случаем является new_record?.

Ответы [ 4 ]

3 голосов
/ 14 октября 2011

Вы можете написать свой собственный профиль # пользователя, который создаст его для вас, если он не существует:

class User < ActiveRecord::Base
  has_one :profile

  def profile_with_default
    profile_without_default || build_profile
  end
  alias_method_chain :profile, :default
end
1 голос
/ 18 сентября 2010

Я думаю, что ваш ответ хороший.У меня немного другое решение:

class User < ActiveRecord::Base
  default_scope :include => :profile
  has_one :profile
  alias_method :my_profile, :profile

  def my_profile
    self.profile = Profile.create(:user => self) unless self.profile
    self.profile
  end
end

Хорошо

  • создавать профиль по запросу, а не по его экземпляру

Не очень хорошо

  • Вы должны использовать my_profile (или как бы вы хотели его назвать)
  • Чек unless self.profile должен бытьна каждом профиле звоните
0 голосов
/ 21 февраля 2016

Это хороший ответ:

class User < ActiveRecord::Base
 has_one :preference_set

 def preference_set
   super || build_preference_set
  end
end
0 голосов
/ 18 сентября 2010

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

Обратный вызов after_initialize вызывается после создания экземпляра объекта, так что это не очень хорошее место для такой логики.

Может быть, вам стоит попробовать использовать before_create / after_create? Эти обратные вызовы вызываются только во время создания объекта.

Кроме того, не используйте Profile.new, используйте один из методов ниже:

self.build_profile(...)
self.create_profile(...)

Во втором случае модель сохраняется. Вы можете передать хэш с атрибутами модели обоим методам (не передавать: пользователь, поскольку он устанавливается автоматически).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...