2

私のレールアプリには、ユーザーがピンに賛成票を投じることができる賛成票システムがあります。しかし、ピンに 1 回だけ賛成票を投じる機能を制限したいと思います。

app/controllers/pins_controller.rb

  def upvote
    @pin = Pin.find(params[:id])
    @pin.votes.create
    redirect_to(pins_path)
  end

アプリ/モデル/pin.rb

class Pin < ActiveRecord::Base

    belongs_to :user

    has_many :votes, dependent: :destroy

    has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
    has_attached_file :logo, :styles => { :medium => "300x300>", :thumb => "100x100>" }

    end

app/config/routes.rb

  resources :pins do
  member do
    post 'upvote'
  end
end

ユーザーが1回だけ賛成票を投じることができるシステムを実装しようとしたので、それを実装する方法がわかりません。act_as_votableジェムがこの機能を提供することは知っていますが、私はそれを使用していないので、自分のコードにそれを実装する方法があるかどうか知りたいと思っていました。

何か案は?

更新: この方法では、ピンごとに 1 票しか許可されません。@Egeソリューションを参照

これで動作するようにします:

def upvote
  @pin = Pin.find(params[:id])

  if @pin.votes.count == 0
     @pin.votes.create
     redirect_to(pins_path)
  else flash[:notice] =  "You have already upvote this!"
    redirect_to(pins_path)
end
end
4

2 に答える 2

13

あなたはbeautifulcoderの回答を正しいものとして選択しましたが、それは間違っている可能性があり、Railsを初めて使用する場合は明らかではない可能性があることに注意してください。

あなたは、ピンは 1 票しか持てないと言いますが、おそらく、ユーザーごとに 1 票を持つべきだということです。つまり、各ユーザーはピンに 1 回だけ賛成票を投じることができるはずです。これは、通常、投票メカニズムがどのように機能するかです。

ビューティフルコーダーの回答では、私がピンに賛成票を投じると、あなたはそれを支持できなくなります。これは、コントローラーがピンの投票数をカウントし、1 を返し (私が賛成票を投じたため)、賛成票を投じられないようにするためです。さらに、賛成票を投じたのに反対票を投じたことを示すメッセージが表示されます。

この問題を解決するには?幸いなことに、Rails はこれを非常に簡単にします。あなたの投票は、実際には変装した参加モデルです。ユーザーとピンの間に関係 (関連付け) を確立します。ユーザーはピンに賛成票を投じることができ、ユーザーはピンに賛成票を投じることができます。つまり、投票がユーザーとピンを「つなぐ」のです。必要なのは、ActiveRecord Associationsを利用してこの関係を定義することです。

ピン モデルには、次の関連付けが追加されます。

class Pin < ActiveRecord::Base

  has_many :votes, dependent: :destroy
  has_many :upvoted_users, through: :votes, source: :user

  ...

end

これにより、次のようなことを実行して@pin.upvoted_users、そのピンに賛成票を投じたユーザーのリストを取得できます。ピンの所有者に通知できるようにしたい場合は、かなりいいです!

User モデルに逆関連付けを追加することもできます。

class User < ActiveRecord::Base

  has_many :votes, dependent: :destroy
  has_many :upvoted_pins, through: :votes, source: :pin

  ...

end

次に、Vote モデルを次のように変更します。

class Vote < ActiveRecord::Base

  belongs_to :user
  belongs_to :pin
  validates_uniqueness_of :pin_id, scope: :user_id

end

最後に、コントローラーで次のようにします。

def upvote
  @pin = Pin.find(params[:id])

  if @pin.votes.create(user_id: current_user.id)
    flash[:notice] =  "Thank you for upvoting!"
    redirect_to(pins_path)
  else 
    flash[:notice] =  "You have already upvoted this!"
    redirect_to(pins_path)
  end
end

出来上がり!これで、ユーザーがアイテムに賛成票を投じることができるソリューションができましたが、アイテムごとに 1 回のみです。

于 2014-07-06T18:23:00.857 に答える