Ruby on Rails - submodel, subclass or subcontroller 만들기(references type)
우선 기준이 스케폴드로 CRUD 모델을 하나 만들어줍니다.
이 모델 아래 복수의 데이터를 가지는 모델을 만들어봅시다.
여기서 references 타입은 FK를 만들어준다고 생각하면 좋습니다.
pattern이라는 모델을 만들면서 data라는 text 타입의 속성과 rule을 참조하는 references 타입의 속성을 만들었습니다.
rule 하위에서 patterns이 라우팅되도록 routes.rb를 수정해줍니다.
제 어플리케이션은 rule이 다수의 pattern을 가져야 하기 떄문에 model에 has_many로 pattern을 여러개를 가질 수 있도록 수정해줍니다.
(
만약 pattern_params 처럼 허용 파라미터를 정의하지 않고 직접 파라미터 값을 받아서 쓰면
에러가 발생합니다. 이유인 즉슨, Rails 4 버전대 이후부터 정책적으로 파라미터 제한을 기본으로 설정하도록 되어서 그렇습니다.
처음에 튜토리얼 코드에서 많이 낚이죠..
#> rails new log
#> cd log
#> rails g scaffold rule name:string desc:text
이 모델 아래 복수의 데이터를 가지는 모델을 만들어봅시다.
하위에 포함될 모델 만들기, 라우팅 설정
#> rails g model pattern data:text rule:references
여기서 references 타입은 FK를 만들어준다고 생각하면 좋습니다.
pattern이라는 모델을 만들면서 data라는 text 타입의 속성과 rule을 참조하는 references 타입의 속성을 만들었습니다.
rule 하위에서 patterns이 라우팅되도록 routes.rb를 수정해줍니다.
#> vim config/routes.rb
Rails.application.routes.draw do
resources :rules do
resources :patterns
end
end
제 어플리케이션은 rule이 다수의 pattern을 가져야 하기 떄문에 model에 has_many로 pattern을 여러개를 가질 수 있도록 수정해줍니다.
#> vim app/model/rule.rb
class Rule < ActiveRecord::Base
has_many :patterns
end
컨트롤러 설정하기
이제 pattern을 만드는 메소드를 만들어봅시다. pattern의 컨트롤러를 아래와 같이 수정합니다.(
#> vim app/controllers/patterns_controller.rb
class PatternsController < ApplicationController
def create
@rule = Rule.find(params[:rule_id]) # 현재 Rule의 번호를 찾고
@pattern = @rule.patterns.create(pattern_params) # 인자값(이 어플에선 data)를 가지고 pattern을 생성합니다.
redirect_to rule_path(@rule) # 다되면 rule page로 이동
end
private # rails4 버전 이후부터, 파라미터에 대해서 제한하는 설정이 기본으로 필요합니다.
def pattern_params # 안하면 아래 에러가 나요.
params.require(:pattern).permit!
end
end
만약 pattern_params 처럼 허용 파라미터를 정의하지 않고 직접 파라미터 값을 받아서 쓰면
ActiveModel::ForbiddenAttributesError
처음에 튜토리얼 코드에서 많이 낚이죠..
View 수정을 통해 추가 페이지 보여주기
마지막으로 view에 하위 모델인 pattern을 추가할 수 있도록 UI를 구성해줍니다.#> vim app/views/rules/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= @rule.name %>
</p>
<p>
<strong>Desc:</strong>
<%= @rule.desc %>
</p>
<strong>Pattern</strong>
<% @rule.patterns.each do |patt| %>
<p> - <%= patt.data %> </p>
<% end %>
Add
<%= form_for([@rule, @rule.patterns.build]) do |f| %>
<div class="field"><%= f.label :data %><br>
<%= f.text_field :data %>
</div>
<div class="actions"><%= f.submit %></div>
<% end %>
<%= link_to 'Edit', edit_rule_path(@rule) %> |
<%= link_to 'Back', rules_path %>