【Sinatra】アクティブレコードを使って1対多の関係を表してみる

Sinatraでアクティブレコードを使って、ユーザと投稿内容を紐づけて、誰が投稿したのかということを出力してみます。1対多の関係ってやつですね。
アクティブレコードを使ってるのでRailsと同じのはずなんで、実証していきます!

*参考
https://qiita.com/yukihigasi/items/4464616f24f3a7684c0d
コード
https://github.com/WilliamMena/sinatra-assessment-has_many_recipes

DB構成

UserテーブルとPostテーブルを作成します。
カラムは以下の通り。

Userテーブル

class CreateUsers < ActiveRecord::Migration[6.0]  
  def change  
    create_table :users do |t|   
      t.string :name  
      t.string :email  
      t.string :password_digest  
    end  
  end  
end  

Postテーブル

class CreatePosts < ActiveRecord::Migration[6.0]  
  def change  
    create_table :posts do |t|  
      t.string :content  
      t.references :user, foreign_key: true  

      t.timestamps  
    end  
  end  
end  

シンプルな内容にしました。

モデル

user.rb

class User < ActiveRecord::Base  
    validates :name, presence: true, length: { maximum: 50 }  
    validates :email, presence: true, length: { maximum: 255 },  
                      format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i },  
                      uniqueness: { case_sensitive: false }  
    has_secure_password  

    has_many :posts  
end  

Userテーブルではバリテーションとパスワードの設定をしています。
has_many :posts でpostテーブルと関係付けをします。

コントローラ

アプリケーションファイルの設定をします。

post.rb

    post '/create' do  
        @current_user ||= User.find(session[:user_id]) if session[:user_id]  
        current_user = @current_user  
        @post = Post.new  
        @post.content = params["content"]  
        @post.user = current_user  
        @post.save  
        if @post.save  
          flash[:success] = '投稿成功'  
          flash[:success] = @post.user  
          redirect 'post/all'  
        else  
          redirect '/session/signup'  
        end   
      end  

少し見にくいですが、一旦Postオブジェクトを作成して、そのあとに保存したいレコードのカラムを追記していってます。

Getも見てみましょう。

post.erb

    get '/all' do  
        @current_user ||= User.find(session[:user_id]) if session[:user_id]  
        @posts = Post.all  
        @user = User.all  
        @post_user = Post.where(user_id: session[:user_id]).all #ログイン中のユーザ  
        @post_user = Post.where(user_id: params[:id]).all #paramsで引き渡す場合  

        @gon_user = @user  
        @gon_posts = @posts  
        @gon_post_user  = @post_user   
        gon.user = @gon_user  
        gon.posts = @gon_posts  
        gon.post_user = @gon_post_user   
        erb :'post/all'  
    end  

@post_user に、ログイン中のユーザか、詳細画面のユーザの投稿を取得することができます。
最後の方にgon がうるさいのは、rubyの変数をjsファイルに持っていくためです。(超便利)

erbファイル

<% @posts.each do |post| %>  
    <p>  
    <%= post.id %>  
    <%= post.content %>  
    <%= post.user_id %>  
    <p>  
    <td>  
    <form method="post" action="/post/delete/<%= post.id %>">   
        <button class = "btn btn-outline-secondary" type="submit">投稿の削除</button>  
    </form>  
</td>  
<% end %>  

postにuser_id を追加しました。

jsファイルに、

console.log(gon.post_user)  

と記述して該当画面を開くと、

ユーザIDが取得されています。

erbファイルに以下のコードを追加します。

<% @post_user.each do |post_user| %>  
  <%= post_user.content%>  
<% end %>  

すると、(今回はログイン中の)ユーザが投稿したレコードが取得されました!

投稿内容にもuser_id が取得されてますね!

まとめ

Railsと全く同じかと思いきや、少し違いました。笑