Gurmukh Singh Gurmukh Singh - 5 months ago 16
Ruby Question

Update column in database from model

So I have a

User
model and a
Post
model

Post
belongs to a User

Post
has a field in the database called
score


In the
Post
model I have a method called
score
which gives the post a score based on the fields (needs to be done this way):

def score
score = 0

if self.title.present?
score += 5
end
if self.author.present?
score += 5
end
if self.body.present?
score += 5
end

score

end


The Question:

There are loads of
Users
and loads of
Posts
. So What I'm trying to do is after the score is worked out, I want to save it to the Post
score
field in the database for each
Post
. The score should be updated if the user updates the
Post
.

I have looked at using
after_update :score!
but don't understand how to apply the logic

Answer

It looks a little like you are trying to re-invent the wheel ActiveRecord provides you.

If you have a database field score, then ActiveRecord will automatically provide an attribute_reader and attribute_writer for score and you should not override these unless you have a really really good reason for it, e.g. you need to add some other resources or some serious business logic into it.

There is a way easier way to solve it, by using the before_save hook, which will kick in before any #create or #update:

class Post
  attribute_accessible :score # if you have Rails 4.x you can omit this line

  before_save :update_score

  private
  def update_score
    new_score = 0
    self.score = [:title, :author, :body].each do |field|
      new_score += 5 if send(field).present?
    end

    self.score = new_score
  end

This way, ActiveRecord will handle the saving for you and your score will always up to date. Additionally Post#score will always return the real value currently saved in the database