実現したいこと
Userテーブルと1対1の関係があるStudentテーブルがあり、どちらか一方が更新されれば、もう一方も更新されるようにしたい。
問題点
以下、2点の問題が発生しています。
①Studentの入力部分が非表示になっている。
②以下のエラーが発生している。
そのために、Controller部分を確認し、フィードバックをいただけないでしょうか?
Modelの記載
親:User.rb
class User < ApplicationRecord has_one :student, dependent: :destroy accepts_nested_attributes_for :student end
子:Student.rb
class Student < ApplicationRecord belongs_to :user, optional: true, inverse_of: :student end
Table構造
Usersテーブル create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "fullname" t.integer "unread", default: 0 t.bigint "global_user_id" t.bigint "school_person_in_charge_id" t.bigint "student_id" t.index ["email"], name: "index_users_on_email", unique: true t.index ["global_user_id"], name: "index_users_on_global_user_id" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["school_person_in_charge_id"], name: "index_users_on_school_person_in_charge_id" t.index ["student_id"], name: "index_users_on_student_id" end
studentsテーブル
create_table "students", force: :cascade do |t| t.string "nickname" t.date "birth" t.integer "gender" t.string "image" t.text "comment" t.bigint "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["user_id"], name: "index_students_on_user_id" end
Controllerの記載
Profiles_controller.rb
class StudentAdmin::ProfilesController < StudentAdmin::StudentsController before_action :authenticate_user! def edit @user = current_user end def profile_update if current_user.student.nil? current_user.create_student!(profile_params) else current_user.student.update(profile_params) end redirect_to user_profile_path(current_user) end private def profile_params params.require(:user).permit(:fullname, :email, :avatar, student_attributes: [:id, :nickname, :birth, :gender, :comment, :user_id]) end end
Form(HTML)の記載
<%= simple_form_for(user, url: user_profile_update_path(user), method: :put, html:{ multipart: true }) do |f| %> <%= f.error_notification %> <%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> //ここは、親テーブルのhtml要素 <div class="form-group row"> <label for="inputEmail3" class="col-sm-3 col-form-label">Fullname</label> <div class="col-sm-9"> <%= f.input :fullname, label: false, input_html: { value: current_user.fullname, class: "form-control" }, required: true, autofocus:true %> </div> </div> <div class="form-group row"> <label for="inputEmail3" class="col-sm-3 col-form-label">Email</label> <div class="col-sm-9"> <%= f.input :email, label: false, input_html: { value: current_user.email, class: "form-control"}, required: true, autofocus: true %> </div> </div> <div class="form-group row"> <label for="filenam" class="col-sm-3 col-form-label">Photo</label> <div class="col-sm-9"> <div class="row"> <div class="col-md-8"> <div class="text-left" style="padding-bottom: 1rem;"> <% if user.avatar.attached? %> <%= image_tag user.avatar.variant(resize: "200x200"), class: "rounded img-thumbnail" %> <% end %> </div> <div class="input-group"> <div class="input-group-prepend"> <div class="input-group-text" id="select_file_button">Click!</div> </div> <!-- <input id="filename" readonly type="text" value="""> --> <input id="filename" readonly type="text" value="<%= user.avatar.filename if user.avatar.attached? %>" class="form-control" aria-describedby="select_file_button"> <%= f.input :avatar, label: false, as: :file, required: true, input_html: { class: "form-control-file", id:'file_button'}, wrapper: false %> </div> </div> </div> </div> </div> //以下は、子テーブルのhtml要素 <%= f.simple_fields_for :student, @user.student do |p| %> <div class="form-group row"> <label for="inputPassword3" class="col-sm-3 col-form-label">Nickname</label> <div class="col-sm-9"> <%= p.input :nickname, label: false, required: true, autofocus: true, input_html: { class: "form-control"}, wrapper: false, label_html: { class: "label" } %> </div> </div> <div class="form-group row"> <label for="inputPassword3" class="col-sm-3 col-form-label">Birthday</label> <div class="col-sm-9 d-flex flex-row justify-content-between align-items-center"> <%= p.input :birth, label: false, required: true, input_html: { class: "form-control mx-1"}, wrapper: false, as: :date, start_year: Date.today.year - 60, end_year: Date.today.year - 6, discard_day: true, order: [:month, :year] %> </div> </div> <fieldset class="form-group"> <div class="row"> <legend class="col-form-label col-sm-3 pt-0">Gender</legend> <div class="col-sm-9"> <div class="form-check"> <%= p.input :gender, :label => false, :collection => [[0, 'Male'], [1, 'Female']], :label_method => :last, :value_method => :first, :item_wrapper_class => 'inline', :input_html => { class: "form-check-input" }, :as => :radio_buttons %> </div> </div> </div> </fieldset> <div class="form-group row"> <label for="inputPassword3" class="col-sm-3 col-form-label">Self Introduction</label> <div class="col-sm-9"> <%= p.input :comment, label: false, as: :text, required: true, autofocus: true, input_html: { class: "form-control", rows: 7}, wrapper: false, label_html: { class: "label" } %> </div> </div> <% end %> <div class="form-group row"> <label for="inputPassword3" class="col-sm-3 col-form-label"></label> <div class="col-sm-9 text-center"> <%= f.button :submit, (user.new_record? ? "Record" : "Update"), class: "btn btn-primary" %> </div> </div> <% end %>
上記の結果は、親テーブルの表示はできますが、子テーブルの表示ができない状況です。ただし、viewsの
<%= f.simple_fields_for :student do |p| %>
のstudentを"students"に変えた場合は、子要素の部分が表示されます。ただし、保存ができません。私自身は、controllerの書き方に問題があるのではないかと考えていますが、色々と試してみましたが、解決に至っていません。お知恵をお貸しいただけると幸いです。
補足情報
ruby 2.5.7p206
Rails 6.0.2.1
Deviseというgemを使って、User管理を行なっています。
form は、simple_formというgemを使っています。
回答1件
あなたの回答
tips
プレビュー