如何限制用户只在铁轨上的ruby中“喜欢”一个帖子?

时间:2012-06-09 12:26:18

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.2

基本上我有一个页面列出了10个最近的微博。每个帖子都有一个类似按钮。单击此类按钮时,我的数据库中的likes表会更新。

喜欢表:

+----+------------+--------------+-------------------------+-------------------------+---------+
| 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       |
+----+------------+--------------+-------------------------+-------------------------+---------+

用户必须只能使用一次微博。我可以通过一些jquery / js来实现这一点,通过显示一个不同的按钮,当需要微博时,它指向一个破坏路径。

但是有没有办法做这个服务器端呢?像不允许通过任何必要的手段多次使用微博?因此,如果我要进入rails控制台并尝试手动喜欢我已经喜欢的微博,它将无法工作,因为它会看到我已经喜欢微博?

与模特一样:

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

Micropost模型:

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

亲切的问候

3 个答案:

答案 0 :(得分:5)

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

这样,您在尝试不止一次的时候会遇到验证错误。

See docs for it.

答案 1 :(得分:0)

我会做两件事:

  1. 将创建逻辑移动到模型(胖模型,瘦控制器)
  2. 在类似的创建中添加验证(如jdoe已经说过)
  3. 所以:

    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创建阶段是模型职责 - &gt;将管理创建的代码移动到模型

    2)找一个好的方法名称来描述动作 - &gt; User.likes! something听起来不错

    3)实施创作方法 - &gt;

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

    4)添加验证以管理模型有效/模型无效逻辑 - &gt; class Like; validates_uniqueness_of ...

    5)使likes!方法意识到有效/无效逻辑 - &gt;

    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
    

答案 2 :(得分:-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

没有创建模板是阻止它正常工作的原因,但模板是空的并且未使用,所以想知道为什么它是强制性的。