[Rails] STI 사용 후 DB가 시원해졌어요.
개요
Player
모형 제작.ポジション
,所属
(일본 대표 또는 올림픽 대표),タイプ
(속도, 역량과 기술 등)는 다대다 디자인이다.Spike
모형 제작.適応グラウンド
와 色
는 다대다 디자인이다.보시다시피 지루하고 많을 때 가지고 싶은 정보를 추가할 때마다 두 개의 표를 추가해야 합니다.
따라서 STI를 사용하는 것이 좋습니다.
매끄러워 갖고 싶은 정보를 많이 늘리고 싶을 때도 테이블을 다시 만들 필요가 없다.
사용법
빨간 테두리가 파란색 테두리에 저장되고 type을 누르면 Tags표에 저장된다고 상상해 보세요.
데이터 취득은 유형에 따라 진행할 수 있다.
빨간색 상자를 파란색 상자에 저장하려면 빨간색 상자의 모델을 만들어 Tag 모델을 상속합니다.
관계
playre.rbclass Player < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :tags, through: :player_tags
end
player_tag.rbclass PlayerTag < ApplicationRecord
belongs_to :player
belongs_to :tag
end
tag.rbclass Tag < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :players, through: :player_tags
has_many :spike_tags, dependent: :destroy
has_many :spikes, through: :spike_tags
end
spike.rbclass Spike < ApplicationRecord
has_many :spike_tags, dependent: :destroy
has_many :tags, through: :spike_tags
end
spike_tag.rbclass SpikeTag < ApplicationRecord
belongs_to :spike
belongs_to :tag
end
여기까진 보통 다대다 관계야.
STI를 사용하려면 Tag 모델을 상속하는 빨간색 상자 모델을 만들어야 합니다.
Tag 모델 상속
position.rbclass PositionTag < Tag
end
belongs.rbclass BelongsTag < Tag
end
genre.rbclass GenreTag < Tag
end
ground.rbclass GroundTag < Tag
end
color.rbclass ColorTag < Tag
end
앞으로 더 많은 정보와 더 많은 정보를 얻고 싶다면 이렇게 type열에 깊이 들어가고 싶은 모델을 만들어 Tag모델을 계승시키면 된다.
관계 추가
player.position_tags
또는 spike.ground_tags
관계를 추가하여 데이터를 얻습니다.
playre.rbclass Player < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :tags, through: :player_tags
# 追加
has_many :position_tags, through: :player_tags
has_many :genre_tags, through: :player_tags
has_many :belongs_tags, through: :player_tags
end
player_tag.rbclass PlayerTag < ApplicationRecord
belongs_to :player
belongs_to :tag
# 追加
has_many :ground_tags, through: :spike_tags
has_many :color_tags, through: :spike_tags
end
여기는 "어? 모르겠어 왜?"적분position_tags
또는 ground_tags
의 책상은 어디에 있습니까?
결론은 Tags 테이블의 type 열의 내용과 각각의 관계가 조합된다는 것입니다.
Rails의 type 열은 STI 전용 특수 열이므로 평소에 사용하지 않도록 주의하십시오.
데이터 삽입
실제로 이런 사용법은 없지만 절차를 추적하고 싶어 태그에 데이터를 삽입한 부분만 기술하고 있다.
views/players/new.html.slim= form_with model: @player, local: true do |f|
.form-group
= f.label :name
= f.text_field :name, class: "form-control"
.form-group
= f.label :position
= f.text_field :position, class: "form-control"
.action.mt-3
= f.submit class: "btn btn-primary"
이 내용을 보내면params[:player][:position]
서버에 저장되어 서버에 요청을 제출합니다.
여러 문자열을 보내려면 임의의 문자열/
또는 ,
로 구분하십시오.
이번 입력FW/MF
요청입니다.
players.controller.rbdef create
player = Player.new(player)
position_tag_names = params[:player][:position]
player.save
# ポイント
player.position_tags = position_tag_names.split('区切りたい文字列').map { |name| PositionTag.find_or_create_by(name: name) }
end
・
・
private
def player_params
params.require(:player).permit(:name)
end
ポイント
이하 1문은 간이다.
나는 본래 모형으로 처리하는 것이 가장 좋다고 생각한다.position_tag_names
임의로 분할하고자 하는 문자열 (/
이나 ,
을 만들 때마다string (split) 을 하나씩 배열에 넣고 (map) 등록하거나 미리 등록하면 이string을 되돌려줍니다.(find_or_create_by)
데이터베이스를 확인한 후 다음과 같이 등록합니다.
id
type
name
created_at
updated_at
1
PositionTag
FW
~~~~~~~~~~
~~~~~~~~~~
2
PositionTag
MF
~~~~~~~~~~
~~~~~~~~~~
데이터를 꺼내보도록 하겠습니다.
단말기[1] pry(main)> player = Player.first
(1.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
Player Load (0.5ms) SELECT `players`.* FROM `players` ORDER BY `players`.`id` ASC LIMIT 1
=> #<Player:0x00007fcea7e69718 id: 1, name: "SS2ゴハン", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, spike_id: 1>
[2] pry(main)> player.position_tags
PositionTag Load (1.6ms) SELECT `tags`.* FROM `tags` INNER JOIN `player_tags` ON `tags`.`id` = `player_tags`.`tag_id` WHERE `tags`.`type` IN ('PositionTag') AND `player_tags`.`player_id` = 1
=> [#<PositionTag:0x00007fcea8f3a498 id: 1, type: "PositionTag", name: "FW", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00>,
#<PositionTag:0x00007fcea8f3a2e0 id: 2, type: "PositionTag", name: "MF", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00>]
player.position_tags
와 그 유저 관련position_tags
.
그리고 each로 회전해서 하나씩 표시하면 마음대로 할 수 있습니다.
최후
STI는 반모드에 대한 기사를 많이 봤지만 이번에는 인터페이스가 똑같아서 사용했다.
상쾌하다.
Reference
이 문제에 관하여([Rails] STI 사용 후 DB가 시원해졌어요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/niwa1903/items/410a10b1132af5049c6e
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Player < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :tags, through: :player_tags
end
class PlayerTag < ApplicationRecord
belongs_to :player
belongs_to :tag
end
class Tag < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :players, through: :player_tags
has_many :spike_tags, dependent: :destroy
has_many :spikes, through: :spike_tags
end
class Spike < ApplicationRecord
has_many :spike_tags, dependent: :destroy
has_many :tags, through: :spike_tags
end
class SpikeTag < ApplicationRecord
belongs_to :spike
belongs_to :tag
end
class PositionTag < Tag
end
class BelongsTag < Tag
end
class GenreTag < Tag
end
class GroundTag < Tag
end
class ColorTag < Tag
end
class Player < ApplicationRecord
has_many :player_tags, dependent: :destroy
has_many :tags, through: :player_tags
# 追加
has_many :position_tags, through: :player_tags
has_many :genre_tags, through: :player_tags
has_many :belongs_tags, through: :player_tags
end
class PlayerTag < ApplicationRecord
belongs_to :player
belongs_to :tag
# 追加
has_many :ground_tags, through: :spike_tags
has_many :color_tags, through: :spike_tags
end
= form_with model: @player, local: true do |f|
.form-group
= f.label :name
= f.text_field :name, class: "form-control"
.form-group
= f.label :position
= f.text_field :position, class: "form-control"
.action.mt-3
= f.submit class: "btn btn-primary"
def create
player = Player.new(player)
position_tag_names = params[:player][:position]
player.save
# ポイント
player.position_tags = position_tag_names.split('区切りたい文字列').map { |name| PositionTag.find_or_create_by(name: name) }
end
・
・
private
def player_params
params.require(:player).permit(:name)
end
[1] pry(main)> player = Player.first
(1.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
Player Load (0.5ms) SELECT `players`.* FROM `players` ORDER BY `players`.`id` ASC LIMIT 1
=> #<Player:0x00007fcea7e69718 id: 1, name: "SS2ゴハン", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, spike_id: 1>
[2] pry(main)> player.position_tags
PositionTag Load (1.6ms) SELECT `tags`.* FROM `tags` INNER JOIN `player_tags` ON `tags`.`id` = `player_tags`.`tag_id` WHERE `tags`.`type` IN ('PositionTag') AND `player_tags`.`player_id` = 1
=> [#<PositionTag:0x00007fcea8f3a498 id: 1, type: "PositionTag", name: "FW", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00>,
#<PositionTag:0x00007fcea8f3a2e0 id: 2, type: "PositionTag", name: "MF", created_at: Mon, 15 Jun 2020 18:13:45 JST +09:00, updated_at: Mon, 15 Jun 2020 18:13:45 JST +09:00>]
Reference
이 문제에 관하여([Rails] STI 사용 후 DB가 시원해졌어요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/niwa1903/items/410a10b1132af5049c6e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)