활성 레코드 delegated_type
delegated_type
를 추가하는 새로운 기능이 추가되었습니다. 이 블로그 게시물에서는 실제 프로젝트를 사용하여 Active Record 모델에서 delegated_type
를 사용하는 방법을 배우고 사용의 이점에 대해서도 논의합니다.프로젝트
학교 관리 시스템을 구현합니다. 시스템에는 다른 프로필이 있는
Users
가 있습니다. 예: 학생, 교사, 부서장, 지원 직원.해결책
delegated_type
로 넘어가기 전에 다양한 가능한 솔루션을 탐색할 것입니다.1. 단일 테이블 상속(STI)
이름에서 알 수 있듯이 단일 테이블 상속은 다양한 사용자 프로필의 모든 필드를 결합하여 단일 메가 테이블에 저장합니다. 특정 사용자 프로필에 필드가 필요하지 않은 경우 해당 값은
nil
입니다.이것이 결과 메가 테이블의 모양입니다.
ID
이름
레코드 유형
등급
부서 이름
서비스 카테고리
1
남자
학생
5
2
암사슴
학생
1
삼
보그
선생님
수학
4
에릭
선생님
영어
5
안나
support_staff
청소
6
베니스
support_staff
관리자
문제
2. 추상 클래스
이 방법에서는 추상 클래스를 사용하여 다양한 사용자 프로필 간에 사용되는 공유 코드의 범위를 지정합니다.
class User < ApplicationRecord
self.abstract_class = true
def say_hello
"Hello #{name}"
end
end
#Schema: students[ id, name, grade ]
class Student < User
end
#Schema: teachers[ id, name, department ]
class Teacher < User
end
예시
> Student.create(name: "John", grade: 1)
> Student.first.say_hello
"Hello John"
> Teacher.create(name: "Lisa", department: "English")
> Teacher.first.say_hello
"Hello Lisa"
문제
Users
의 페이지 매김을 구현하는 것은 불가능합니다. 시도해야 하는 경우에도 적절한 제한 및 오프셋 없이 두 테이블을 동시에 쿼리해야 합니다. 3. 연관이 있는 여러 테이블
여기에서 하나의 상위 테이블을 사용하여 모든 공통 테이블 속성을 추출하고 Active Record 연결을 사용하여 프로필별 데이터를 참조합니다.
#Schema: users[ id, name ]
class User < ApplicationRecord
has_one :student_profile, class_name: "Student"
has_one :teacher_profile, class_name: "Teacher"
enum user_type: %i(student teacher)
def say_hello
"Hello #{name}"
end
def profile
return student_profile if self.student?
return teacher_profile if self.teacher?
end
end
#Schema: teachers[ id, department, user_id ]
class Teacher < ApplicationRecord
end
#Schema: students[ id, grade, user_id ]
class Student < ApplicationRecord
end
예시
> User.where(name: "John").first.profile.grade
1
> User.where(name: "John").say_hello
"Hello John"
> User.where(name: "Lisa").first.profile.department
"English"
> User.where(name: "Lisa").say_hello
"Hello Lisa"
4. 액티브 레코드 delegated_type
delegated_type
와 함께 Active Record를 사용하는 것은 연관이 있는 다중 테이블과 유사하지만 모든 조건부 코드를 추상화하여 깔끔한 슬레이트를 제공합니다. 공통 속성User
이 있는 부모 테이블과 필요한 프로필 정보Student
, Teacher
가 포함된 자식 테이블이 있습니다.#Schema: users[ id, name, profilable_type, profilable_id ]
class User < ApplicationRecord
delegated_type :profilable, types: %w[ Student Teacher Support ]
def say_hello
"Hello #{name}"
end
end
#Schema: teachers[ id, department ]
class Teacher < ApplicationRecord
include Profilable
end
#Schema: teachers[ id, grade ]
class Student < ApplicationRecord
include Profilable
end
module Profilable
extend ActiveSupport::Concern
included do
has_one :user, as: :profilable, touch: true
end
end
새 레코드 만들기
> User.create! profilable: Student.new(grade: 5), name: "John"
> User.create! profilable: Teacher.new(department: 'Math'), name: "Lisa"
쿼리 기능
> User.where(name: "John").first.profilable
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? ORDER BY "users"."id" ASC LIMIT ? [["name", "John"], ["LIMIT", 1]]
Student Load (0.1ms) SELECT "students".* FROM "students" WHERE "students"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
=> #<Student id: 2, grade: 5>
> User.where(name: "Lisa").first.profilable
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."name" = ? ORDER BY "users"."id" ASC LIMIT ? [["name", "Lisa"], ["LIMIT", 1]]
Teacher Load (0.2ms) SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<Teacher id: 1, department: "Math">
> Teacher.where(department: "Math").count
(0.2ms) SELECT COUNT(*) FROM "teachers" WHERE "teachers"."department" = ? [["department", "Math"]]
=> 1
> Student.where(grade: 5).first.user.name
Student Load (0.1ms) SELECT "students".* FROM "students" WHERE "students"."grade" = ? ORDER BY "students"."id" ASC LIMIT ? [["grade", 5], ["LIMIT", 1]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."profilable_id" = ? AND "users"."profilable_type" = ? LIMIT ? [["profilable_id", 2], ["profilable_type", "Student"], ["LIMIT", 1]]
=> "John"
delegated_type
는 연관이 있는 다중 테이블과 유사하지만레일즈 매직을 사용하여 구현 세부 사항. 이제 결합된
User
엔티티에 대해 페이지 매김이 가능합니다.추가 읽기
Reference
이 문제에 관하여(활성 레코드 delegated_type), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ronakjain90/active-record-delegatedtype-4od0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)