

■前提・実現したいこと

Ruby on Rails で  
複数のユーザーが記事を投稿できる簡単なブログを作っています。  
誰でもemailとpasswordを使ってログインし、  
記事を投稿できるようにしています。

そして今実装したいのは  
「記事のページにいくと記事を投稿した人が誰かをemailアドレスで表示する」  
ということです。

例えば

Aさんがa@yahoo.co.jpでログインし投稿した記事には  
「書いた人：a@yahoo.co.jp」  
と表示し、

Bさんがb@yahoo.co.jpでログインし投稿した記事には  
「書いた人：b@yahoo.co.jp」  
と表示したいです。

userに関してはdeviseを利用しています。

画像で例をあげると、  
ログインしてから下のように記事を投稿すると

[![画像の説明をここに入力](https://i.stack.imgur.com/wwCp3.png)](https://i.stack.imgur.com/wwCp3.png)

記事のページではこのように書いた人を表示させたいです。

[![画像の説明をここに入力](https://i.stack.imgur.com/Bp0iM.png)](https://i.stack.imgur.com/Bp0iM.png)

また編集したときにはemailの表示は変えなくて  
いいようにもしたいです。

つまり  
Aさんがa@yahoo.co.jpでログインし投稿した記事には  
「書いた人：a@yahoo.co.jp」  
と表示しますが、この記事をBさんが編集しても  
「書いた人：a@yahoo.co.jp」のまま  
という感じです。

=================================

これを実装するにあたり  
まずpostにhas_many:usersを加えて関連付けし、

記事のデータ(post)に  
user_idというカラムを追加し、

これにログインして記事を投稿する人のidを  
代入して保存し、viewのhtml.erbの部分で  
「投稿者：<% @post.user.email%>」  
としようとしましたが上手くいきませんでした。

ログインし、実際に記事を投稿しようとしたときに  
以下のようなエラーが出ました。

■発生している問題・エラーメッセージ

[![画像の説明をここに入力](https://i.stack.imgur.com/96mNU.png)](https://i.stack.imgur.com/96mNU.png)

■該当のソースコード

コントローラーは下のようになります。

●application_controller.rbに  
以下のようにコードを書き加え

before_action :set_current_user, only: [:create]

[code]

    def set_current_user
    @current_user = User.find_by(id: session[:user.id])
    end
    
[/code]

●posts_controller.rbにはこのように書いています。

[code]

    class PostsController < ApplicationController
    def index
    @post = Post.all.order(created_at: 'desc')
    end
    
    def show
    @post = Post.find_by(params[:id])
    @user = User.find_by(id: @post.user_id)
    end
    
    def new
    @post = Post.new
    end
    
[/code]

def create  
@post = Post.new(  
content: params[:content],  
user_id: @current_user.id  
)  
if @post.save  
redirect_to root_path  
else  
render 'new'  
end  
end

[code]

    def edit
    @post = Post.find(params[:id])
    end
    
    def update
    @post = Post.find(params[:id])
    if @post.update(post_params)
    redirect_to post_path
    else
    render 'edit'
    end
    end
    
    def post_params
    params.require(:post).permit(:title, :body)
    end
    end
    
[/code]

●show.html.erbに書いた部分は以下です。

[code]

    <p>書いた人:<%= @post.user.email %> </p>
    
[/code]

●modelのpost.rbも載せておきます。

[code]

    class Post < ApplicationRecord
    validates :title, presence: true
    validates :body, presence: true
    has_many :users
    end
    
[/code]

●dbはこのようになっています。

[code]

    ActiveRecord::Schema.define(version: 20171209035931) do
    
    create_table "posts", force: :cascade do |t|
    t.string "title"
    t.text "body"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "user_id"
    end
    
    create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    end
    
    end
    
[/code]

■試したこと

↓のサイトに書かれている通りにやってみました。  
<https://qiita.com/you88/items/63ad0b9c07da4323fe26>

しかし上手くいかず、色々と調べたり  
変数いじったりしてみたのですが解決しません。

■補足情報(言語/FW/ツール等のバージョンなど)

補足というか思ったの事なのですが  
エラーのidがnil Classとなっていますが、  
そもそも＠current_userにログインしている  
ユーザーの値が入っていないのではないか  
と思っております。

困っています。  
よろしくお願いいたします。

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

**追記**

ご返信ありがとうございます。

ご指摘の通りhas_manyは間違っていたと思います。  
ありがとうございます。  
ですが、ほかの部分でつまっているので  
もう少しお力をお貸しいただけたらと思います。

現在このように記事を  
投稿しようとしたら  
このようなエラーがでるという状況です。

[![画像の説明をここに入力](https://i.stack.imgur.com/CaAi2.png)](https://i.stack.imgur.com/CaAi2.png)

上にも書いたのですが、  
コントローラーは

application_controller.rbでは

before_action :set_current_user, only: [:create]

def set_current_user  
@current_user = User.find_by(id: session[:user_id])  
end

post_controller.rbでは

def create  
@post = Post.new(  
post_params,  
user_id: current_user.id  
)  
if @post.save  
redirect_to root_path  
else  
render 'new'  
end  
end

としています。

解決策があれば  
教えて戴けたらと思います。  
どうかよろしくお願いします。

==================================================

**追記２**

ありがとうございます。  
前者の方で試してみることにしました。

しかし、ログインして  
記事を投稿しようとしたところ、  
次のようにcurrent_user.idがnilだと  
言われてしまいました。

[![画像の説明をここに入力](https://i.stack.imgur.com/MAFJa.png)](https://i.stack.imgur.com/MAFJa.png)

ログインしている状態でしか  
投稿できない様にしているので、  
ログインしていることは確実なのですが、  
なぜこのようになってしまうのでしょうか？

勝手な想像ですが、  
gem deviseを利用している場合、

application_controller.rbの

before_action :set_current_user, only: [:create]

def set_current_user  
@current_user = User.find_by(id: session[:user_id])  
end

という部分が使えないとかいう  
ことがあったりするのでしょうか？

何度もすみませんが、  
どうぞよろしくお願いいたします。

＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝

**追記３**

application_controller.rbにて

before_action :set_current_user, only: [:create]

def set_current_user  
@current_user = current_user  
end  
としたところ、記事の投稿でエラーがでることは  
なくなりました！

しかし、各記事のページに行くと

[![画像の説明をここに入力](https://i.stack.imgur.com/FbSnz.png)](https://i.stack.imgur.com/FbSnz.png)

となってしまいます。

これはすなわちpostにuser情報が  
くっついていないということなんでしょうか？  
どうすれば良いのでしょうか...  
どうぞよろしくお願いいたします。


CC BY-SA 3.0
2017-12-09T10:35:46.150
40155
2017-12-10T07:23:16.287
2017-12-10T07:23:16.287
26577
26577
question
ruby-on-rails ruby devise
Ruby on Rails でのユーザー情報と投稿の紐付けに関して


Postモデルで、

[code]

    has_many :users
    
[/code]

ではなく

[code]

    belongs_to :user
    
[/code]

としてください。

自分のテーブルにある「他のテーブルのIDを記録したカラム」で他のテーブルを参照する時は`belongs_to`、他のテーブルにある「自分のテーブルのIDを記録したカラム」で他のテーブルを参照する時は`has_many`または`has_one`(1対多か1対1か)になります。

* * *

エラーになってるのは、`Post.new`の引数が間違っている(コードのような引数の渡し方が出来ない)からです。

単純には

[code]

    @post = Post.new(post_params)
    @post.user_id = @current_user.id
    
[/code]

で動きますが、質問のようなことがやりたいのであれば、

UserモデルにPostへのリレーションを追加し、

[code]

    class User < ...
      has_many :posts
    end
    
[/code]

そのリレーションを利用してPostを作った方がいいと思います

[code]

    @current_user.posts.build(post_params)
    
[/code]


CC BY-SA 3.0
2017-12-10T02:54:08.543
40161
2017-12-10T06:32:57.340
2017-12-10T06:32:57.340
5793
5793
40155
answer