1

I've been through the other similar questions, and unfortunately, nothing seems to be helping my situation.

I'm attempting to use rabl to generate my JSON, but if any of the attributes I need for a child object are nil, I want to skip that child. My original template looks like

child :links, :root => :edges, :object_root => :datas do
    node(:id) { |link| link.id.to_s() }
    node(:source) { |link| link.parent_id.to_s() }
    node(:target) { |link| link.child_id.to_s() }
end

I've been trying to figure out how to exclude things. So if I have

child :links, unless: lambda{|l| l.child_id == nil || l.parent_id == nil},:root => :edges, :object_root => :datas do
    node(:id) { |link| link.id.to_s() }
    node(:source) { |link| link.parent_id.to_s() }
    node(:target) { |link| link.child_id.to_s() }
end

I get "undefined child_id for Work..." as an error. So apparently, even though its in the child declaration, it's still referring to the parent. I tried moving that code into a separate file and including it, and received the same error. Using an if statement also has the same issue.

I then tried

child :links, :root => :edges, :object_root => :datas do
    node(:id, unless: lambda{|l| l.child_id == nil || l.parent_id == nil} ) { |link| link.id.to_s() }
    node(:source, unless: lambda{|l| l.child_id == nil || l.parent_id == nil}) { |link| link.parent_id.to_s() }
    node(:target, unless: lambda{|l| l.child_id == nil || l.parent_id == nil}) { |link| link.child_id.to_s() }
end

But that gives me {"data":{}}, which I don't want. I just want nothing at all if it fails the condition.

Based on some of the replies in Accessing the child instance in a RABL template, I tried

child :links, :root => :edges, :object_root => :datas do
    if root_object.child_id == nil
        node(:id) { |link| link.id.to_s() }
        node(:source) { |link| link.parent_id.to_s() }
        node(:target) { |link| link.child_id.to_s() }
    end
end

And received "undefined method `child_id' for # ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Link"

It seems strange to me that this is so difficult to do. Basically, how can I refer to the individual child element at each step of this loop? So that I can actually check it and ignore it. Is this an issue with rabl-rails?

EDIT:

So, after reading https://github.com/nesquena/rabl/issues/367, I tried the following:

#works.rb
def valid_links
    links = self.links.select {|l| l.parent_id != nil && l.child_id != nil}
    return links
end

#works/show.json.rabl
child :valid_links => "edges" do
    node(:id) { |link| link.id.to_s() }
    node(:source) { |link| link.child_id.to_s() }
    node(:target) { |link| link.parent_id.to_s() }
end

This is almost working. However, I need to define the object_root and root. I got around root by just setting the valid_links to point to what I need, but whenever I try to define the object_root I get "undefined method `id' for [:valid_links, "links"]:Array". Is there any way around this?

Thanks.

Community
  • 1
  • 1
LiamD
  • 1,958
  • 2
  • 13
  • 13

1 Answers1

3

The docs say you can pass in the child object to the block like this:

child :links, :root => :edges, :object_root => :datas do |child|
  unless child.child_id.nil?
    ...
  end
end

(in the docs search for "You can also pass in the current object").

jeanaux
  • 713
  • 3
  • 9
  • I just gave that a shot, and unfortunately, it's returning the "undefined method `child_id' for # – LiamD Mar 30 '14 at 20:19
  • one indirect solution could be to exclude the children before they get to rabl. I.e. on your model you could define a method that filters the children and call that instead of links. – jeanaux Mar 30 '14 at 20:44
  • Yeah, that's what I've resorted to doing (I edited my question.) Unfortunately, that prevents me from using object_root (and root) for some reason. So now I'm trying to figure out an alternative way to set the object root. – LiamD Mar 30 '14 at 20:47