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

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

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

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

Ruby on Rails

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

Q&A

解決済

3回答

13618閲覧

Ruby on Railsでrenderでフォームの内容を保持する実装について

dongw

総合スコア119

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2017/04/13 01:25

編集2017/04/13 02:02
def new @hoge = Hoge.new(hoge_params) end def create @hoge = Hoge.new(hoge_params) if @hoge.save redirect_to hoge_path, notice: "作成しました" else render 'new' @hoge = Hoge.new(hoge_params) end end
= form_for @hoge do |f| タイトル = f.text_field :title, placeholder:'タイトル' 本文 = f.text_field :content, placeholder:'本文' = f.submit '作成'

このような記述をしrenderで再描写後にフォームに打ち込んだ文字がセットされている仕組みってどうなっているんでしょうか?

form_forで@hogeを使っているのはデータの送り先を表しているもの、
と考えていたので、@hogeがrender後に再び代入されただけで、フォームに文字がセットされる仕組みがどういう風になっているのかがわかりません。

また、

else @hoge = Hoge.new(hoge_params) render 'new'

このような記述もしてみたのですが動作してくれませんでした。
これは何故でしょうか?
renderはビューの再描写をするだけ、ということなので@hogeが再代入されるタイミングが前でも同じかなあ、と思ったのですが

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

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

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

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

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

guest

回答3

0

form_forヘルパで作るフォームは、渡されたリソース(@hoge)に対応する適切なaction属性を生成するのととともに、各フィールドにリソースの属性値を設定することもやってくれます。さらに、バリデーションのエラー情報の内容もフィールドの表示に反映します。

scaffoldで作成されるコードのeditアクションとそのビューを見てみればわかると思います。ほとんどnewと共通になっていますが、表示させるとフィールドにはリソースの値が設定されています。

最初のコードで

else render 'new' @hoge = Hoge.new(hoge_params)

となっていますが、@hoge = Hoge.new(hoge_params)の値はどこにも使われていないので、意味がありません。無くても同じ動作をするはずです。(コールバックなどがあれば別)

else @hoge = Hoge.new(hoge_params) render 'new'

この前に@hoge.saveした時点で、@hogeにはどのカラムでエラーがあったのかという情報も追加されます。しかし、Hoge.newしてしまったのでその情報が失われてしまいます。結果、ビューにはエラーの情報は反映されません。

投稿2017/04/13 02:37

suzukis

総合スコア1449

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

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

dongw

2017/04/13 05:30

回答ありがとうございます。 saveしようとした瞬間にバリデーションに引っかかったら@hogeにエラーの情報、パラメータ?が付与されるということでしょうか? その情報があるからこそバリデーションエラーがビューで表示できるのに新しく@hogeを作ってしまったからバリデーションの情報は消えてしまったのですね。
guest

0

ベストアンサー

コメントの補足です。

ruby

1def new 2 # オブジェクトA ... (1) 3 @hoge = Hoge.new 4end 5 6def create 7 # オブジェクトB ... (2) 8 # (1)の@hogeとは別の新規のオブジェクト 9 @hoge = Hoge.new(hoge_params) 10 11 # オブジェクトB 12 # バリデーションエラーが起きれば、オブジェクトBにエラー内容を保持 13 if @hoge.save 14 redirect_to hoge_path, notice: "作成しました" 15 else 16 # オブジェクトC 17 # Hoge.newにより新規に作られたオブジェクトが@hogeに設定される 18 # バリデーションエラーはオブジェクトBが持っているが、 19 # @hogeが指すのは、オブジェクトCになってしまったので 20 # エラーは表示されない 21 @hoge = Hoge.new(hoge_params) # オブジェクトB 22 23 render 'new' 24 end 25end

投稿2017/04/13 02:14

mingos

総合スコア4025

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

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

dongw

2017/04/13 05:41

詳しく書いていただきありがとうございます。 1点伺いたいのですが、 @hogeに情報を保持しているからフォームに情報が残ったまま、というのはform_forの機能としてもあるのですか? newからcreateに飛んだ場合ページ遷移し、@hogeというオブジェクトの情報をcreateで使えるだけだと思うのですが、フォームの適正な位置に文字が入っているということはformのidなどの情報も@hogeに持たされているということですか?
mingos

2017/04/13 05:51

form_for @hoge do |f| としている事により、 fを通して@hogeの内容を利用できます。 f.text_field :title で、@hoge.titleの内容が、inputタグのvalueに自動でセットされるのはこのためです。 f.text_field :titleは、 text_field_tag "hoge[title]", @hoge.title と同じ意味になります。
dongw

2017/04/14 01:39

なるほど! それはもしこれがform_tagで作ったフォームでしたらオブジェクトに結びつかないフォームなので この場合renderしてもフォームの内容は自動ではセットされない、ということでしょうか?
mingos

2017/04/14 02:01

値のセットは、viewの中のtext_field、text_field_tagが担当しています。 text_field_tagはこちらが第二引数に値を正しく渡す必要がありますが、値はセットされます。 自動=ユーザが入力したものが画面に出てくるという意味であれば、form_tagでも自動でセットされます。
dongw

2017/04/17 01:50

大変親切にコメントありがとうございます。 最後の質問なのですが、 text_field_tagで値をセットする方法としてはrender で値を渡してあげる方法を取るのでしょうか?
mingos

2017/04/17 02:41

値を渡すという表現は、プログラミングにおいては関数(メソッド)の引数に渡すという意味合いが強いです。 renderメソッドには値を渡してないですよね? なので、renderで値を渡すわけでありませんという言い方になります。 text_field_tagは、inputタグを生成するヘルパーメソッドです。 何をしているかというと、 <input type="text" name="パラメータ名" value="値" /> というHTMLタグを生成します。 「text_field_tagに値をセットする」とは、このvalueに値をセットされた状態のHTMLタグを作る事を指します。 valueに値をセットするには、text_field_tagの第二引数に渡します。 @hoge.titleを例にすると、@hoge.titleに"テスト"が入っているとすると、 <%= text_field_tag("hoge[title]", @hoge.title) %> ↓ <input type="text" name="hoge[title]" value="テスト" /> という事です。 うまく伝わるといいのですが・・。
dongw

2017/04/18 05:03

なるほど、text_field_tagに値をセットしてあげることが必要なのですね。 とても勉強になりました。ありがとうございました!
guest

0

elseの後の
@hoge = Hoge.new(hoge_params)
の行が必要ありません。
@hoge.saveで失敗しても@hoge自体は残っているので
@hogeに登録されている情報が引き継がれるはずです。

でもこのコードはユーザーの登録のような気がします。

投稿2017/04/13 01:38

編集2017/04/13 01:52
moke

総合スコア2241

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

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

dongw

2017/04/13 02:00

回答ありがとうございます。 ログイン失敗ではなくて作成でした、タイトル間違っていました。 今確認したところ確かに@hoge = Hoge.new(hoge_params) は要りませんでした、申し訳ないです。 しかし、 else @hoge = Hoge.new(hoge_params) render 'new' とするとフォームは保持されるのですが、バリデーションエラーは出ません。 どうなっているんでしょうか?
mingos

2017/04/13 02:15

エラー内容はオブジェクトに設定されますが、@hoge = Hoge.new(hoge_params)によって別のオブジェクトが@hogeに割り当てられるため、エラーが消えてしまいます。 コメントだと説明しづらいので、回答に記載します。
moke

2017/04/13 02:53

elseの後の @hoge = Hoge.new(hoge_params) で@hogeエラー情報を持った@hogeを上書きしてるって説明で十分なのでは?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問