34156


記事の一覧からいいねをクリックするとこのようなエラーが出てしまいます。  
[![画像の説明をここに入力](https://i.stack.imgur.com/DSx2S.png)](https://i.stack.imgur.com/DSx2S.png)

@postには記事のIDが入っていてそれを現在のユーザーのfavoritesにしまうと思うのですが@favoritesというインスタンス変数がいまいちわかりません。このbuildを使うと@favoriteの中に現在のユーザーのお気に入りのポストという感じに作られるイメージなのですが合っているでしょうか？  
このコードで動くはずなのですがrailsを始めたばかりなのでイメージが薄くエラーが取れないです。助けて下さいお願いします。

追記：

routes.rb

[code]

    Rails.application.routes.draw do
      get 'users/index'
    
      get 'users/show'
    
      devise_for :users
      resources :users, only: [:index, :show] do
        get :favorites, on: :member
      end
      resources :posts do
        resources :favorites, only: [:create, :destroy]
      end
      root 'posts#index'
      # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
    end
    
[/code]

favorite.rb

[code]

    class Favorite < ApplicationRecord
        class Favorite < ActiveRecord::Base
            belongs_to :user
            belongs_to :post
        end
        #追記2：以下のuserとpostのpresenceをコメントアウトしたらうまく動いたのですが
        #userとpostが空でエラーが出ていたみたいなのですが空でいいのでしょうか?
        validates :user, presence: true
        validates :user_id, uniqueness: { scope: :post_id }
        validates :post, presence: true
    end
    
[/code]

post.rb

[code]

    class Post < ApplicationRecord
        belongs_to :user
        mount_uploader :image, ImageUploader
        acts_as_ordered_taggable_on :interests
        has_many :favorites, dependent: :destroy
        def favorited_by? user
            favorites.where(user_id: user.id).exists?
        end
     end
    
[/code]

user.rb

[code]

    class User < ApplicationRecord
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable
      has_many :posts
      has_many :favorites, dependent: :destroy
    end
    
[/code]

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

[code]

    class FavoritesController < ApplicationController
        before_action :authenticate_user!
    
        def create
            @post = Post.find(params[:post_id])
            #追記1：以下のpost:とpost_id:に変更したら上の画像の別のエラーが出ました。
            @favorite = current_user.favorites.build(post_id: @post)
    
            if @favorite.save
              redirect_to posts_url, notice: "お気に入りに登録しました"
            else
              redirect_to posts_url, alert: "この投稿はお気に入りに登録できません"
            end
         end
    
        def destroy
            @favorite = current_user.favorites.find_by!(post_id: params[:post_id])
            @favorite.destroy
            redirect_to posts_url, notice: "お気に入りを解除しました"
        end
    
    end
    
[/code]

favoriteテーブル

[code]

    class CreateFavorites < ActiveRecord::Migration[5.0]
      def change
        create_table :favorites do |t|
          t.integer :user_id
          t.integer :post_id
    
          t.timestamps
        end
      end
    end
    
[/code]


CC BY-SA 3.0
2017-04-17T12:13:20.587
34075
2017-04-22T05:15:07.907
2017-04-17T19:18:09.557
22565
22565
question
ruby-on-rails ruby
railsでいいね機能を付けたのですがうまくいいねが追加されません。


コードからRuby on Rails 5、Deviseを使っていると推定して回答します。  
このような前提条件は基本的に明記してください。

* * *

>
> @postには記事のIDが入っていてそれを現在のユーザーのfavoritesにしまうと思うのですが@favoritesというインスタンス変数がいまいちわかりません。このbuildを使うと@favoriteの中に現在のユーザーのお気に入りのポストという感じに作られるイメージなのですが合っているでしょうか？

`@post`はPostのidではなくPostオブジェクトが入るコードになっています。  
`@favorite`の理解は概ね合っています。`current_user.favorites.build(..)`は新たにFavoriteオブジェクトを生成したのち、favorite.userにcurrent_userを結びつけます。

* * *

エラーの「unknown attribute: 'post' for
Favorite.」はFavoriteにpostという属性が見つからないことを示しています。  
また、`@favorite.save`で「undefined method `user` for
#<Favorite:0xa520ecc>」は`user`メソッドがFavoriteオブジェクトに見当たらないことを示しています。  
これらは、FavoriteモデルにPostやUserのリレーションが無いということです。  
そこで最初に疑うべき箇所はFavoriteモデルのコード app/models/favorite.rb です。

[code]

    class Favorite < ApplicationRecord
        class Favorite < ActiveRecord::Base
            belongs_to :user
            belongs_to :post
        end
        #...
    end
    
[/code]

これは明らかにおかしいです。

  1. FavoriteモデルにUserとPostのリレーションを含む別のFavoriteモデルが内包してしまっています。通常はこのような構造にはなりません。（内側のモデルクラスは`Favorite::Favorite`になるため別物です）
  2. `ActiveRecord::Base`はRuby on Rails 4以下で使われていた`ApplicationRecord`相当（正確には継承元）のクラスです。5以上では使わないでください。

以上を踏まえると次のように修正されます。

[code]

    class Favorite < ApplicationRecord
        belongs_to :user
        belongs_to :post
    
        validates :user, presence: true
        validates :user_id, uniqueness: { scope: :post_id }
        validates :post, presence: true
    end
    
[/code]


CC BY-SA 3.0
2017-04-20T07:02:12.603
34156
2017-04-22T05:15:07.907
2017-04-22T05:15:07.907
19925
19925
34075
answer