폴리모픽 관련 기억

16165 단어 Rails4

다형성 관련이란 무엇입니까?



여러 부모를 가진 하위 테이블을 구현하는 관련 메커니즘

어떤 경우에 사용합니까?



예를 들어, Shop model과 User model에서 각각 Profile을 갖고 싶습니다.
갖게 하는 Profile의 내용이 완전히 같은 경우라든가


  • 같은 내용의 model을 2개 만들어도 좋지만,
  • 변경시 2개 변경시켜야 합니다.
  • Shop이든 User든 상관없이 어쨌든 프로필 목록을 만들고 싶을 때 귀찮습니다


  • 그럴 때는 폴리모픽 관련을 사용하여 Shop model과 User model 모두를 부모로 하는 Profile model을 작성한다.

    어떤 식으로 실현합니까?



    사용자 모델 만들기


    $ rails g scaffold name:string
    

    프로필 모델 만들기


    #{関連名}:references{polymorphic} 에서 폴리모픽 관련을 위한 컬럼 생성
  • 관련명에 대해서는 #{自model名}able 로 하는 경우가 많은 것 같다
  • 참고 : Rails 폴리모픽 관련 관련 이름 명명 - 130 단위

  • $ rails g model profile profilable:references{polymorphic} disription:string
    

    migration 및 model 구현



    이런 간지

    db/migrate/20160621160304_create_profiles.rb
    class CreateProfiles < ActiveRecord::Migration
      def change
        create_table :profiles do |t|
          t.references :profilable, polymorphic: true, index: true
          t.string :disription
    
          t.timestamps null: false
        end
      end
    end
    

    app/models/profile.rb
    class Profile < ActiveRecord::Base
      belongs_to :profilable, polymorphic: true
    end
    

    app/models/user.rb
    class User < ActiveRecord::Base
      has_one :profile, :as => :profilable
    end
    

    데이터를 넣어보세요


    u = User.create(name: 'aaa')
    u.profile = Profile.create(disription: 'test')
    
  • profilable_type : 부모 모델의 클래스명
  • profilable_id : 부모 모델 ID
  • sqlite> select * from users;
    id          name        created_at                  updated_at
    ----------  ----------  --------------------------  --------------------------
    1           aaa         2016-06-21 16:07:03.154460  2016-06-21 16:07:03.154460
    
    sqlite> select * from profiles;
    id          profilable_id  profilable_type  disription  created_at                  updated_at
    ----------  -------------  ---------------  ----------  --------------------------  --------------------------
    1           1              User             test        2016-06-21 16:07:45.587894  2016-06-21 16:07:45.593233
    

    Shop model도 생성


    $ rails g model shop name:string
    

    app/model/shop.rb
    class Shop < ActiveRecord::Base
      has_one :profile, :as => :profilable
    end
    

    데이터를 넣어보세요


    s = Shop.create(name: 'aaa')
    s.profile = Profile.create(disription: 'abc')
    
    s = Shop.create(name: 'bbb')
    s.profile = Profile.create(disription: 'abcd')
    
    sqlite> select * from shops;
    id          name        created_at                  updated_at
    ----------  ----------  --------------------------  --------------------------
    1           aaa         2016-06-21 16:13:06.268592  2016-06-21 16:13:06.268592
    2           bbb         2016-06-21 16:13:39.186536  2016-06-21 16:13:39.186536
    
    sqlite> select * from profiles;
    id          profilable_id  profilable_type  disription  created_at                  updated_at
    ----------  -------------  ---------------  ----------  --------------------------  --------------------------
    1           1              User             test        2016-06-21 16:07:45.587894  2016-06-21 16:07:45.593233
    2           1              Shop             abc         2016-06-21 16:13:06.295915  2016-06-21 16:13:06.331801
    3           2              Shop             abcd        2016-06-21 16:13:44.673048  2016-06-21 16:13:44.680561
    

    다형성 관련을 검색 할 때 어떤 쿼리가 발행 되었습니까?


    Shop.find_by(name: 'bbb').profile.disription
    
    profilable_type 와, profilable_id 로 SELECT 하고 있다
      Shop Load (0.3ms)  SELECT  "shops".* FROM "shops" WHERE "shops"."name" = ? LIMIT 1  [["name", "bbb"]]
      Profile Load (0.2ms)  SELECT  "profiles".* FROM "profiles" WHERE "profiles"."profilable_id" = ? AND "profiles"."profilable_type" = ? LIMIT 1  [["profilable_id", 2], ["profilable_type", "Shop"]]
    => "abcd"
    

    자식에서 부모 모델에 액세스하는 방법


    profilable 사용하기
    Profile.find_by(disription: 'abc').profilable.class.to_s # => Shop
    

    코드



    감상


  • 객체 지향
  • 정확히 같은 모델을 사용하는 것이 확정되어 있으면 편리해
  • 그 뒤집기에서 특정 부모의 경우에만 특정 열이 필요하다면 어려울 것입니다

  • 검색시에, id 와 캐릭터 라인으로 검색하고 있으므로, 1회로 대량의 아이 요소에 액세스 하는 경우, 처리 시간을 신경 쓰는 것이 좋을지도
  • 대량으로 단시간에 갱신할 필요가 있는 경우, 1개의 테이블에 넣는 편이 속도는으로 그렇게


  • 참고


  • Rails 폴리모픽 관련 관련 이름 명명 - 130 단위
  • Rails.GrAFR : 다형성 관련 DB 구조
  • 좋은 웹페이지 즐겨찾기