【Rails】posts/show.html.erbでcomment#createしたい時のMissing Templateエラー

投稿詳細ページの下部に、その投稿へのコメント欄を作っていた時。
posts/show.html.erbからcomments#createを呼び出して、保存成功なら再度posts/show.html.erbredirect、保存失敗なら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のコントローラーでのrenderメソッドのレシピ集 - Rails Webook

【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のバリデーションエラー後にレイアウトが崩れるとき | Workabroad.jp

【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整形ツール。

tm-webtools.com

ボタンひとつでこれ↓が

[{"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_nameuser_nameが取得できる。

参考文献


万一間違いがあった場合はコメント欄よりご指摘ください。

【Git】.gitignoreサンプル

.gitignoreに何を追加したらいいか迷った時にググっていたら、素晴らしい.gitignoreテンプレなるものを発見した。

github.com

リポジトリルートの.gitignoreを差し替えるだけ。 自分の言語/環境に合わせて使おう!