【Rails】posts/show.html.erbでcomment#createしたい時のMissing Templateエラー
投稿詳細ページの下部に、その投稿へのコメント欄を作っていた時。
posts/show.html.erb
からcomments#create
を呼び出して、保存成功なら再度posts/show.html.erb
にredirect
、保存失敗ならrender
をさせようとして結構ハマった。
次のように書くとrender
した時にMissing Template
エラーが出る。posts#show
を呼んでほしいのに、comments#show
を探しちゃってるっぽい。
# comments_controller.rb def create @post = Post.find(params[:post_id]) @comments = @post.comments @comment = Comment.new(comment_params) @comment.post_id = @post.id if @comment.save redirect_to post_path(@post.id) else render post_path(@post.id) end end
こんな時は明示的に「posts/show
のテンプレートを呼び出してくれ」と指定しましょう。render
部分を次のように書き換え。
render template: 'posts/show'
結構ハマったけどこれでようやく解決しました。
該当部分周辺のコード全文↓
# config/routes.rb resources :posts do resources :comments, only: [:create] end
<%# posts/show.html.erb %> <%= form_with model: @comment, url: post_comments_path(@post.id), method: :post, local: true do |f| %> <table> <tr> <td><%= f.text_field :comment, value: @comment.comment, placeholder: 'コメント' %></td> <td><%= f.submit '送信' %></td> </tr> </table> <% end %>
# posts_controller.rb def show @post = Post.find(params[:id]) @comment = Comment.new end
# comments_controller.rb def create @post = Post.find(params[:post_id]) @comments = @post.comments @comment = Comment.new(comment_params) @comment.post_id = @post.id if @comment.save redirect_to post_path(@post.id) else render template: 'posts/show' end end private def comment_params params.require(:comment).permit(:post_id, :comment) end
参考文献
【Rails】バリデーションエラー後にレイアウトが崩れるのを防ぐ
現象
フォームのバリデーションエラーで入力画面に戻った時になぜかレイアウトが崩れてしまう。
原因
エラーが出ると、そのエラーが出ている部分の要素がdiv
で囲まれてしまうからなんだそうな。
<div class="field_with_errors">フィールド</div>
エラーが出ると勝手にこのdiv
が出現する。
回避方法
config/application.rb
に下記を追記。div
が勝手に生成されなくなって、レイアウト崩れも起こらなくなった。
config.action_view.field_error_proc = Proc.new do |html_tag, instance| html_tag end
追記しただけでは変化が見られない場合はサーバーの再起動をしよう!
参考文献
【Rails】コントローラー系とモデル系の作成コマンドと書き方 総まとめ
コントローラー系とモデル系の作成コマンドと書き方に関して、日頃自分が知りたいと思い都度ググっている情報を全部まとめた。(オプション系は省略)似たような誰かのためにもなったら嬉しい。
コントローラー系
コントローラーとビューの作成
$ rails g controller コントローラー名(複数形) アクション名
サンプル
$ rails g controller Tweets index
生成されるもの
- controllers内に tweets_controller.rb
- views内に tweetsフォルダ
- views内のtweetsフォルダ内に index.html.erb
コントローラーのみ作成
なし
モデル系
モデルとマイグレーションファイルの作成
$ rails g model モデル名(単数形) カラム名:データ型
※カラムを複数作る時でもカンマは不要。
サンプル
$ rails g model Tweet user_id:integer tweet:text
生成されるもの
- models内に tweet.rb
- db/migrate内に YYYYMMDDHHMMSS_create_tweets.rb
マイグレーションファイルのみ作成
$ rails g migration Addカラム名Toテーブル名 カラム名:データ型
※カラム削除の場合はRemoveカラム名Fromテーブル名
とする。他にもRenameとか色々あるけど個人的にはあまり使わないので割愛。
※カラムを複数作る時でもカンマは不要。
サンプル
$ rails g migration AddTitleToTweets title:string
生成されるもの
- db/migrate/内に YYYYMMDDHHMMSS_add_title_to_tweets.rb
マイグレーションファイルの中身/書き方
新規テーブル作成
class モデルクラス名 < ActiveRecord::Migration def change create_table :テーブル名 do |t| t.データ型 :カラム名, null: nullを許可するかどうか(true or false), default: デフォルト値, comment: 'コメント' t.timestamps end end end
サンプル
class CreateLikes < ActiveRecord::Migration def change create_table :likes do |t| t.integer :tweet_id, null: false, default: 0, comment: 'いいねされたツイートのID' t.integer :user_id, null: false, default: 0, comment: 'いいねしたユーザーのID' t.timestamps end end end
カラム追加
class モデルクラス名 < ActiveRecord::Migration def change add_column :テーブル名, :追加したいカラム名, :データ型, after: :どのカラムの後に追加するか, null: nullを許可するかどうか(true or false), default: デフォルト値, comment: 'コメント' end end
サンプル
class AddTitleToTweets < ActiveRecord::Migration def change add_column :tweets, :title, :string, after: :tweet, null: false, default: '', comment: 'ツイートのタイトル' end end
カラム削除
class モデルクラス名 < ActiveRecord::Migration def change remove_column :テーブル名, :削除したいカラム名, :データ型 end end
サンプル
class RemoveTitleFromTweets < ActiveRecord::Migration def change remove_column :tweets, :title, :string end end
マイグレーション実行
$ rails db:migrate
【JSON】読みやすく整形する
開発時に思った通りのJSONがきちんと返ってきているか確認したい時がチラホラあると思う。でもJSONって見にくい...。そんな時に便利なJSON整形ツール。
ボタンひとつでこれ↓が
[{"id": 1,"user_id": 1,"tweet": "テストだよ","created_at": "2018-11-19T17:09:25.000+09:00","updated_at": "2018-11-19T17:09:25.000+09:00"},{"id": 2,"user_id": 1,"tweet": "jsonだよ","created_at": "2018-11-20T16:19:28.000+09:00","updated_at": "2018-11-20T16:19:28.000+09:00"}]
こう↓なります。
[ { "id": 1, "user_id": 1, "tweet": "テストだよ", "created_at": "2018-11-19T17:09:25.000+09:00", "updated_at": "2018-11-19T17:09:25.000+09:00" } { "id": 2, "user_id": 1, "tweet": "jsonだよ", "created_at": "2018-11-20T16:19:28.000+09:00", "updated_at": "2018-11-20T16:19:28.000+09:00" } ]
「JSON 整形」のキーワードでググると他にも似たようなサービスが色々ヒットしました。自分にとって使いやすいものをお好みで。
製作者様に大感謝!!!
【Docker】今まで普通に動いていたコンテナが突然起動しなくなった時
昨日まで普通に動いていたDockerコンテナが突然起動しなくなった時など、焦ってとりあえずイメージ削除&再起動とかしてしまうけど(私だけ?)、その前に立ち上がらない原因をちゃんと突き止めよう、というお話。ついつい焦りが生じてしまって忘れがちなのでメモ。
$ docker logs コンテナID
これでコンテナ内部で何が起きているのか確認できます。
確認できたらそこに表示されているエラーメッセージをコピペで更にググるなり、調べなくても解決法が分かるようだったら自力で対処しましょう。
あわせて読んでおくといいかも◎
dockerでコンテナが立ち上がらないときやってみること - Qiita
余談
個人的に比較的よく起こるのがこれ。
$ docker logs コンテナID => Booting Puma => Rails 5.2.1 application starting in development => Run `rails server -h` for more startup options A server is already running. Check /app/tmp/pids/server.pid. Exiting
Dockerさん:「あなたが立ち上げようとしてるコンテナは既に立ち上がってるよー。既に立ち上がってるのに追い討ちかけて立ち上げようとされましてもー。」
って感じ。多分。言われている通り/app/tmp/pids
フォルダ内を確認しましょう。server.pid
が残っていると、起動していないコンテナでもDockerさんが既に起動していると思い込んでしまうようです。docker-compose down
が正常にできなかった時とかに残ってしまうみたいですがよく分かりません...。とりあえず手動でserver.pid
を削除してから再度起動すると直ってます。(コンテナ起動するとまた自動で生成されるので恐れず手動削除してしまってOK)
【Rails】リレーションを張った2つのテーブルのJSONをまとめて取得
個人練習でTwitterもどきを作っていた時に、リレーションを張った2つのテーブル(TweetsテーブルとUsersテーブル)のJSONをまとめて取得したい時があった。一度知ってしまえば記述はシンプルなのに、最初は調べてもなぜかすぐにはヒットしなかったので、まとめ。
before
tweets_controller.rb
def index tweets = Tweet.all.where(user_id: current_user.id) respond_to do |format| format.html # 通常のURLの場合、index.html.erb が返される format.json { render json: tweets.to_json } # URLが.jsonの場合、tweets.to_json が返される end end
index.json
[ { "id": 1, "user_id": 1, "tweet": "テストだよ", "created_at": "2018-11-19T17:09:25.000+09:00", "updated_at": "2018-11-19T17:09:25.000+09:00" } { "id": 2, "user_id": 1, "tweet": "jsonだよ", "created_at": "2018-11-20T16:19:28.000+09:00", "updated_at": "2018-11-20T16:19:28.000+09:00", } ]
after
tweets_controller.rb
def index tweets = Tweet.all.where(user_id: current_user.id) respond_to do |format| format.html format.json { render json: tweets.to_json(:include => :user) } # (:include => :user)を追加 end end
index.json
[ { "id": 1, "user_id": 1, "tweet": "テストだよ", "created_at": "2018-11-19T17:09:25.000+09:00", "updated_at": "2018-11-19T17:09:25.000+09:00", "user": { id: 1, user_name: "ほげ" } } { "id": 2, "user_id": 1, "tweet": "jsonだよ", "created_at": "2018-11-20T16:19:28.000+09:00", "updated_at": "2018-11-20T16:19:28.000+09:00", "user": { id: 1, user_name: "ほげ" } } ]
こうすればtweets.user.user_name
でuser_name
が取得できる。
参考文献
万一間違いがあった場合はコメント欄よりご指摘ください。
【Git】.gitignoreサンプル
.gitignoreに何を追加したらいいか迷った時にググっていたら、素晴らしい.gitignoreテンプレなるものを発見した。
リポジトリルートの.gitignoreを差し替えるだけ。 自分の言語/環境に合わせて使おう!