Development Tip

Rails-모범 사례 : 종속적 인 has_one 관계를 만드는 방법

yourdevel 2020. 10. 20. 08:17
반응형

Rails-모범 사례 : 종속적 인 has_one 관계를 만드는 방법


has_one 관계를 만드는 가장 좋은 방법이 무엇인지 말씀해 주시겠습니까?

fe 사용자 모델이 있고 프로필이 있어야합니다.

어떻게 할 수 있습니까?

한 가지 해결책은 다음과 같습니다.

# user.rb
class User << ActiveRecord::Base
  after_create :set_default_association

  def set_default_association
    self.create_profile
  end
end

하지만 그다지 깨끗하지 않은 것 같습니다 ... 어떤 제안이 있습니까?


has_one 관계를 만드는 모범 사례 before_createafter_create. 또는 더 이른 콜백을 사용하고 자체 검증 단계를 통과하지 못하는 하위 문제 (있는 경우)를 처리합니다.

때문에:

  • 좋은 코딩을 사용하면 유효성 검사가 실패 할 경우 하위 레코드의 유효성 검사가 사용자에게 표시 될 수 있습니다.
  • ActiveRecord에 의해 더 깨끗하고 명시 적으로 지원됩니다. AR은 부모 레코드를 저장 한 후 (생성시) 하위 레코드의 외래 키를 자동으로 채 웁니다. 그런 다음 AR은 상위 레코드 작성의 일부로 하위 레코드를 저장합니다.

방법 :

# in your User model...
has_one :profile
before_create :build_default_profile

private
def build_default_profile
  # build default profile instance. Will use default params.
  # The foreign key to the owning User model is set automatically
  build_profile
  true # Always return true in callbacks as the normal 'continue' state
       # Assumes that the default_profile can **always** be created.
       # or
       # Check the validation of the profile. If it is not valid, then
       # return false from the callback. Best to use a before_validation 
       # if doing this. View code should check the errors of the child.
       # Or add the child's errors to the User model's error array of the :base
       # error item
end

귀하의 솔루션은 확실히 그것을 수행하는 적절한 방법이지만 (적어도 성장할 때까지) 단순화 할 수 있습니다.

# user.rb
class User < ActiveRecord::Base
  has_one      :profile
  after_create :create_profile
end

이것이 기존 대규모 데이터베이스의 새 연결 인 경우 다음과 같이 전환을 관리합니다.

class User < ActiveRecord::Base
  has_one :profile
  before_create :build_associations

  def profile
    super || build_profile(avatar: "anon.jpg")
  end

private
  def build_associations
    profile || true
  end
end

따라서 기존 사용자 레코드는 요청시 프로필을 얻고 새 레코드가 만들어집니다. 이것은 또한 기본 속성을 한 곳에 배치하고 Rails 4 이후부터 accepts_nested_attributes_for와 함께 올바르게 작동합니다.


Probably not the cleanest solution, but we already had a database with half a million records, some of which already had the 'Profile' model created, and some of which didn't. We went with this approach, which guarantees a Profile model is present at any point, without needing to go through and retroactively generate all the Profile models.

alias_method :db_profile, :profile
def profile
  self.profile = Profile.create(:user => self) if self.db_profile.nil?
  self.db_profile
end

Here's how I do it. Not sure how standard this is, but it works very well and its lazy in that it doesn't create extra overhead unless it's necessary to build the new association (I'm happy to be corrected on this):

def profile_with_auto_build
  build_profile unless profile_without_auto_build
  profile_without_auto_build
end

alias_method_chain :profile, :auto_build

This also means that the association is there as soon as you need it. I guess the alternative is to hook into after_initialize but this seems to add quite a bit of overhead as it's run every time an object is initialized and there may be times where you don't care to access the association. It seems like a waste to check for its existence.


There is a gem for this:

https://github.com/jqr/has_one_autocreate

Looks like it is a bit old now. (not work with rails3)

참고URL : https://stackoverflow.com/questions/3808782/rails-best-practice-how-to-create-dependent-has-one-relations

반응형