1

I am working in Rails API with version 4.2 and i got stuck in enum mapping for related entries. My Models are following

class Student < ActiveRecord::Base
  has_many :enrollments
  validates :LastName, presence: true

end

class Enrollment < ActiveRecord::Base
  belongs_to :student


  enum Grade: [:A, :B, :C, :D, :F]
end

In my action when i just retrieve enrollment list i can get the Grade field as enum values. But when use join query with select method to return values i got the databases integer values only. My retrieving logic is like below

@students = Student.joins(:enrollments).select('students.*, enrollments.*').paginate(:page => params[:page])

My json like below:

{
students: [2]
0:  {
id: 1
LastName: "Alexander"
FirstMidName: "Carson"
Grade: 0
}-
1:  {
id: 2
LastName: "Alexander"
FirstMidName: "Carson"
Grade: 2
}-
-
}

I need to return first Grade is 'A' and the second one is 'C'. Please help to achieve this..

The following is my rabl file

collection :@students
attributes :id, :LastName, :Grade

node(:total) {|m| @students.total_entries }
node(:total_pages) {|m| (@students.total_entries.to_f / @students.per_page).ceil }

2 Answers 2

0

Actually, this is expected behaviour, as enum values are serialised as int to database - check docs.

But you can implement your own method within Enrollment, to render proper grade for you:

class Enrollment < ActiveRecord::Base
  # rest of the code

  def formatted_grade
    self.Grade.to_s
  end
end

so you can use it in your view:

<%= enrollment.formatted_grade %>

or, when converting to json:

enrollment.to_json(methods: :formatted_grade)

Please check my other answer regarding enum.

Hope that helps!

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks but i din't get based on my scenario. How i call formatted_grade in join query. I am using rabl to return the api as json
@Akhil - please, provide your current template, so I'm able to suggest anything.
I updated my rabl file. One more point is when use enrollments as child with Grade attribute i got correct calues like 'A' and 'C'
Ahh... ok @Akhil, so you've found the solution! I've been scratching my head thinking what could possibly go wrong... Well, there is no other way I'm affraid
I got as child element. But i am thinking to get in the same parent element as my expectation is inner join
|
0

I found 2 options to get this work. But i don't know the best approach. I will post the options here so you all can suggest and advice on this..

Option 1: Put enums in return model Here i used Students.joins(:enrollments) so that returned data will take as student model array (my assumption). Here rails verify the enum in Student model and not found so it returns the original integer. But if we write enum definition in the Student model it will return like we thought. Here is the changes

Student Model class:

class Student < ActiveRecord::Base
  has_many :enrollments
  validates :LastName, presence: true

  enum Grade: [:A, :B, :C, :D, :F]
end

Data Fetch code in the Controller

@students = Student.joins(:enrollments).select('students.*, enrollments.Grade').paginate(:page => params[:page])

Response Template in Rabl

collection :@students
attributes :id, :LastName, :FirstMidName, :Grade

node(:total) {|m| @students.total_entries }
node(:total_pages) {|m| (@students.total_entries.to_f / @students.per_page).ceil }

But i don't know this is a best practice to include enums in each model where we try to join.


Option 2: Always use Model which has enum defintion in the left (first) side of the join

Here i try to use the technique from the assumption i wrote in the option 1. So we have already enum definition in Enrollment model so i reversed the data fetch query. So only changes in the query.

Student Model class: No changes

Data Fetch code in the Controller

@students = Enrollment.joins(:student).select('students.*, enrollments.Grade').paginate(:page => params[:page])

Response Template in Rabl Same as option 1.

Here no duplication. But better to get clear idea about the query order.


Now i used option 2. Better suggestions or advice on my solutions are welcome

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.