dannymcc
dannymcc

Reputation: 3814

Increment integer on save in Rails 3?

I have the following code in my Rails 3 application:

 def like
    @suggestion = Suggestion.find(params[:id])
    Suggestion.update_all("votes = (votes + 1)")
    redirect_to suggestions_url
  end

  def dislike
    @suggestion = Suggestion.find(params[:id])
    Suggestion.update_all("votes = (votes - 1)")
    redirect_to suggestions_url
  end

It's working, but rather than updating the current suggestion it's updating them all. So I changed it to:

 def like
    @suggestion = Suggestion.find(params[:id])
    @suggestion.update_all("votes = (votes + 1)")
    redirect_to suggestions_url
  end

  def dislike
    @suggestion = Suggestion.find(params[:id])
    @suggestion.update_all("votes = (votes - 1)")
    redirect_to suggestions_url
  end

but then I get:

undefined method `update_all' for #<Suggestion:0x007f87c2b918a0>

So then I tried @suggestion.update_attribute(:votes, '1') but that resets the value to 1 instead of incrementing it.

What's the correct way to achieve this? I just want the integer (votes) of the current suggestion to increment/decrease by 1 on each save.

I've also tried the following with no luck:

def like
 @suggestion = Suggestion.find(params[:id])
 @suggestion.increment(:votes)
 redirect_to suggestions_url
end

Upvotes: 0

Views: 3170

Answers (2)

dcashman
dcashman

Reputation: 196

A couple things. It sounds like what you want is a controller action that increments an attribute by one. You were probably closest with the code

@suggestion.update_attribute(:votes, '1')

If you check the documentation for that method, it sets the value of the attribute votes to the second arguement, the string '1', on the object, @suggestion, and its corresponding row in the database. Instead of setting it to '1', you want to set it to the incremented value:

@suggestion.update_attribute(:votes, @suggestion.votes + 1)

Ethan suggested using the convenience method, increment!, which works just the same.

Now, if you wanted to actually auto-increment each time the object gets saved (as in something else about the object gets altered, you'd want to use the :before_save callback with increment without the bang.

Upvotes: 5

Ethan Hayon
Ethan Hayon

Reputation: 346

This seems more suitable in the model. I suggest creating a like method inside the model like so:

def like
    self.increment!(:votes)
end 

Now you can do something like this:

@suggestion = Suggestion.find(params[:id])
@suggestion.like

Note: increment!, with the exclamation point also performs the save action

Upvotes: 6

Related Questions