2

我的 rails 应用程序中有一个支持系统,允许用户支持 Pin。但我想限制仅对 Pin 图进行一次投票的能力。

应用程序/控制器/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

应用程序/配置/路由.rb

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

我不确定如何实现这一点,因为我试图实现一个只允许用户投票一次的系统,这不是我想要的,我希望他们只能投票一次“PIN”。我知道acts_as_votable gem 提供了这个功能,但由于我没有使用它,我想知道是否有办法在我自己的代码上实现它。

有任何想法吗?

更新:此方法仅允许每个引脚投一票。请参阅@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 新手,这可能并不明显。

你说一个 Pin 应该只有一票,但大概你的意思是每个用户应该有一个投票例如,每个用户应该只能对一个 Pin 投票一次。这就是投票机制通常的工作方式。

使用beautifulcoder 的回答,如果我对Pin 进行投票,您将无法对其进行投票,因为您的控制器将计算Pin 上的投票数,返回1(因为我对其进行了投票)并阻止您投票。此外,它会闪烁一条消息,说您已投票,而您还没有!

如何解决这个问题呢?幸运的是,Rails 让这一切变得超级简单。你的投票实际上是一个变相的加入模型。它在用户和引脚之间建立关系(即关联)。用户可以对 pin 进行投票,并且 pin 可以由用户投票。换句话说,投票“连接”用户和引脚!您需要做的是通过利用ActiveRecord 关联来定义这种关系。

您的 Pin 模型将添加此关联:

class Pin < ActiveRecord::Base

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

  ...

end

这使您可以执行类似的操作@pin.upvoted_users并获取已投票支持该 pin 的用户列表。如果您希望能够通知别针所有者,那就太好了!

您还想为您的用户模型添加反向关联:

class User < ActiveRecord::Base

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

  ...

end

然后像这样更改投票模型:

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

瞧!您现在有了一个解决方案,用户可以对项目进行投票,但每个项目只能投票一次。

于 2014-07-06T18:23:00.857 回答
0

对控制器操作条件的小更新

def upvote
  @pin = Pin.find(params[:id])
  @pin.votes.create(user_id: current_user.id)

  if @pin.save
    flash[:notice] =  "Thank you for upvoting!"
    redirect_to(pins_path)
  else 
    flash[:notice] =  "You have already upvoted this!"
    redirect_to(pins_path)
  end
end
于 2016-04-08T14:10:26.517 回答