Murtza
Murtza

Reputation: 1416

How to add/ update points for specific attributes in rails 4

I have two models profile and review. profile has points column but i dont know how should i add/update the points.

Your help is much appreciated.

Profile.rb

class Profile < ActiveRecord::Base
    # :first_name
    # :last_name
    # :gender
    # :phone
    # :slogan
    # :description
    # :points

    has_many :reviews
end

Review.rb

class Review < ActiveRecord::Base
  belongs_to :profile

  # :body
end

Upvotes: 1

Views: 177

Answers (2)

Agis
Agis

Reputation: 33646

You could do it using callbacks.

changes tells you what changes were made to a record's fields. So in the code above you check if the relevant fields were empty before and now are filled and if so, you add a value to the score field right before the record is saved.

class Profile < ActiveRecord::Base
  before_save :update_score

  private

  def update_score
    self.score += 2  if has_added?('first_name')
    self.score += 2  if has_added?('last_name')
    self.score += 5  if has_added?('phone')
    self.score += 10 if has_added?('slogan')
  end

  def has_added?(field_name)
    changes[field_name].present? && changes[field_name].first.nil?
  end
end

For the reviews part, similarly:

class Review < ActiveRecord::Base
  belongs_to :profile

  after_save :update_profile_score, 
              if: Proc.new { |review| review.profile.reviews.count == 20 }

  private

  def update_profile_score
    self.profile.score += 20
    self.profile.save
  end
end

Upvotes: 2

methyl
methyl

Reputation: 3312

I suggest creating new class to take responsibility of calculating points. Then, you can use this class to calculate points before saving the model and update the points property.

This code is untested but should give you the idea.

class PointCalculator
  def initialize(profile)
    @profile = profile
  end

  def calculate
    first_name_points + last_name_points + phone_points + slogan_points + review_points
  end

  private

  def first_name_points
    @profile.first_name.present? ? 2 : 0
  end

  def last_name_points
    @profile.last_name.present? ? 2 : 0
  end

  # (...)

  def review_points
    @profile.reviews.length
  end
end

class Profile < ActiveRecord::Base
    has_many :reviews

    before_save :calculate_points

    private

    def calculate_points
      self.points = PointCalculator.new(self).calculate
    end
end

Upvotes: 0

Related Questions