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

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

ただいまの
回答率

87.61%

[Rails ] attr_accessor で追加したフォームパラメーターをモデル内で使う方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,831
退会済みユーザー

退会済みユーザー

フォーム内容とカラムの型が違う場合1度 attr_accessor で付与したフィールドでフォームとやりとりして
モデル内で値をカラムにセットする必要があると思うのですがいまいちその一般的なやり方がわかりません

attr_accessor の使い方がまだよくわかっていなくて
データベースに保存されないだけで ruby 上ではカラムと同じように扱えるフィールドという認識で
モデルの中に勝手に値がセットされるんだと思ってたのですが

f.checkbox :gender_form, {multiple:true}, 'male', nil
f.checkbox :gender_form, {multiple:true}, 'female', nil

のようなフォームから params => user => gender_form => {'male', 'female'} のような配列パラメーターがとんできて
コントローラーで

def create
  @user = User.new(user_params)
  @user.save
end

def user_params
  params.require(:user).permit(:gender_form)
end

と全部モデルに渡すとモデル内で self.gender_form でアクセスできると思ったのですが

user.rb で

  validates :gender_form, presence: true

  after_validation :set_columns, on: [ :create, :update ]

  private def set_columns
    gender = gender_form.join(',')
  end

とかいても 

undefined method `join' for nil:NilClass

となって gender_form の値を取得できません

コントローラーでは当然拾えるので

  @user = User.new(user_params)
  @user.gender = user_params.gender_form.join(',')
  @user.save


という感じでフォームとカラムの差異の吸収は
コントローラー内でやるべきなのでしょうか

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

attr_accessorはrubyのメソッドですね。
特に難しいことはしていなくて、インスタンス変数のgetterとsetterを一緒に定義するための便利機能です。
つまり、

attr_accessor :name


は、以下のような定義を書いたのと同じことになります。

def name
  @name
end
def name=(val)
  @name = val
end


参考 : https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_accessor.html

データベースに保存されないだけで ruby 上ではカラムと同じように扱えるフィールドという認識
これは結果的にそのように使えているというだけですね。

で、前置きが長くなりましたが、動かない原因は、viewのcheckboxに指定しているフィールドが:gender_formではなく:genderになっているためだと思われます^^;

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/01 19:50

    ありがとうございます
    ビューのソースは前の質問をそのままはりつけてしまったので修正ミスです

    params には gender_form でとんできていました
    あれからずっとデバッグしてようやくわかったのですが
    permit(:gender_form) と書いた瞬間 gender_form が失われてしまうようなのです…
    ただなぜ消えるのかがよくわかりません
    とりあえず permit を消せば動くことは確認でくたのですが
    質問からは脱線するのでこの辺にしておきますが

    方針としてはモデル内で変換をかくというのでいいのでしょうか

    キャンセル

  • 2019/03/01 21:44

    なるほど、permitは普通に書くと配列を通してくれないみたいですね。
    params.require(:user).permit(gender_form: [])
    とすると大丈夫だと思います。

    他のattributeを加工して目的のattributeに値を入れるのであればmodelのコールバックがいいかなと思います。平文パスワードを暗号化してDBに保存するときなんかもこんなやり方をします。
    ただ、そもそもこのデータの格納方法が最適なのかはどんなアプリケーションか分からないのでなんとも言えないところです。

    キャンセル

  • 2019/03/02 01:54

    ありがとうございます!
    価が配列の場合はpermitの書き方が違うのですね
    その書き方だとちゃんと受け取れました
    しかも他のパラメータと合わせて書く場合最後にかかないとダメみたいでストロングパラメーターも難しいですね…

    キャンセル

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

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

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