Hitsuji_monのブログ~ 村上春樹のあれ ~

文学好きな組み込み系エンジニア

ユーザ専用掲示板画面 | eachには配列を渡そう

eachで取り出す対象は「オブジェクトじゃダメ。配列で渡そう」

Before: エラー時
boards_controller.rb

# boards_controller.rb
~~
    def index_personal
        @boards = params[:tag_id].present? ? Tag.find(params[:tag_id]).boards : Board.find_by(user_id: @current_user)
    #  @boards = @boards.page(params[:page])
        binding.pry
    end
~~

index_personal.html.erb

# index_personal.html.erb
~~
<% @boards.each do |board| %>
    <tr>
      <td><%= board.id %></td>
      <td><%= board.title %></td>
      <td><%= board.name %></td>
      <td><%= board.created_at.to_s(:datetime_jp) %></td>
      <td><%= board.updated_at.to_s(:datetime_jp) %></td>
      <td><%= link_to '詳細', board, class: 'btn btn-outline-dark' %>
      <td><%= link_to '削除', board, class: 'btn btn-outline-dark', method: :delete %>
    </tr>
  <% end %>
~~

エラーメッセージ(&お気持ち)

ActiveRecordを使ってデータにアクセスすると、user_idでフィルターされたデータがちゃんと@boardsに渡されていた。
しかしview側では, eachメソッドが未定義だと言われる。なんでってなった。

NoMethodError in Boards#index_personal
Showing /app/app/views/boards/index_personal.html.erb where line #35 raised:

undefined method `each' for #<Board:0x00007fcf4e39f010>

After: 解決時ver!

# boards_controller.rb
~~
    def index_personal
        @boards = params[:tag_id].present? ? Tag.find(params[:tag_id]).boards : Board.where(user_id: @current_user)  
    #  @boards = @boards.page(params[:page])
        binding.pry
    end
~~
# index_personal.html.erb

# 同じなので略


eachにオブジェクトは渡さない

eachには配列で渡す。そうしないと一つ一つを取り出してループ変数に格納できない

  • find_by(カラム名: データ) : オブジェクトとして結果が格納
  • where(カラム名: データ) : 配列として結果が格納 こっち!!

これでユーザごとにMy掲示板を表示できたわ!!!!

qiita.com

Postgresqlでmigrationができない | Pendingされる時

PostgreSQLRailsアプリを作成中に
「migrationエラー」が起きる問題

f:id:Hitsuji_mon:20191013212344p:plain


原因: すでにデータベースが作成されているのに、新たに同じデータベースを作成しようとすると起きる

結論:PostgreSQLを再起動して、migrationすれば解決

$ bin/rake db:reset
$ bin/rake db:migrate:reset 

これでmigrationできる

teratail.com


migrationエラーの内容

# DBのDROP, CREATE, migrate を自動で実行するコマンド
$ rails db:migrate:reset RAILS_ENV=development
PG::DuplicateTable: ERROR:  relation "comments" already exists
$ rails dp:drop
PG::ObjectInUse: ERROR:  database "app2ch_development" is being accessed by other users
  • PostgreSQLを一度切断し、再度起動しないといけない
# データベースにログイン
$ psql DB名
# 起動中のプロセスを特定する
デーアベース名 = # select * from pg_stat_activity;

プロセス指定して、一個一個切るのはめんどいな

$ brew services stop postgresql # DB終了
$ brew services start postgresql # DB起動


PosgreSQLで強制的にデータベースを削除する方法

psql -l //データベース名を確認
psql postgres //postgreSQLにログイン
\du //ユーザーと権限を確認

ps aux | grep 消したいDB名 // 消したいDB名のプロセスID(数字)を確認
sudo kill プロセスID
//以下例
sudo kill 45912
# postgresqlだとエラーだったので、以下は権限ユーザに書き換え
dropdb -U postgres(もしくは消す権限のもったユーザー) 消したいDB名

PostgreSQLでデータベースを作成する方法

# Ownerも指定
$ createdb MyApp_development -O MyApp
$ createdb MyApp_test -O MyApp

qiita.com

2chのクローンアプリを作る

こちらの「シラバス」をもとに、2chのクローンアプリを作成中
調べないといけないコードをメモ
cyllabus.jp


親子関係のあるモデル

resourcesメソッドによるルーティング
RESTの規約に沿って自動的にルーティングを行う

  • boardsのルーティング内(boardsのパスより下)にcommentsルーティングを作成する

ってことでええんかな

# routes.rb
Rails.application.routes.draw do
  resources :boards do
    resources :comments, only: [:create, :destroy]
  end
end

コメントフォームを作るために、コメントModelを作成

# board.rb
class Board < ActiveRecord::Base
    has_many :comments, dependent: :destroy

    validates :title, presence: true, length: { in: 4..127 }
    validates :editor, presence: true, length: { in: 1..30 }
end
  • 親モデルに依存する子モデル
#comment.rb
class Comment < ActiveRecord::Base
    belongs_to :board

    validates :board, presence: true
    validates :name, presence: true
    validates :content, presence: true, length: {in: 1..1000 }
end
  • 親モデルのcontroller
# boards_controller.rb
~~
class BoardsController < ApplicationController
    def show
        @board = Board.find(params[:id])
        @comment = Comment.new
    end
~~

  • 子モデル(コメントフォーム)のcontroller
class CommentsController < ApplicationController
    def create
        @board = Board.find(params[:board_id])    # 親インスタンスを作成
        @comment = Comment.new(params_comment)
        @comment.board = @board    # 謎!!!
    
        if @comment.save
            redirect_to board_url(@board)
        else
            render "boards/show"
        end
    end

    private

    def params_comment
        params.require(:comment).permit(:namee, :content)
    end
end

  • 入れ子関係のフォーム
    • 入れ子のresourcesのルーティング定義をした場合
    • 新規保存のアクションへのurlは、「親モデル単数形_小モデル複数形_path」という形になり、

引数には親モデルと子モデルが入ります。

<%= form_for @comment, url: board_comments_path(@board, @comment) do |f| %>
      名前: <%= f.text_field :name %> <br>
      コメント: <%= f.text_area :content %> <br>
      <%= f.submit %>
<% end %>