1

I have a Submission model

belongs_to :report
has_many :answers

Report Model

has_many :questions

Question Model

has_many :answers   # answer has submission_id

Now in rabl template I need output like this

        object @submission
        attributes :status, :submission_time

        child :report do
            attribute :id, :name
            child :questions do
                attribute :id, :content
                node(:answers_count) do |question|
                    question.answers.where("submission_id = ?", @submission.id).count
                end
                node(:answers) do |question|
                    question.answers.where("submission_id = ?", @submission.id).collect{ |answer| {:name => answer.name, :id => answer.id}}
                end
            end
        end

This is working perfectly fine but the problem is in answers_count and answers node I am using @submission and because of that index action is not working.

Its fine in show action but index action is creating issues as @submission is not available in index action.

PS: Once I fix the issue I will move the big query from view to model. I know that, Just for simplicity I have pasted that inline.

Mohit Jain
  • 43,139
  • 57
  • 169
  • 274

2 Answers2

2

This is not the best solution but it will work

object @submission
attributes :status, :submission_time

child :report do
    attribute :id, :name

    submission_id = locals['submission'] ? locals['submission'].id : locals[:object].id

    child :questions do
        attribute :id, :content
        node(:answers_count) do |question|
            question.answers.where("submission_id = ?", submission_id ).count
        end
        node(:answers) do |question|
            question.answers.where("submission_id = ?", submission_id ).collect{ |answer| {:name => answer.name, :id => answer.id}}
        end

    end
end
Manoj Sehrawat
  • 1,283
  • 1
  • 10
  • 25
0

This should work for you, although it's a bit of a hack admittedly. I've kept the non-working solutions below for posterity:

object @submission
attributes :status, :submission_time

child :report do
    submission_id = root_object.id
    attribute :id, :name
    child :questions do
        attribute :id, :content
        node(:answers_count) do |question|
            question.answers.where("submission_id = ?", submission_id).count
        end
        node(:answers) do |question|
            question.answers.where("submission_id = ?", submission_id).collect{ |answer| {:name => answer.name, :id => answer.id}}
        end
    end
end    

INCORRECT SOLUTIONS:

Use root_object for this:

node(:answers_count) do |question|
  question.answers.where("submission_id = ?", root_object.id).count
end

Alternatively, pass it as an argument to the child :report block:

    object @submission
    attributes :status, :submission_time

    child :report do |submission|
        attribute :id, :name
        child :questions do
            attribute :id, :content
            node(:answers_count) do |question|
                question.answers.where("submission_id = ?", submission.id).count
            end
            node(:answers) do |question|
                question.answers.where("submission_id = ?", submission.id).collect{ |answer| {:name => answer.name, :id => answer.id}}
            end
        end
    end

Unfortunately, neither of these approaches worked. The first solution doesn't work because root_object changes with the block scope (it identifies the parent for the containing block). The second solution doesn't work because unlike node, child passes in the child object for that iteration. Unfortunately, this is contrary to what the documentation would have you believe.

PinnyM
  • 35,165
  • 3
  • 73
  • 81
  • In first solution root_object is pointing the question object for that loop and in second solution submission start pointing to report object. :( – Mohit Jain May 20 '13 at 14:12
  • @MohitJain: You are right, but there must be a mistake in [the docs](https://github.com/nesquena/rabl#child-nodes) that seems to indicate the second solution would work. Also, see http://stackoverflow.com/questions/15878381/how-to-add-parent-attributes-inside-its-children-in-rabl-template-when-parent-i which seems to have a similar problem. Frankly, I'm surprised that RABL makes it difficult to access the root via child (as opposed to a node). – PinnyM May 20 '13 at 14:49