从不同模型的控制器更新一个模型的属性

时间:2013-01-10 06:12:38

标签: mysql ruby-on-rails ruby rails-activerecord

我有一个简单的帖子和用户应用,用户提交和提交帖子。我有两个模型,帖子和用户,现在我正在使用帖子模型添加“upvoting”功能。

每个帖子都有:id:upvote:users_voted_by属性。 每个用户都有:username:posts_voted_ongood_karma属性

当用户点击帖子上的upvote按钮时,我需要确保当前用户不在该帖子的:users_voted_by列中,如果没有,请在:upvote属性中添加1那篇文章。这部分已经完成。

但我还需要将帖子:id添加到当前用户的:posts_voted_on字段中,并将1添加到提交者的:good_karma字段。

发布模型:

class Post < ActiveRecord::Base
  attr_accessible :comment_count, :downvote, :id, :text, :title, :upvote, :url, :user, :users_voted_by
end

用户模型:

class User < ActiveRecord::Base
  attr_accessible :email, :password, :password_confirmation, :username, :posts_voted_on, :good_karma, :bad_karma

  attr_accessor :password
  before_save :encrypt_password

  validates_confirmation_of :password
  validates_presence_of :password, :on => :create
  validates_presence_of :email
  validates_uniqueness_of :email
  validates_presence_of :username
  validates_uniqueness_of :username

  def self.authenticate(email, password)
    user = find_by_email(email)
    if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end
end

我的upvote方法在posts_controller中:

  def upvote
    @post = Post.find(params[:post_id])

    respond_to do |format|
      if @post.users_voted_by.index(current_user.username) == nil && @post.update_attributes(:upvote => @post.upvote + 1, :users_voted_by => @post.users_voted_by + ',' + current_user.username)
        format.html { redirect_to @post }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

第五行是神奇的地方。确保我投票的帖子没有:users_voted_by字段中的当前用户。然后,它会更新:upvote:users_voted_by字段。

如何添加此方法(操作?),以便它还更新投票用户和帖子提交者的属性,以存储业力增长。

1 个答案:

答案 0 :(得分:1)

猜猜service object可以在这里提供帮助,例如(未经测试)

class Voter
  def initialize(post, user)
    @post = post
    @user = user
  end

  def upvote
    return false unless @post.users_voted_by.index(@user.username)
    @post.upvote += 1
    @post.users_voted_by = @post.users_voted_by + ',' + @user.username
    @user.good_carma += 1
    @post.save && @user.save
  end

  def downvote
    ...
  end
end

然后控制器看起来像

   def upvote
    @post = Post.find(params[:post_id])
    respond_to do |format|
      if Voter.new(@post, current_user).upvote
        format.html { redirect_to @post }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end