Rails使用变量作为列名

时间:2013-10-05 09:39:32

标签: ruby-on-rails ruby

我有一个Like模型,它连接用户喜欢的项目。添加到标准liked状态,项目可以是spinned& pinned,都是布尔字段。

赞模特

 _________________________________________________
| item_id | user_id |  liked  |  spinned | pinned |
|---------|---------|---------|----------|--------|
|    1    |    1    |  true   |   true   | false  |
|    2    |    1    |  false  |   true   | true   |
|    3    |    2    |  true   |   false  | false  |
 -------------------------------------------------

项目的不同状态都会通过相同的AJAX来电更新,并在action中调用相同的likes controller。当尚未存在时,它会创建一个所需状态为真的类似的东西。

likes_controller

def index
  # get the item id
  action = params[:act]
  mid = params[:mid]

  # gets the desired like item to see if it already exists
  like = Like.where(:item_id => mid, :user_id => current_user.id).first

  case action

    # like the item
    when "like"
      # if the item doesn't exist
      if like.blank?
        # create the like
        Like.create(:user_id => current_user.id, :item_id => mid, :liked => true)
      else
        # else toggle the liked status
        like.toggle! :liked
      end

    # pin the item
    when "pin"
      if like.blank?
        # create the like
        Like.create(:user_id => current_user.id, :item_id => mid, :pinned => true)
      else
        # else toggle the pinned status
        like.toggle! :pinned
      end

    # spin the item
    when "spin"
      if like.blank?
        # create the like
        Like.create(:user_id => current_user.id, :item_id => mid, :spinned => true)
      else
        # else toggle the spinned status
        like.toggle! :spinned
      end
  end
end

如你所见,case中的代码非常重复,我想知道我是否可以更有效地使用我的action('like','pin','spin')变量

我可以轻松地将action转换为相应的字段名称(“like”=>“likes”,“pin”=>“pinned”,“spin”=>“spinned”)从我的view发送另一个参数值。

我可以使用它只有一个代码块而不是3个类似代码吗?

action = "liked" # this would change depending on the desired action

# if the item doesn't exist
if like.blank?
  # original
  Like.create(:user_id => current_user.id, :item_id => mid, :liked => true)
  # doesn't work, how would I do this appropriately?
  Like.create("user_id = ?, item_id = ?, ? = true", current_user.id, mid, action)
else
  # this works!, what about SQL injection? How can I prevent this?
  like.toggle!("#{action}")
end

2 个答案:

答案 0 :(得分:1)

如果事件的原子性不是主要问题,您可以使用select或new然后保存。

like = Like.where(:item_id => mid, :user_id => current_user.id).first
like ||= Like.new(:item_id => mid, :user_id => current_user.id, :pinned => false, :spinned => false, :liked => false)
when "like"
like.liked = !like.liked
when "spin"
like.spinned = !like.spinned
when "pin"
like.pinned = !like.pinned
end
like.save!

答案 1 :(得分:0)

事实证明,在使用action:column时,我可以简单地使用变量create()代替列选择器toggle()

结果是:

if like.blank?
  # create the like
  Like.create(:user_id => current_user, :item_id => mid, action => true)
else
  # else toggle the desired status
  like.toggle!(action)
end