Reputation: 20415
I have a Exam model, which has a database attribute score
. Now, I want to have another attribute named rating
, which converts this score to rating (A, B, C, D, F). I don't want to create another column for rating
, so I used virtual attribute as follow:
class Exam < ActiveRecord::Base
attr_accessor :rating
after_initialize :set_rating
after_find :set_rating
private
def set_rating
self.rating = case score
when 0..49 then "F"
when 50..79 then "B"
else "A"
end
end
This works, in the sense that I can call
e = Exam.find_by_student("John")
e.rating
However, the object e
does not have attribute rating attached to it. So if I pass object e
to Rails view, I can't get e.rating
where rating is an attribute.
How can I achieve what I would like, i.e., a database-less attribute that is available after_find?
Thank you.
Upvotes: 2
Views: 2893
Reputation: 239291
Scrap all that and just define a method called rating
.
class Exam < ActiveRecord::Base
# ...
def rating
case score
when 0..49 then "F"
when 50..79 then "B"
else "A"
end
end
end
If you need to include this "attribute" in a JSON response, you can pass the :methods
parameter to as_json
to explictly include it:
render json: @exam.as_json(members: :rating)
Upvotes: 7