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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

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

Q&A

2回答

4159閲覧

rails:strong parameterについて教えてください

su--ss

総合スコア12

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby

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

0グッド

0クリップ

投稿2018/10/21 09:30

前提・実現したいこと

railsを学習中の初学者です。
railsでの写真の投稿機能を作製中、空の投稿を行った際にエラーが発生してしまいます。

ParameterMissingの示す通り、strongparameterで指定したmicropostが空だと言われていると思うのですが、どのようにコードを記述すれば問題がないのか、解決の方法がわかりません。

micropost_paramsに何も入っていないため@micropost.saveが失敗し、if文のelseの分岐に入らないのはなぜなのだろう?と疑問に思っています。

お力をお貸しいただけると幸いです。

発生している問題・エラーメッセージ

Started POST "/microposts" for 103.5.142.123 at 2018-10-21 08:45:03 +0000 Cannot render console from 103.5.142.123! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by MicropostsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"PPaLrLIV51b+cnsyD5lpWrO+TbisckvNPcVURZWQiu7g+TUR2/wPjTHEJyM+vk5t975hvrQqj+PElz8PaF+dcg==", "commit"=>"Create Micropost"} User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ? [["id", 3], ["LIMIT", 1]] Completed 400 Bad Request in 3ms (ActiveRecord: 0.2ms) ActionController::ParameterMissing (param is missing or the value is empty: micropost): app/controllers/microposts_controller.rb:26:in `micropost_params' app/controllers/microposts_controller.rb:7:in `create'

該当のソースコード

controller

1class MicropostsController < ApplicationController 2 before_action :authenticate_user! 3 before_action :collect_user,only: :destroy 4 5 6 def create 7 @micropost = current_user.microposts.build(micropost_params) 8 if @micropost.save 9 flash[:success] = "Micropost created!" 10 redirect_to root_path 11 else 12 @feed_items = [] 13 render "static_pages/home" 14 end 15 end 16 17 def destroy 18 @micropost.destroy 19 flash[:success] = "Micropost deleted" 20 redirect_to root_path 21 end 22 23 private 24 25 def micropost_params 26 params.require(:micropost).permit(:picture) 27 end 28 29 def collect_user 30 @micropost = current_user.microposts.find_by(id: params[:id]) 31 redirect_to root_path if @micropost.nil? 32 end 33 34end 35

model

1class Micropost < ApplicationRecord 2 belongs_to :user 3 default_scope -> {order(created_at: :desc)} 4 mount_uploader :picture, PictureUploader 5 validates :user_id, presence: true 6 validates :picture, presence: true 7 validate :picture_size 8 9 def picture_size 10 if picture.size > 5.megabytes 11 errors.add(:picture, "should be less than 5MB") 12 end 13 end 14end 15

form

1<%= form_for(@micropost) do |f|%> 2 <%= render 'shared/error_messages', object: f.object %> 3 4<%= f.label :picture%> 5<%= f.file_field :picture,accept: "image/png,image/jpeg"%> 6 7<%= f.submit class: "btn btn-primary" %> 8 9<% end %>

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Rais学んで半年ぐらいの者です。うまくいかない可能性もありますが、よろしくお願いします。

画像のアップロードをする際に、nilでも許容したい!という質問に受け取れるので、
fetchメソッドを使うといいと思います。

使い方としては

params.fetch([オブジェクト],{}).permit([カラム1],[カラム2],…)

みたいな感じですね!
これで、オブジェクトがnilでも許容されます!

fetchメソッドは、rubyのメソッドです。
ハッシュオブジェクトのメソッドで、対応するキーがないと第2引数に指定したオブジェクトを返すメソッドです。

params: { micropost: { picture: nil } }

を渡したいと思うので、

params.fetch(:microposts, {}).permit(:picture)

でうまくいくのではないかと思います。

また、DBでNotNull制約やModelでvalidationを組んでいたら@micropost.saveで弾かれる可能性もあると思いますので、気をつけてください!

参考文献

  • rubyのfetchメソッドに関して

https://ref.xaio.jp/ruby/classes/hash/fetch

  • Railsのストロングパラメータ

https://qiita.com/mochio/items/45b9172a50a6ebb0bee0#%E6%8C%87%E5%AE%9A%E3%81%97%E3%81%9F%E3%82%AD%E3%83%BC%E3%81%8C%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AB%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E5%87%BA%E3%81%95%E3%81%AA%E3%81%84%E3%82%88%E3%81%86%E3%81%AB%E3%81%99%E3%82%8B

投稿2018/10/21 18:23

Gonzaemon

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

私も初学者なので、的外れなことを申し上げているかもしれませんが…。

micropost_paramsに何も入っていないため@micropost.saveが失敗し、if文のelseの分岐に入らないのはなぜなのだろう?と疑問に思っています。

 こちらの件に関してお答えしたうえで、どうすれば意図した動作をしてくれるのかに関して記述させていただければと思います。

 今回のエラーに関して結論から申し上げますと、@mivropost.saveに処理が到達する前にエラーが発生しているということだと思われます。そして、エラーメッセージが示している通り、その原因はstrong_parameterにあります。

 まず最初に確認しておくべきなのは、「今回発生したエラーはどんなエラーか」という点ですね。

ActionController::ParameterMissing (param is missing or the value is empty: micropost)

ParameterMissingの示す通り、strongparameterで指定したmicropostが空だと言われていると思うのですが、

 もちろんその認識で問題ないのですが、今回の場合は**「micropost?そんなもんは存在しないよ!」と言われているように思います。param is missing の部分にあたりますね。strongparameterを活用する際、特に今回のようにrequire(:foo).permit(:bar)という書き方をしている場合、:fooに当たる部分が送られてこない場合には、nilではなくてParameterMissingを返します。**これが今回、if文に到達してくれない理由だと考えられます。

さて、では、「どうしたらこのエラーを回避することができるのか」という話題に移ります。
先にサンプルコードを記述させていただきますね。

controller

1def create 2 if micropost_params.present? 3 @micropost = current_user.microposts.build(micropost_params) 4 @micropost.save 5 flash[:success] = "Micropost created!" 6 redirect_to root_path 7 8 else 9 @feed_items = [] 10 render "static_pages/home" 11 end 12end

上記のコードでは、if micropost_params.present?を最初に持ってくることによって、micropost_params自体が渡ってきているかどうかstrongparameterに行く前に確認しています。すると、micropost_paramsが存在しない-つまりはParameterMissingを吐かれるような状況-では、strongparameterが読まれません。

おそらくこれで、「if文が動かない理由」と「どうしたらエラーを回避できるのか」に関してお答えできていると思います。
おかしなことを言っていたら、ご指摘いただけますと幸いです。
よろしくお願いいたします。

投稿2018/10/21 18:21

take77

総合スコア130

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

su--ss

2018/10/21 20:53

お二方とも大変丁寧なご回答ありがとうございます。 ご解説頂いたことも含め大変勉強になりました。 結果から申し上げますとGonzaemonさんの方法で動作しました。 しかしながらtake77さんにお教え頂いた方法でも動きそうなのに、なぜ動作しないのだろう?と調べて見た所、present?メソッドに原因があるのかと思いました。 railドキュメントによると、present?は、変数.present?のような形で使用し「nil, "", " "(半角スペースのみ), [](空の配列), {}(空のハッシュ) のときにfalseを返します。」とありました。 http://railsdoc.com/references/present 1、parameterMissingが帰っている現状 2、method.present? になっているため使えないということなのかな?と思いました。 この解釈も間違っていたらご指摘頂けるとありがたいです。 重ね重ねになりますが回答ありがとうございました。
take77

2018/10/22 01:58 編集

丁寧な返信、ありがとうございます。 1、parameterMissingが帰っている現状 2、method.present? 解釈はそれであっていると思います。 今回の件ですが、これは私の記述がおかしかったです…。 "micropost_params.present?"と記載していたところですが、正しくは"micropost_params[:picture]"でした。 こうしないと、micropost_paramsが値として取ってもらえないですね。 失礼いたしました(また動かなかったらどうしよう、と内心ビビっています)。 また補足になりますが、私自身の慣習としてDBでnull: falseを可能な限り記載しています。 この辺りの記述に関しては人の趣味が現れるみたいですね。 Gonzaemonさんの記述方法に関しては全く考えていなかった記述でしたので、私も勉強になりました。 Gonzaemonさんにもこの場を借りてお礼申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問