Damir Nurgaliev
Damir Nurgaliev

Reputation: 351

Destroying object without its ID

I'm creating LIKE model to my rails application. Routing is:

resources :bonuses, only: %i(index create) do
  resources :likes, only: %i(create destroy)
end

I did a create of like and now trying to make a dislike button. I want to delete like with this button:

= link_to "Dislike", bonus_like_path, method: :delete

But i get error here: missing required keys: [:bonus_id, :id] If I pass the bonus_like_path(bonus) I will miss the ID parameter of like(but I dont need him, I know user.id)

To delete like everything that I need to know is bonus_id and current_user.id

schema.rb (likes)

create_table "likes", force: :cascade do |t|
  t.integer "user_id",  null: false
  t.integer "bonus_id", null: false
  t.index ["user_id", "bonus_id"], name: "index_likes_on_user_id_and_bonus_id", unique: true, using: :btree
end

The associations are simple:

Bonus:

has_many :likes, dependent: :destroy
has_many :liked_users, through: :likes, source: :user

User:

has_many :likes, dependent: :destroy
has_many :liked_bonus, through: :likes, source: :bonus

Like:

belongs_to :bonus, counter_cache: true, touch: true
belongs_to :user

So I understand that I can make DELETE bonus_like_path(bonus) request because user already defined in current_user. But don't know how to write it correctly.

Upvotes: 0

Views: 86

Answers (3)

Mark Swardstrom
Mark Swardstrom

Reputation: 18080

You could put an unlike method on bonus controller in this case. It's not RESTful, but since you're not passing the like id in the first place the bonus id seems to be the one id you need and the right place to take action.

def unlike
  bonus = Bonus.find(params[:id])
  bonus.likes.where(:user_id => current_user).destroy_all
  # render or redirect
end

and in routes

resources :bonuses, only: %i(index create) do
  put :unlike, on: :member
  resources :likes, only: %i(create)
end

If you go this way, move the like method over too and remove the likes resources in routes.

Upvotes: 1

mlabarca
mlabarca

Reputation: 806

If I understand correctly you're trying to piggyback on the existing resourceful path helpers to get a link to delete your like BUT without sending the like id which is generated by the Resourceful route. I don't know why you aren't using the REST-like(no pun intended) like id, but Instead of finding a way of ignoring the like id parameter, how about setting up a proper route that requires only the bonus id?

resources :bonuses, only: [:index :create] do
  resources :likes, on: [:create]
  delete 'delete_like', on: :member
end

With this you should have a /bonuses/1/delete_like route, and a delete_like_bonus_pathhelper that will receive the bonus id as :bonus_id parameter (Check with rake routes). More info at the routing guide here. Tested it on rails 3.2.

Upvotes: 0

NM Pennypacker
NM Pennypacker

Reputation: 6942

Just because you pass id params in doesn't mean you have to use those specific params. In your view you could do:

link_to "Dislike", bonus_like_path(bonus, like.id), method: :delete

and in your controller:

current_user.likes.where(bonus_id: params[:bonus_id]).destroy_all

or whatever you need to do to destroy that object. The point is that like you said, you have current_user in your controller.

Just because you pass in a bonus id and like id, doesn't mean you have to act on those params specifically.

Upvotes: 0

Related Questions