1
votes

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.

1

1 Answers

3
votes

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").