0

I have a PORO TutorProfileHandler that has a function json that returns a hash.

class TutorProfileHandler

    def initialize(opts)
        @profile = opts[:tutor_profile]
    end

    def json
        tutor = @profile.tutor
        return {
            id: tutor.id,
            first_name: tutor.first_name,
            last_name: tutor.last_name.first + '.',
            school: @profile.school,
            avatar: @profile.avatar.url,
            bio: @profile.bio,
            academic_level: @profile.academic_level,
            headline: @profile.headline,
            major: @profile.major,
            rate: @profile.rate,
            rating: @profile.rating,
            courses: JSON.parse(@profile.courses),
            video_url: @profile.video_url
        }
    end
end

In my index_tutor_profiles.json.jbuilder, I would like to generate

{
   tutor_profile: [{id: 1, ...}, {id: 2, ...}, ...],
   tutor_sum: 20
}

However when I do this

json.tutor_profiles (@tutor_profiles) do |profile|
    TutorProfileHandler.new({tutor_profile: profile}).json
end

json.tutor_sum @tutor_sum

It gives me an empty array for tutor_profiles.

However if I move everything from TutorProfileHandler.json to the jbuilder file, it works. How do I explicitly include the hash returned by TutorProfileHandler.json in the jbuilder array?

Note: This returns an array, but it creates a new key-value pair array:

json.tutor_profiles json.array(@tutor_profiles) do |profile|
    TutorProfileHandler.new({tutor_profile: profile}).json
end

Result:

{
   array: [{id: 1, ...}, {id: 2, ...}, ...],
   tutor_profile: [],
   tutor_sum: 20
}
Richard
  • 828
  • 1
  • 8
  • 28
  • json builder is DSL. One should not pass the hash to builder, one should explicitly state a DSL like `last_name @profile.last_name` or whatever. – Aleksei Matiushkin Mar 04 '16 at 05:37
  • @mudasobwa What would be the DRY way to do this if I also have a `show_tutor_profile.json.jbuilder` that has the same key-value pairs? – Richard Mar 04 '16 at 05:39
  • I never used builder myself, due to the reason I did not find elegant an DRY pattern. Probably the only way is to have a lambda, that calls `public_send key, value` on the prepared hash. BTW, what’s wrong with `hash.to_json`? – Aleksei Matiushkin Mar 04 '16 at 06:37

1 Answers1

1

There is a ugly approach:

json.tutor_profiles @tutor_profiles do |profile|
    tmp_json = TutorProfileHandler.new({tutor_profile: profile}).json
    json.(tmp_json, *(tmp_json.keys))
end

I think the best practise is directly nesting inside model. You can get more information from the its github page.

Haozhao
  • 11
  • 4