質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • Ruby

    7622questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails 5

    1732questions

  • Devise

    248questions

    Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。

deviseで入れ子型のストロングパラメータを設定したい!

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 132

zendendo

score 26

railsのストロングパラメータに関する質問です。

deviseのuser登録画面に子モデルaddress_list(住所)の入力項目prefectures(県カラム)を設置し、入力内容をストロングパラメータ化して受取り、
userとaddress_listを同時作成したいと考えています。

しかし、deviseでネストしたストロングパラメータの設定の仕方が分からず困っています。
どうすればいいのか教えて頂ければ幸いです。

現状のdeviseのストロングパラメータの設定です。

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :sex])
  end

end
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

userとその子モデルに新規作成を行いたい場合、以下のようにすることでストロングパラメータで値を受取り、同時作成することができました。

まず、application_controller.rbに、カスタマイズした入力内容をチェックするためのdevise用ストロングパラメータ(サニタイザー)を設定。

class ApplicationController < ActionController::Base

  before_action :configure_permitted_parameters, if: :devise_controller?#ストロングパラメータ起動


  protected
  #devise用のストロングパラメータconfigure_permitted_parametersを設定する
  def configure_permitted_parameters
    #ユーザーが新規登録する際変更できるのは、第1引数sing_up(deviseデフォルト設定になっている新規登録に必要な項目、emailやpasswordなど)と独自追加カラムnickname,sexのみ許可、
    #加えて子モデルaddress_listの、prefectures_master_idのみ許可
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :sex, :address_list_attributes => [:prefectures_master_id]])#ネストありの設定、親レコード、子レコード受け渡し成功
  end

end

・devise内製の/app/controllers/users/registrations_controller.rbを編集(ないなら作成してから編集)、ストロングパラメータをカスタマイズ。

 class Users::RegistrationsController < Devise::RegistrationsController
 def configure_sign_up_params
    #
    devise_parameter_sanitizer.permit(:sign_up) do |params|
      #ユーザー(入力者)が新規登録をするとき変更できるのは、sign_up(deviseのデフォルト設定のカラム、emailやpasswordなど)に加え、追加した独自カラムnicknameとsexのみ変更を許可
      #加えて子モデルaddress_listのprefectures_master_idカラムのみ変更を許可
      params.permit(:sign_up, keys: [:nickname, :sex, address_list_attributes: [:prefectures_master_id]])
    end
  end

  #ユーザー編集用ストロングパラメータをカスタマイズ
  def configure_account_update_params
    #accepts_nested_attributes_for(親から子を作成保存するときに使うメソッド)を使いdeviseのデフォルト挙動をカスタマイズしたい場合は、ブロックを渡す
    devise_parameter_sanitizer.permit(:account_update) do |params|
      #渡したブロックをカスタマイズ
      #ユーザー(入力者)が編集更新をするとき変更できるのは、account_update(deviseのデフォルト設定のカラム、emailやpasswordなど)に加え、追加した独自カラムnicknameとsexのみ変更を許可、
      #加えて子モデルaddress_listのprefectures_master_idカラムのみ変更を許可
      params.permit(:account_update, keys: [:nickname, :sex, address_list_attributes: [:prefectures_master_id]])
    end
  end

end

・モデルでリレーションの設定。

class User < ApplicationRecord
  #一人のユーザーは、一つの住所を保有している
  has_one :address_list, inverse_of: :user#一人のユーザーはひとつの住所を保有し、メモリ上でuserとaddress_listを同一インスタンスとして扱う
  accepts_nested_attributes_for :address_list#親子関係にある関連モデルaddress_list(子)を作成する。(具体的には、ビューで子レコードに入力するパラメータをつくってくれる)
class AddressList < ApplicationRecord
    #複数のAddressList(送り先住所)は、一人のユーザーに保有されている
    belongs_to :user, inverse_of: :address_list#一つの住所は一人のユーザーに保有され、メモリ上では同一のインスタンスとして扱う
end


app/views/devise/registrations.new.html.erbを編集(devise内製の入力フォームを編集)
fields_forで、address_listに入力するフォームを作成。
また、resource.build_address_list || AddressList.newという記述で、
resource(親であるユーザーレコード)の子になるadress_listを作成。

<div class="panel panel-default devise-bs">
  <div class="panel-heading">
    <h4><%= t('.sign_up', default: '新規会員登録') %></h4>
  </div>
  <div class="panel-body">
    <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { role: 'form' }) do |f| %>
      <div class="form-group">
        <%= f.label :ニックネーム %>
        <%= f.text_field :nickname, class: 'form-control' %>
      </div>
      <div class="form-group">
        <%= f.label :性別 %>
        <%= f.select :sex, [["男", 1], ["女", 2],["その他", 3]] ,class:"form-control" %>
      </div>
      <div class="form-group">
        <%= f.label :email %>
        <%= f.email_field :email, autofocus: true, class: 'form-control' %>
      </div>
      <div class="form-group">
        <%= f.label :password %>
        <%= f.password_field :password, class: 'form-control' %>
      </div>
      <div class="form-group">
        <%= f.label :password_confirmation %>
        <%= f.password_field :password_confirmation, class: 'form-control' %>
      </div>

      <%#= f.fields_for :address_lists do |al| %><!-- ここから子レコードaddress_listsに入力する内容 -->
      <!--以下1:1の子モデルaddress_listへ入力する内容 -->
      <%= f.fields_for :address_list, resource.build_address_list || AddressList.new do |al| %><!--userモデルに送るform_forとは別にaddress_listに送るフォームを作成。resource(ユーザー)の子address_listを1対1で作成 -->
      <div class="form-group">
        <%= al.label :お住まいの都道府県 %>
        <%= al.select :prefectures_master_id, [["東京", 1], ["千葉", 2],["神奈川", 3]] ,class:"form-control" %>
        <%#= al.collection_select :prefectures_master,PrefecturesMaster.all, :id, :pref_name ,class:"form-control" %>
      </div>
      <% end %><!-- ここまでが子レコードaddress_listsに入力する内容 -->
      <%= f.submit t('.sign_up', default: 'Sign up'), class: 'btn btn-primary' %>
    <% end %>
  </div>
</div>
<%= render 'devise/shared/links' %>

以上で、user登録と同時にaddress_listも登録されるようになりました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

devise が裏で何をやっているのか分からないんですが、こんな感じでイケませんかね?

# address_lists: [:prefectures_master_id] を追加
devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname, :sex, address_lists: [:prefectures_master_id]])

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7622questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

  • Ruby on Rails 5

    1732questions

  • Devise

    248questions

    Deviseとは、Ruby-on-Railsの認証機能を追加するプラグインです。