我的rails应用程序中有一个upvote系统,允许用户提升Pin。 但是我想限制一次只能推销一次的能力。
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
应用/配置/ routes.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
答案 0 :(得分:12)
您选择了beautifulcoder的答案作为正确答案,但您应该知道它可能不正确,如果您是Rails的新手,可能并不明显。
你说一个Pin应该只有一票,但大概你的意思是它应该有一个每个用户的投票,因为每个用户应该能够只投票一次Pin。这就是投票机制通常的工作方式。
使用beautifulcoder的答案,如果我赞成一个Pin,你将无法支持它,因为你的控制器将计算Pin上的投票数,返回1(因为我对它进行了投票)并阻止你从upvoting。此外,它会闪烁一条消息,说你已经投了它,而你还没有!
如何解决这个问题?幸运的是,Rails让这非常容易。您的投票实际上是伪装的加入模型。它建立了用户和引脚之间的关系(即关联)。用户可以对引脚进行upvote,并且可以由用户对引脚进行upvoted。换句话说,投票&#34;连接&#34;用户和别针!您需要做的是通过利用ActiveRecord Associations来定义这种关系。
您的Pin模型会添加此关联:
class Pin < ActiveRecord::Base
has_many :votes, dependent: :destroy
has_many :upvoted_users, through: :votes, source: :user
...
end
这使您可以执行@pin.upvoted_users
之类的操作,并获取已投票赞成该用户的用户列表。非常好,如果你想通知别人的主人!
您还想为用户模型添加反向关联:
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
瞧!您现在有一个解决方案,用户可以在其中投票,但每个项目只能投票一次。
答案 1 :(得分: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