Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json_fields: expose all fields plus additional methods #12

Open
marks opened this issue Apr 4, 2013 · 12 comments
Open

json_fields: expose all fields plus additional methods #12

marks opened this issue Apr 4, 2013 · 12 comments
Labels

Comments

@marks
Copy link

marks commented Apr 4, 2013

I'm new to using mongoid-cached-json but so far it seems like exactly what I need - thank you!

I have a fairly complex model and I want .to_json to expose all of its key/values just as it did before I added mongoid-cached-json to the mix but also two methods (:definition => :method). When I do the following, .to_json starts to only expose the two defined methods.

Bottom line: trying to have it just add the defined fields to .to_json and not replace the existing contents. Ideas? Is that within scope of this project?

json_fields \
  :display_name => {:definition => :display_name},
  :display_id => {:definition => :display_id}

Many thanks in advance!

@dblock
Copy link
Collaborator

dblock commented Apr 5, 2013

How do you already expose the existing fields today?

In order to do caching this gem will need to know about each field, notably whether it's a reference or whether it's not. That's because to construct the JSON we mix cached and non-cached reference data, avoiding a lot of data calls in the process. If you expose all your existing fields (say all attributes) I would be definitely open to extending this gem to support it. For example:

json_fields \
   attributes: { select: :all }, # maybe attributes: :auto, etc.?
   something_else: { ... }

@marks
Copy link
Author

marks commented Apr 5, 2013

Before your gem I was doing 'as_document.to_json'. Your comments gave me an idea. I could make a self.attributes method that simply collected all the methods in the document. Is the what you were suggesting?

Mark Silverberg
marksilver.net/LinkedIn
(Sent from my iPhone)

On Apr 5, 2013, at 7:47 AM, "Daniel Doubrovkine (dB.)" notifications@github.com wrote:

How do you already expose the existing fields today?

In order to do caching this gem will need to know about each field, notably whether it's a reference or whether it's not. That's because to construct the JSON we mix cached and non-cached reference data, avoiding a lot of data calls in the process. If you expose all your existing fields (say all attributes) I would be definitely open to extending this gem to support it. For example:

json_fields
attributes: { select: :all }, # maybe attributes: :auto, etc.?
something_else: { ... }

Reply to this email directly or view it on GitHub.

@dblock
Copy link
Collaborator

dblock commented Apr 5, 2013

Not really. Again, mongoid_cached_json needs to know about the actual attributes, its implementation keeps all kinds of structures around that it looks at when overriding as_json. So I mean extending functionality of this gem to look into every attribute and add it to the internal structures without their definition. An automatic way to listing all attributes, as if you listed them manually with attribute: ... under json_fields.

@marks
Copy link
Author

marks commented Apr 5, 2013

Got it -- that "attribute: ... under json_fields" sounds like a viable solution for what I'm looking to do.

@mping
Copy link

mping commented Dec 28, 2013

So is there an equivalent of user.as_json(methods: :permalink) right now?

@dblock
Copy link
Collaborator

dblock commented Jan 2, 2014

@mping Care to elaborate?

@mping
Copy link

mping commented Jan 3, 2014

Sure, the rails docs state that you can indicate methods to be called when generating the json: http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html here's the relevant example:

user.as_json(methods: :permalink)
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
#      "created_at" => "2006/08/01", "awesome" => true,
#      "permalink" => "1-konata-izumi" }

is there an equivalent for this? AFAIK you can only indicate what fields you want. I am also having trouble understanding the lifecycle of the json cache, ie, if I should manually expire an object or not. My ideal use case would be that I would just include the gem, I wouldn't even need to specify the json_fields (btw this causes an error) and my as_json custom calls would just work with the cache.

@dblock
Copy link
Collaborator

dblock commented Jan 3, 2014

Your ideal workflow would be a good feature request (this thread is that feature request): something that automatically figures out which fields to include in the JSON. This is just not implemented. Currently you have to declare the JSON fields.

There's no equivalent of specifying what you want in the JSON at runtime, you have to do this through a json_fields declaration. Those can vary by properties: ... hierarchy, but that's it. If you were to specify things at runtime, caching would become harder, as we would have to also vary it by the parameters of the call. So it's not as simple as overriding as_json.

You don't have to manually expire anything, when you include the module in a Mongoid document cache will expire on changes.

@mping
Copy link

mping commented Jan 3, 2014

I don't mind declaring the json_fields. I can specify fields at compile-time/class declaration, but I would like a more freeform way to declare it, something like:

class Widget
  include Mongoid::CachedJson

  field :name
  has_many :gadgets

  json_fields \
    :name => {:properties => [:schema1] },
    :gadgets => { :type => :reference, :properties => [:schema1, :schema2] }
    :permalink {:type => :method, :properties => [:schema2]}
end


# method would not have side effects, or at least would be idempotent for same self
def permalink
   widget_path(@widget) #or something else
end

widget.as_json({ :properties => :schema1 })

this would cover 99% of my needs :)

@dblock
Copy link
Collaborator

dblock commented Jan 3, 2014

The properties are a hierarchy by design and currently hard-coded. We chose the hierarchy deliberately because this creates a lot of nesting problems (a parent can contain a child with its :short json in its :public properties, and the child can also contain the parent with a :short json reference in its :public properties). If you remove the hierarchy you will have to be even more careful to avoid circular references.

I am open to evolving both of these things, but I suspect the implementation is far from trivial.

@mping
Copy link

mping commented Jan 3, 2014

I haven't looked at the code, so can't really say there's a way to implement custom properties, but allowing {:type => :method} shouldn't be too hard. Can you point me to where to look? Thanks

@dblock
Copy link
Collaborator

dblock commented Jan 3, 2014

It's all here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants