1

基本的に、最近の 10 個のマイクロポストを一覧表示するページがあります。各投稿にはいいねボタンがあります。このいいねボタンをクリックすると、データベースのいいねテーブルが更新されます。

好きなテーブル:

+----+------------+--------------+-------------------------+-------------------------+---------+
| id | likable_id | likable_type | created_at              | updated_at              | user_id |
+----+------------+--------------+-------------------------+-------------------------+---------+
| 2  | 5770       | Micropost    | 2012-06-09 11:30:55 UTC | 2012-06-09 11:30:55 UTC | 2       |
| 3  | 5770       | Micropost    | 2012-06-09 11:42:45 UTC | 2012-06-09 11:42:45 UTC | 2       |
+----+------------+--------------+-------------------------+-------------------------+---------+

ユーザーは、マイクロポストを 1 回だけ高く評価できます。jquery/js を使ってこれを可能にするには、マイクロポストがいいね! されたときに破棄パスを指す [似ていない] ボタンを表示します。

しかし、このサーバー側も行う方法はありますか? 必要に応じて、マイクロ投稿が複数回いいねされることを許可しないようにするにはどうすればよいですか? したがって、Rails コンソールに移動して、既に気に入ったマイクロポストを手動でいいね! しようとしても、マイクロポストが既に気に入ったと見なされるため、機能しませんか?

モデルのように:

class Like < ActiveRecord::Base
  belongs_to :likable, :polymorphic => true
  attr_accessible :likable_id, :likable_type, :user_id
end

マイクロポスト モデル:

class Micropost < ActiveRecord::Base
    belongs_to :user
    has_many :likes, :as => :likable
end

好きなコントローラー:

class LikesController < ApplicationController
  def create
    micropost = Micropost.find(params[:micropost])
     like = micropost.likes.build(:user_id => current_user.id)
     like.save
  end
end

いいねフォーム:

<%= form_tag likes_path, :remote => true, :class => "like_micropost" do %>  
   <%= hidden_field_tag :micropost, micropost.id %>
       <%= submit_tag '', :class => "likeMicropostSubmit"  %> 
<% end %>

私は以前に運がなかったこれを試しました:

class LikesController < ApplicationController
  def create
    micropost = Micropost.find(params[:micropost])
    if micropost.likes.where(:user_id => current_user.id).nil?
     like = micropost.likes.build(:user_id => current_user.id)
     like.save
    end
  end
end

敬具

4

3 に答える 3

5
# in Like class
validates_uniqueness_of :user_id, :scope => [:likable_id, :likable_type]

このようにして、何かを複数回気に入ろうとすると、検証エラーが発生します。

ドキュメントを参照してください。

于 2012-06-09T12:38:28.457 に答える
0

私は2つのことをします:

  1. 作成ロジックをモデルに移動 (ファット モデル、スキニー コントローラー)
  2. like作成時に検証を追加します(jdoeがすでに言ったように)

そう:

class LikesController < ApplicationController
  def create
    micropost = Micropost.find(params[:micropost])
    current_user.likes! micropost
  end
end

class Like < ActiveRecord::Base
  validates_uniqueness_of :user_id, :scope => [:likable_id, :likable_type]
end

class User < ActiveRecord::Base
  # exclamation mark to avoid confusion between things that are liked by the user
  def likes!(likable_object)
    unless likable_object.likes.where(:user_id => self.id).exists?
      like = likable_object.likes.build(:user_id => self.id)
      like.save
    end
  end
end

編集:説明:

1) Like 作成フェーズの管理はモデルの責務 → 作成を管理するコードをモデルに移動

2) アクションを説明するための適切なメソッド名を見つける ->User.likes! somethingいいですね

3) 作成方法の実装 ->

def likes!(likable_object)
  like = likable_object.likes.build(:user_id => self.id)
  like.save
end

4) モデル有効/モデル無効ロジックを管理するためにバリデーションを追加 ->class Like; validates_uniqueness_of ...

5)likes!有効/無効ロジックを意識したメソッドにする →

def likes!(likable_object)
  unless likable_object.likes.where(:user_id => self.id).exists?
    like = likable_object.likes.build(:user_id => self.id)
    like.save
  end
end
于 2012-06-09T12:44:28.147 に答える
-1

これは私にとってはうまくいきました:

class LikesController < ApplicationController
  def create
    micropost = Micropost.find(params[:micropost])
    unless micropost.likes.where(:user_id => current_user.id).exists?
     like = micropost.likes.build(:user_id => current_user.id)
     like.save
    end
  end
end

テンプレートを作成していないことが原因で、適切に機能しなくなっていましたが、テンプレートは空で未使用であるため、なぜ必須なのか疑問に思っています。

于 2012-06-09T12:36:49.863 に答える