I have a Like model, it connects users liking items. Additonally to the standard liked status, items can be spinned & pinned, all being boolean fields.
Like Model
_________________________________________________
| item_id | user_id | liked | spinned | pinned |
|---------|---------|---------|----------|--------|
| 1 | 1 | true | true | false |
| 2 | 1 | false | true | true |
| 3 | 2 | true | false | false |
-------------------------------------------------
The different states of an item all get updated via the same AJAX call, calling the same action in my likes controller. When the like does not yet exist, it creates a like with the desired state being true.
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
As you see, the code in the case gets very repetitive, I wanted to know if I could use my action ('like', 'pin', 'spin') variable more effectively.
I could easily convert the action to the appropriate field name ("like" => "liked", "pin" => "pinned", "spin" => "spinned") by sending another parameter value from my view.
Could I then use this to only have one block of code instead of 3 similar ones?
iE
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