grape-entity icon indicating copy to clipboard operation
grape-entity copied to clipboard

Only Option Not Correct for Nested Value

Open Linell opened this issue 10 years ago • 2 comments
trafficstars

I have a couple entities that look like this:

class Foo::Entity < Grape::Entity
  expose :id, :foo_name
end

class Bar::Entity < Grape::Entity
  expose :id, :stuff, :things

  expose :foo, :using => Foo::Entity
end

In the resource for Bar, I'm doing

get '/' do
  present @bars.index(:limit => @limit), :only => @only
end

For the first layer, this works great. For example, passing [:id, :things] to @only works perfectly. Passing nothing to @only results in me getting the full Foo object too, which is exactly what I want.

The issue arises when I pass [:id, :things, {:foo => [:foo_name]}]. Instead of the expected id, things, and foo hash containing foo_name, I get back id, things and a foo hash containing just the foo object's id.

Linell avatar Oct 12 '15 20:10 Linell

The problem with my above example lies in the code for should_return_key?.

The only_fields variable, in my case, is this:

{:id => true, :things => true, :foo => [:foo_name]}.

BUT the actual check for whether or not the key should be included is just only_fields.key?(key). Which fails for foo_name, since it isn't a key of only_fields. Anything nested the way the README shows isn't going to work.

Even worse though, is that the id is returning in my above example. This is caused by the fact that it's just looping over all of the keys in each exposure and trying them against only_fields. What that means is anything that shares a key is going to show up (in my case because I want the bar id).

Is there a way to know which object we're comparing the key to? Or maybe even just if we could know if it's supposed to be nested at all?

Linell avatar Oct 12 '15 23:10 Linell

So I've narrowed it down a little more. I don't 100% understand everything that's going on, but it looks like when serializable_hash is called for my nested object the options[:only] field (which is correct) is being overridden by the options.merge(runtime_options || {}) line.

If the override wasn't happening, it works correctly. The only_fields variable from my previous comment is populated with just the things it should be and so it works just fine. If I just make opts = options it seems golden.

Linell avatar Oct 13 '15 15:10 Linell