4

I have a RABL template as shown below

object @user
attributes :name
child :contacts do
  # does not work
  if contact.is_foo?
    attributes :a1, :a2
  else
    attributes :a3, :a4
  end
end

How do I access the Contact object in the child block of the template? I need to perform some conditional logic on the child instance.

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198

4 Answers4

10

You can access the current object by declaring the block parameter.

object @user
attributes :name
child :contacts do |contact|
  if contact.is_foo?
    attributes :a1, :a2
  else
    attributes :a3, :a4
  end
end

Old answer

I ended up using the root_object method, which returns the data object in a given context.

object @user
attributes :name
child :contacts do
  if root_object.is_foo?
    attributes :a1, :a2
  else
    attributes :a3, :a4
  end
end
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
  • 1
    This answer implies that the root_object will give you an individual contact that changes as the template iterates though the contacts collection. I find that it simply gives me the whole contacts collection with no indicator of which child contact is being processed. – J Edward Ellis Nov 07 '16 at 20:52
3

Another approach to keep things DRY:

contacts/show.json.rabl

object @contact
node do |contact|
    if contact.is_foo?
        {:a1 => contact.a1, :a2 => contact.a2}
    else
        {:a3 => contact.a3, :a4 => contact.a4}
    end
end

users/show.json.rabl

object @user
attributes :name
child :contacts do
    extends 'contacts/show'
end
T C
  • 1,337
  • 1
  • 12
  • 21
1

Here's one way:

child :contacts do
  node(:a1, :if => lambda { |c| c.is_foo? }
  node(:a2, :if => lambda { |c| c.is_foo? }

  node(:a3, :unless => lambda { |c| c.is_foo? }
  node(:a4, :unless => lambda { |c| c.is_foo? }
end

Not exactly the same but one possibility, another is:

node :contacts do |u|
  u.contacts.map do |c|
    if contact.is_foo?
      partial("contacta", :object => c)
      # or { :a1 => "foo", :a2 => "bar" }
    else
      partial("contactb", :object => c)
      # or { :a3 => "foo", :a4 => "bar" }
    end
  end
end
nesquena
  • 216
  • 2
  • 6
0

I know it's a late reply but came across the similar problem so thought of answering.

It's more like a hack but works.

When two variables are used as block argument contact and a random variable x, contact refers to an object of the collection

When one variable is used in block argument, it renders collection object
object @user
attributes :name
child :contacts do |contact, x|
  if contact.is_foo?
    attributes :a1, :a2
  else
    attributes :a3, :a4
  end
end