user823981
user823981

Reputation: 112

Modifying an ActiveRecord model with a function

I'm just learning RoR and I've run into a problem in my unit tests where a simple function I wrote will not modify it's object appropriately. I must be missing something very basic because I have seen this question on any forum.

I run my test with rake via "rake test test/functional/song_test.rb". The data is loaded from a yaml file and that seems to be correct. But when I call my "vote!" function (see below) to modify an attribute, @rating, the change is not visible in the test and my assertion fails.

test "vote!" do
  song1 = songs(:song1)                         # 'songs' was loaded from a yaml file
  assert song1.respond_to?('vote!'), "Can't vote!()!"
  assert_equal 5, song1.rating, "Rating is wrong"  # assertion passes

  song1.vote!(1)

  assert_equal 1, song1.rating, "Rating should be 1" # assertion fails
end 

Here is the failure message:

SongTest#test_vote! = 0.00 s                         
  1) Failure:
test_vote!(SongTest) [/test/functional/song_test.rb:35]:
Rating should be 1.
<1> expected but was
<5>.

I verified with puts() that the change does occur within the vote! function. But after the function returns the song1.rating value has not changed. Here's the class with the vote! function.

class Song < ActiveRecord::Base
  validates :rating, :presence => true

  def vote!(num_stars)
    @rating = num_stars
  end
end

I'm thinking that there are two copies of the object somehow and the vote! function is invoked on a temporary object. But I don't see how or why that would be.

Upvotes: 1

Views: 43

Answers (1)

tadman
tadman

Reputation: 211680

The rating attribute and the @rating instance variable are not related. Your vote! method should look like:

def vote!(num_stars)
  self.rating = num_stars
end

What you're doing in your existing code is creating an instance variable that isn't used.

As a note, by convention a method called vote! would have the effect of saving the changes made to the model. For example:

self.update_attribute(:rating, num_stars)

Upvotes: 1

Related Questions