mongoid-cached-json
mongoid-cached-json copied to clipboard
json_fields: expose all fields plus additional methods
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!
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: { ... }
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.)" [email protected] 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.
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.
Got it -- that "attribute: ... under json_fields" sounds like a viable solution for what I'm looking to do.
So is there an equivalent of user.as_json(methods: :permalink) right now?
@mping Care to elaborate?
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.
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.
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 :)
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.
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
It's all here.