devise에서 여러 모델로 저장
7133 단어 nested_attributes루비Railsdevise
실현하고 싶은 일
devise의 계정 등록시에 2개의 모델에 기록시키고 싶다.
(사용자 정보 및 회사 정보)
왜?
다음 문제가 발생하기 때문입니다.
Campany와 User 각각에서 User A 씨를 팔로우하고 싶었다.
문제점
팔로우 기능 구현 시 Campany(모델)와 User(모델)로 등록한 사용자는 같은 번호의 id를 가지고 있다.
┗Campany 페이지에서 계정 등록을 실시했을 때의 1번째의 유저 id는 1번.
┗User 페이지에서 계정 계정 등록을 했을 때의 1번째 사용자 id는 1번.
Follow 테이블에 follower로서 정보를 기록할 때 뒤의 연결을 위해 id를 남기고 싶지만 Campany와 User는 각각 다른 테이블에서 온 id 정보.
id 1이 되어 중복하기 때문에, 이 방법은 좋지 않았다.

생각한 해결 방법
법인(Campany)도 User로 간주 User 테이블에 등록한다.
다만 법인정보는 자식모델로서 Campanies 테이블에 등록한다.
준비
devise의 기본 설정 열에 임의 열 추가
devise의 registrations_controller.rb
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up,
keys: [:name, :category_id, campany_attributes: [:campany_name, :campany_logo, :category_id, :campany_url, :tel, :staff_last_name_kana, :staff_first_name_kana]])
end
campany_attributes: [:campany 레코드의 열 이름, :campany 레코드의 열 이름, ]
모델명 _attributes로 하는 것으로 부모 모델에 연결하고 있다.
(보충 : campany_attributes의 campany는 has_one 관계라면 단수, has_many라면 복수)
연관 설정
user.rb
# userモデルの中でcampanyモデルへも同時書き込み
has_one :campany, inverse_of: :user
accepts_nested_attributes_for :campany
# Userモデル中でcampanyモデルへも書き込む
belongs_to :user, inverse_of: :campany
이번에는 new 액션은 user 등록으로 사용하고 있다.
법인 등록은 다른 화면으로 하고 싶었으므로 아래의 루트로 준비.
routes.rb
get '/campany/new' => 'users/registrations#campany' ,as: :new_campany
참고로 한 기사에서는
@user.campany.build로 중첩 모델의 구조로 할 수 있다고 했지만, 이 기술이지만 잘 가지 않았다.
하기의 기법으로 하는 것으로 해결할 수 있었다.
또한 create 액션은 devise의 기능을 덮어쓰기 때문에 super 아래에 기술한다.
마지막으로 user.save로 하지 않으면 아이 모델(campany)에는 보존되지 않기 때문에 잊지 말고.
devise의 registrations_controller.rb
# 企業の登録フォーム
def campany
@user = User.new
@user.build_campany
end
def create
super
user = User.new(configure_sign_up_params)
user.save
end
주의:
하위 모델에 데이터를 전달하는 방법은 다음과 같이 f.fields_for를 사용합니다.
상하와 같이 들여쓰기가 제대로 갖추어져 있으면 실현하고 싶은 레이아웃에 맞추어 User 모델, Campany 모델에 건네주는 데이터의 위치가 흩어져 있어도 좋다.
(부모 form은 form_for임)
campany.html.erb
<h2><%= t('.sign_up') %></h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label "会社名" %><br />
<%= f.text_field :name, autocomplete: "off" %>
</div>
<%= f.fields_for :campany do |campany| %>
<div class="field">
<%= campany.label "会社URL" %><br />
<%= campany.text_field :campany_url, autocomplete: "off" %>
</div>
<div class="field">
<%= campany.label :tel %><br />
<%= campany.telephone_field :tel, autocomplete: "off" %>
</div>
<% end %>
<div class="field">
<%= f.label "カテゴリー" %><br />
<%= f.collection_select :category_id, Category.all, :id, :name, {prompt: "選択してください"}%>
</div>
<%= f.fields_for :campany do |campany| %>
<div class="field">
<%= campany.label "ご担当者様 姓(カナ)" %><br />
<%= campany.text_field :staff_last_name_kana, autocomplete: "off" %>
</div>
<div class="field">
<%= campany.label "ご担当者様 名(カナ)" %><br />
<%= campany.text_field :staff_first_name_kana, autocomplete: "off" %>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit t('.sign_up')%>
</div>
<% end %>
<%= render "devise/shared/links" %>

무사히 2개의 모델에 보존되었습니다.
실패한 것
registrations_controller 안에서 campany 메소드를 처음에는 new_campany라는 이름으로 하고 있었다.
오류로 new_campany_path? 라고 말했지만 그런 것은 아니다.
애초에 메소드명이 prefix 패스로 에러 문 토출한다는 것은 어떤 의미?
고민하는 것 3시간, 예약어 키워드가 고개를 끄덕였다.
설마 생각 메소드 이름을 바꾸자 뷰에 무사히 날아 줬다.
예약어에는 조심하자.
Reference
이 문제에 관하여(devise에서 여러 모델로 저장), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/params_bird/items/96922cae0c7a82ff157c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)