LoginSignup
0
0

More than 1 year has passed since last update.

undefined method `permit' for "1":String に手こずった。

Last updated at Posted at 2022-08-21

はじめに

本記事はプログラミング初心者が、railsの学習を進めながら、躓いた部分、解決した箇所、またそれらの解決方法を備忘録も兼ねてまとめているものです。
最初はprogate。そのあと、「現場で使える RubyonRails5 速習実践ガイド」(通称)「現場Rails」を参考に進めていきました。
そのため、記事の内容には誤りがある可能性があることをご理解ください。
誤りがあればお手数ですが、ご指摘いただければと思います。よろしくお願いします。

環境

Ruby 3.1.2
Rails 7.0.3.1

new.html.slim
- if @user.errors.present?
  ul#error_explanation
    - @user.errors.full_messages.each do |message|
      li = message
dl
 = form_with model: @user, url: '/users', local: true do |f|
    .form-group
        f.label 名前
        = f.text_field :name, class: 'form-control', id: 'user_name', placeholder: '山田 太郎'
    .form-group
      f.label 性別
      br
      = f.radio_button :sex, :男性
      = f.label :sex, '男性', {value: :'男性', style: "display: inline-block;"}
      = f.radio_button :sex, :女性
      = f.label :sex, '女性', {value: :'女性', style: "display: inline-block;"}

    .form-group
        = f.label :age
        / = f.text_field :age, class: 'form-control', id: 'user_age'
        .form-controlls
        = f.select :age, options_for_select(1..40), options = { include_blank: true }
        |歳
    .form-group
        = f.label :hemo
        = f.text_field :hemo, class: 'form-control', id: 'user_hemo', placeholder: '15.0'
        |g/dl
    .form-group
        = f.label :feti
        = f.text_field :feti, class: 'form-control', id: 'user_feti', placeholder: '105.0'
        |ng/mL
    .form-group
        = f.label :sterone
        = f.text_field :sterone, class: 'form-control', id: 'user_sterone', placeholder: '550'
        |ng/mL
    .form-group
      #check
       = check_box_tag (:user)
      f.label 個人情報の取り扱いについて同意します。
      iframe src="https://kiyaku.jp/hinagata/privacy.html"
    / =f.submit '判定を開始する', class: 'btn btn-primary'
    input(type="submit" id='link3' value="判定を開始する" disabled)

user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :sex, presence: true
  validates :hemo, presence: true
  validates :feti, presence: true
  validates :sterone, presence: true
---中略---

end

user.contoroller

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
   @user = User.new(user_params)
   if @user.save
    redirect_to @user, notice: "判定が正常に実行されました。"
   else
    render :new, status: :unprocessable_entity
   end
  end



  private
  def user_params
    params.require(:user).permit(:name, :sex, :age, :hemo, :feti, :sterone)
  end
end

問題のエラー

webサイトなどによくある、個人情報などの取り扱いについて、同意する際、チェックマークなんかいれますよね。
以下の画像のようなイメージです。
スクリーンショット 2022-08-21 22.37.56.png
スクリーンショット 2022-08-21 22.38.03.png

チェックマークが入ったら、「判定を開始する」ボタンが出てくるようにしたかったです。(してます。)
しかしながら、バリデーションを追加して、「判定を開始する」ボタンを押したら、以下のようなエラーになりました。
スクリーンショット 2022-08-21 21.51.45.png

どうやら:urserには、:nameや:ageなどの入力された値が入ってくるはずなのに、'1'という数値が入ってきてしまっている。というようなエラーなようです。

解決方法

メンターの方にアドバイスをもらいました。
①モデルで、データベースに保存しない属性を指定できるattributeで定義する。
agreementはデータベースには保存されない、同意をしたかチェックするために使用する

user.rb
  attribute :agreement, :boolean, default: false

agreementに対して、バリデーションをつける

user.rb
  # 新規作成時には同意を必須して、かつtrueしか許可しない
   validates :agreement, presence: true, acceptance: true, on: [:create]

③ストロングパラメータにagreementを追加

user.contoroller
class UsersController < ApplicationController
  private
  def user_params
    params.require(:user).permit(:name, :sex, :age, :hemo, :feti, :sterone, :agreement)
  end
end

④viewのコードも汚かったので、同時に直していただきました。
(f.labelの部分に=がついていなかったり、idの部分がおかしかったので、整理しました。わかりにくくてすみません💦)
(最終的なコード)

new.html.slim
- if @user.errors.present?
  ul#error_explanation
    - @user.errors.full_messages.each do |message|
      li = message
dl
 = form_with model: @user, url: '/users', local: true do |f|
    .form-group
        = f.label :name
        = f.text_field :name, class: 'form-control', id: 'user_name', placeholder: '山田 太郎'
    .form-group
      = f.label :sex
      br
      = f.radio_button :sex, :男性
      = f.label :sex, '男性', {value: :'男性', style: "display: inline-block;"}
      = f.radio_button :sex, :女性
      = f.label :sex, '女性', {value: :'女性', style: "display: inline-block;"}

    .form-group
        = f.label :age
        .form-controlls
        = f.select :age, options_for_select(1..40), options = { include_blank: true }
        |
    .form-group
        = f.label :hemo
        = f.text_field :hemo, class: 'form-control', id: 'user_hemo', placeholder: '15.0'
        |g/dl
    .form-group
        = f.label :feti
        = f.text_field :feti, class: 'form-control', id: 'user_feti', placeholder: '105.0'
        |ng/mL
    .form-group
        = f.label :sterone
        = f.text_field :sterone, class: 'form-control', id: 'user_sterone', placeholder: '550'
        |ng/mL
    .form-group
      = f.check_box :agreement, checked: false, id: 'check'
      = f.label :agreement, '個人情報の取り扱いについて同意します。', for: 'check'
      iframe src="https://kiyaku.jp/hinagata/privacy.html"
    input(type="submit" id='link3' value="判定を開始する" disabled)

これで、バリデーションを加え、チェック機能を実装しても、できるようになりました。バリデーションもしっかり機能しています。スクリーンショット 2022-08-21 22.49.31.png

おわりに

今回のエラーの大きな原因は、同意するのボタンの部分の実装がうまくいっておらず、本来カラムが入るべきところを、定義していない:userを入れてしまったことが原因です。slimの時のcheckboxの書き方をしかり覚えて、同じミスがないようにしたいです。また、modelにattributeを定義することで、データに登録せずとも、同意したかどうかをチェックできるものがあったので、以後使えそうだなと思いました。かなり読みにくい記事だとは思いますが、だれかの役に立てれば幸いです。もし何かあれば、お気軽にコメントよろしくお願いします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0