初めてのWebアプリ開発:4日目
はじめてのオリジナルWebアプリ開発を始めて4日目の記録。
現在レシピ投稿アプリを開発しています。
今日学んだことまとめ
ネストした子モデルのparamsを親モデルのコントローラーで受け取り、保存する方法。
Model
class Recipe < ApplicationRecord belongs_to :user has_many :ingredients, dependent: :destroy has_many :instractions, dependent: :destroy accepts_nested_attributes_for :ingredients, allow_destroy: true accepts_nested_attributes_for :instractions, allow_destroy: true end
class Ingredient < ApplicationRecord belongs_to :recipe end
class Instraction < ApplicationRecord belongs_to :recipe end
View
<%= form_for(recipe) do |f| %> #(フォーム内容) <% end %> </div> #今回はフォームで入力フィールドを増減できるよう「nested_form_fields」のgem使用
Controller
def new @recipe = current_user.recipes.build #recipeモデルのインスタンス生成 .buildは保存はせず生成のみ @recipe.ingredients.build #recipeモデルに関連づいたingredientモデルのインスタンス生成 @recipe.instractions.build #recipeモデルに関連づいたinstractionモデルのインスタンス生成 end def create @recipe = current_user.recipes.build(recipe_params) #@recipeの引数にフォームから受けとるrecipe_paramsを渡す。 if @recipe.save #ここで保存。 flash[:success] = 'レシピを投稿しました。' redirect_to current_user else flash[:danger] = 'レシピの投稿に失敗しました。' render :new end end private def recipe_params #親モデル(recipes)のコントローラーでネストされた子モデル(ingredients,instractions)のparamsも合わせて取得する params.require(:recipe).permit( :title, :content, :volume, ingredients_attributes: [:name, :amount, :_destroy], instractions_attributes: [:content, :_destroy] ) end
link_toメソッドで渡すべき引数について
レシピ一覧ページでは概要(タイトルとおすすめ文)だけ表示し、レシピ詳細ボタンを押すと詳しいレシピを表示するようにしました。
この概要ページから詳細ページへ引数を渡すところでエラー文が出て、渡すべきパラメーターについて理解が曖昧だったことに気づき、link_toメソッドの勉強になったので記録。
recipe概要ページのView内(複数回renderするのでパーシャル)のlink_toメソッド記述欄
<% recipes.each do |recipe| %> #recipesから一つずつrecipeオブジェクトを取り出し変数recipeに代入していく <%= recipe.title %> <% user = recipe.user %> <%= link_to user.name, user_path(user), class: 'text-left' %><span class="text-muted pull-right"><%= l recipe.created_at, format: :short %></span> #user_path(user)では引数としてuserオブジェクトを指定。つまりeachメソッドによって取り出された個別のuserモデルオブジェクト、つまりuser.idがリンク先のパスに指定される。users#showに対するパスであるuser_path(user)で生成されるパスは$rails routesで確認すると/users/:id/(.:format)なので、最終的に/users/2(user.id = 2の場合)のようなパスが生成される。 #(途中省略) <%= link_to 'レシピ詳細', recipe_path(recipe, user_id: user.id) %> #recipe(Recipeモデルのオブジェクト)を引数で渡す。 #これはrecipe_path()で生成されるパスを$rails routesで確認するとわかる。 #生成されるパスは/recipes/:id/(.:format)でありrecipe.idが渡される必要がある。 <% end %>
エラー文から、ルーティングをいじったため生成されるパスが変わったことにより、渡すべき引数が変わってしまったことが原因であると判断。
これをレシピコントローラーのprivate下のparamsで受け取ります。
recipes_controller
class RecipesController < ApplicationController before_action :recipe_params_show, only: [:show] def show end private def recipe_params_show @recipe = Recipes.find_by(id: params[:id]) end end
今日はこんな感じで色々と勉強になりました。ここはこうした方がいいよ、とかここは間違っているよ、などのご指摘があればぜひ教えていただけると有難い限りです!
現在主に、「Ruby on Rails 5 アプリケーションプログラミング」の書籍をメインに勉強しています。
疑問が出たらまずはこの本で調べます。特に複数データベースのアソシエーションについては度々参照しています。
この本に乗っていない場合はググるかQuiitaやStackOverflowなどで調べています。StackOverflowでは英語の記事数が日本語のそれに比べ圧倒的に多いため、英語の記事もよく参照しています。
Ruby on Rails 5アプリケーションプログラミング
- 作者: 山田祥寛
- 出版社/メーカー: 技術評論社
- 発売日: 2017/04/14
- メディア: 大型本
- この商品を含むブログを見る
「Ruby on Rails 5 アプリケーションプログラミング」の前に参考にしていたのはこちらの書籍です。初心者にとっても親切丁寧に解説されており、上の書籍に進む前の段階で大変お世話になりました。
- 作者: 掌田津耶乃
- 出版社/メーカー: 秀和システム
- 発売日: 2016/12/17
- メディア: 単行本
- この商品を含むブログを見る
他にも購入したい書籍が山積みですが、地道に一歩づつ。
4月後半から始めたプログラミング、まだまだ先は長いですが頑張りたいと思います。