What I want to do
노래라는 모델이 있고 이 노래모델을 수정하는 사람이 작곡가, 가수, 작사가가 있다고 해보자
이 노래 모델을 마지막에 수정한 사람이 누구인지 체크하기 위해
latest_modified_by라는 테이블이 있고
modified_by_user_type
modified_by_user_id
라는 정보가 있다고 해보자
modified_by모델에 has_one :modified_by_user
를 지정하고 수정한 사람이 누구냐에 따라(modified_by_user_type) 다른 모델을 참고하게 할 수 있는 방법이 없을까?
선결론
has_one에 지정하는 class_name을 조건에 따라 동적으로 바꿔주면 가능하다고 생각했다.
proc등을 선언하면 왠지 될법 싶었는데 의외로 class_name에는 proc사용이 안됨
결론 class_name을 동적으로 바꾸는건 불가능
대안으로 아래와 같이 3개의 has_one을 선언하고 modified_by_user메소드를 선언해서 type에 따라 어느 has_one을 선택할지 바꿔주도록 했다.
has_one :가수, primary_key: :modified_by_user_id, foreign_key: :id
has_one :작사가, primary_key: :modified_by_user_id, foreign_key: :id
has_one :작곡가, primary_key: :modified_by_user_id, foreign_key: :id
private :가수, :작사가, :작곡가 # 직접 참조 못하게끔 강제하기 위해
def modified_by_user
return nil if modified_by_user_type.nil?
return 가수 if modified_by_user_type == '가수'
return 작사가 if modified_by_user_type == '작사가'
return 작곡가 if modified_by_user_type == '작곡가'
nil
end
위와같이 선언후
노래.first.latest_modified_by.modified_by_user
방법으로 다이나믹하게 수정한 유저의 모델을 가져올 수 있었다.(가수 or 작사가 or 작곡가)
여러가지 삽질
삼항연산자는 사용가능
has_one :test5, primary_key: :modified_by_user_id, foreign_key: :id, class_name: false ? '가수' : '작곡가'
삼항연산자 자체는 사용이 가능한데 false부분에 self지정이 불가능..(의미가 없잖아)
선언한 메소드를 참조 못함
has_one :test3, primary_key: :modified_by_user_id, foreign_key: :id, class_name: xx
def xx
end
와 같은 방법으로는 xx를 찾을 수 없다고 나옴. class_name은 모델만 참조하기 때문
lambda
has_one :test7, primary_key: :modified_by_user_id, foreign_key: :id, :class_name -> klass { klass.is_a?(User) ? :phone_number : :mobile_number
x같은 문법이라고 혼남
class_name은 안돼지만..
has_one :yy
def yy
end
이런 방법은 선언이가능