[RUBY-ON-RAILS] 여러 외래 키와 관련 레일
RUBY-ON-RAILS여러 외래 키와 관련 레일
나는 관계를 정의하는 하나 개의 테이블에 두 개의 열을 사용할 수 있어야합니다. 예를 들어 작업 응용 프로그램을 사용 그래서.
일을 시도 :
class User < ActiveRecord::Base
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to :owner, class_name: "User", foreign_key: "owner_id"
belongs_to :assignee, class_name: "User", foreign_key: "assignee_id"
end
그럼 Task.create (OWNER_ID : 1, assignee_id : 2)
이 날은 사용자가이 반환하지만 User.first.task는 아무 것도 반환하지 않습니다 사용자 하나 Task.first.assignee을 반환 Task.first.owner을 수행 할 수 있습니다. 어떤 작업이 사용자에 속해 있지 않기 때문에, 그들은 소유자 및 양수인에 속한다. 그래서,
2를 시도 :
class User < ActiveRecord::Base
has_many :tasks, foreign_key: [:owner_id, :assignee_id]
end
class Task < ActiveRecord::Base
belongs_to :user
end
그건 그냥 모두 같은 두 개의 외래 키가 지원하지 않는 것 실패합니다.
내가 원하는 그래서 User.tasks 말을 소유하고 작업을 할당 모두 사용자를 얻을 수있을 것입니다.
기본적으로 어떻게 든 Task.where의 쿼리와 동일 할 관계를 구축 (OWNER_ID || assignee_id == 1)
그게 가능합니까?
나는 finder_sql을 사용 찾는 게 아니에요,하지만 내가 원하는이 문제의 용인되지 응답 외모에 가까운 수 : 레일 - 여러 인덱스 키 협회
이 방법은 다음과 같을 것입니다 그래서,
3을 시도 :
class Task < ActiveRecord::Base
def self.by_person(person)
where("assignee_id => :person_id OR owner_id => :person_id", :person_id => person.id
end
end
class Person < ActiveRecord::Base
def tasks
Task.by_person(self)
end
end
나는 레일 4 일에 그것을 얻을 수 있지만, 나는 다음과 같은 오류가 점점 계속 :
ActiveRecord::PreparedStatementInvalid: missing value for :owner_id in :donor_id => :person_id OR assignee_id => :person_id
해결법
-
==============================
1.
class User < ActiveRecord::Base def tasks Task.where("owner_id = ? OR assigneed_id = ?", self.id, self.id) end end
has_many 제거 : 사용자 클래스의 작업을.
has_many 사용 : 우리가 테이블 작업에 USER_ID라는 이름의 열이하지 않는 작업은 전혀 이해가되지 않습니다.
내 경우는 내가이 문제를 해결하기 위해 무슨 짓을 :
class User < ActiveRecord::Base has_many :owned_tasks, class_name: "Task", foreign_key: "owner_id" has_many :assigned_tasks, class_name: "Task", foreign_key: "assignee_id" end class Task < ActiveRecord::Base belongs_to :owner, class_name: "User", foreign_key: "owner_id" belongs_to :assignee, class_name: "User", foreign_key: "assignee_id" # Mentioning `foreign_keys` is not necessary in this class, since # we've already mentioned `belongs_to :owner`, and Rails will anticipate # foreign_keys automatically. Thanks to @jeffdill2 for mentioning this thing # in the comment. end
이 방법은, 당신은뿐만 아니라 User.first.owned_tasks로 User.first.assigned_tasks를 호출 할 수 있습니다.
지금, 당신은 assigned_tasks 및 owned_tasks의 조합을 반환하는 작업이라는 방법을 정의 할 수 있습니다.
훨씬 가독성이 간다 그거 좋은 솔루션이 될 수 있지만,보기의 성능 지점에서, 그 다음의 작업을 얻기 위해, 두 개의 쿼리 대신 한 번으로 발급됩니다, 이제 훨씬 좋은, 그리고 것 두 쿼리의 결과뿐만 아니라 가입해야합니다.
그래서 사용자에 속하는 작업을 얻기 위해, 우리는 다음과 같은 방법으로 사용자 클래스에서 사용자 지정 작업 방법을 정의하는 것입니다 :
def tasks Task.where("owner_id = ? OR assigneed_id = ?", self.id, self.id) end
이 방법은, 그것은 하나 개의 쿼리에서 모든 결과를 가져올 것입니다, 우리는 병합하거나 어떤 결과를 결합하지 않을 것입니다.
-
==============================
2.레일 5에 예상대로 내가 뭔가 레일 (5)는 이제 기본 포함되어 나타납니다 더 이상 작품을 발견 위 @ 드레-HH의 대답에 확장 경우의 효과에 WHERE 절 tasks.user_id =?, 실패하는 더 USER_ID 컬럼이 없기 때문에 이 시나리오한다.
레일 5에 예상대로 내가 뭔가 레일 (5)는 이제 기본 포함되어 나타납니다 더 이상 작품을 발견 위 @ 드레-HH의 대답에 확장 경우의 효과에 WHERE 절 tasks.user_id =?, 실패하는 더 USER_ID 컬럼이 없기 때문에 이 시나리오한다.
나는 그것이 has_many 협회와 함께 작업을 진행하는 것은 여전히 가능하다 발견했습니다, 당신은 절 레일 추가 곳이 추가 unscope해야합니다.
class User < ApplicationRecord has_many :tasks, ->(user) { unscope(:where).where("owner_id = :id OR assignee_id = :id", id: user.id) } end
-
==============================
3.5 레일 :
5 레일 :
당신은 여전히 has_many 연결을 원하는 경우 절은 @Dwight 대답을 참조 기본값을 unscope해야합니다.
비록 User.joins (: 작업) 저를 준다
ArgumentError: The association scope 'tasks' is instance dependent (the scope block takes an argument). Preloading instance dependent scopes is not supported.
더 이상 가능한 한 당신은뿐만 아니라 @Arslan 알리 솔루션을 사용할 수 없습니다.
4 레일 :
class User < ActiveRecord::Base has_many :tasks, ->(user){ where("tasks.owner_id = :user_id OR tasks.assignee_id = :user_id", user_id: user.id) } end
갱신 1 : 에 관한 @JonathanSimmons 코멘트
이 범위를 사용자 모델을 통과 할 필요가 없습니다. 현재 사용자의 인스턴스가이 람다에 자동으로 전달됩니다. 이처럼 전화 :
user = User.find(9001) user.tasks
갱신 2 :
호출 has_many : 액티브 클래스의 작업이 어떤 클래스 변수에 람다 함수를 저장하고이 람다를 호출은 객체의 작업 방법을 생성하는 단지 멋진 방법입니다 것입니다. 생성 방법은 다음 의사 유사합니다 :
class User def tasks #define join query query = self.class.joins('tasks ON ...') #execute tasks_lambda on the query instance and pass self to the lambda query.instance_exec(self, self.class.tasks_lambda) end end
-
==============================
4.나는 이것에 대한 해결책을했다. 나는이 더 잘 할 수있는 방법에 어떤 포인터에 열려있어.
나는 이것에 대한 해결책을했다. 나는이 더 잘 할 수있는 방법에 어떤 포인터에 열려있어.
class User < ActiveRecord::Base def tasks Task.by_person(self.id) end end class Task < ActiveRecord::Base scope :completed, -> { where(completed: true) } belongs_to :owner, class_name: "User", foreign_key: "owner_id" belongs_to :assignee, class_name: "User", foreign_key: "assignee_id" def self.by_person(user_id) where("owner_id = :person_id OR assignee_id = :person_id", person_id: user_id) end end
이것은 기본적으로 has_many 협회를 무시하지만 아직도 내가 찾고 있던 액티브 :: 관계 개체를 반환합니다.
그래서 지금은 이런 식으로 뭔가를 할 수 :
User.first.tasks.completed 그 결과는 소유하거나 첫 번째 사용자에게 할당 된 모든 완료 작업입니다.
-
==============================
5.레일 5 있기 때문에 당신은 또한 액티브 안전한 방법 인 그렇게 할 수 있습니다 :
레일 5 있기 때문에 당신은 또한 액티브 안전한 방법 인 그렇게 할 수 있습니다 :
def tasks Task.where(owner: self).or(Task.where(assignee: self)) end
-
==============================
6.내 협회에 대한 답변과 레일 (복수) 외래 키 (3.2) : 모델에서 그들을 설명하고 마이그레이션을 작성하는 방법을 당신을 위해 단지입니다!
내 협회에 대한 답변과 레일 (복수) 외래 키 (3.2) : 모델에서 그들을 설명하고 마이그레이션을 작성하는 방법을 당신을 위해 단지입니다!
코드에 관해서는, 여기 내 수정은
class User < ActiveRecord::Base has_many :tasks, ->(user) { unscope(where: :user_id).where("owner_id = ? OR assignee_id = ?", user.id, user.id) }, class_name: 'Task' end class Task < ActiveRecord::Base belongs_to :owner, class_name: "User", foreign_key: "owner_id" belongs_to :assignee, class_name: "User", foreign_key: "assignee_id" end
경고: 당신이 새로운 기록하거나 편집 기존 레코드를 생성 RailsAdmin과 필요성을 사용하는 경우, 당신은 같은 것을 할 때이 해킹 문제가 발생할 것입니다 제가 suggested.Because을했습니다하지 마십시오 :
current_user.tasks.build(params)
그 이유는 사용 task.user_id 채우기 위해 current_user.id에 레일 만 USER_ID 같은 것이없는 것을 찾기 위해 시도 할 것입니다.
그래서, 박스 외부의 방법으로 내 해킹 방법을 고려하지만, 그렇게하지 않습니다.
from https://stackoverflow.com/questions/24642005/rails-association-with-multiple-foreign-keys by cc-by-sa and MIT license
'RUBY-ON-RAILS' 카테고리의 다른 글
[RUBY-ON-RAILS] ExecJS :: ProgramError : 예기치 않은 토큰 punc«(»예상 punc«:»레이크 자산을 실행 : 생산에 사전 컴파일 (0) | 2020.02.15 |
---|---|
[RUBY-ON-RAILS] belongs_to와 has_one의 차이점은 무엇입니까? (0) | 2020.02.15 |
[RUBY-ON-RAILS] 내가 어떻게 활성 레코드 레일에 두 개의 서로 다른 데이터베이스와 함께 작동합니까? (0) | 2020.02.15 |
[RUBY-ON-RAILS] 설치 MYSQL : 오류 : 빌드 보석 네이티브 확장에 실패 (0) | 2020.02.15 |
[RUBY-ON-RAILS] 어떻게 내 ActionMailer보기에 내보기 도우미를 사용 하는가? (0) | 2020.02.15 |