Module: Mongoid::CachedJson::ClassMethods
- Defined in:
- lib/mongoid-cached-json/cached_json.rb
Instance Method Summary collapse
-
#cached_json_key(options, cached_class, cached_id) ⇒ Object
Cache key.
-
#json_fields(defs) ⇒ Object
Define JSON fields for a class.
-
#materialize_cached_json(clazz, id, object_reference, options) ⇒ Object
Materialize a cached JSON within a cache block.
-
#materialize_json(options, object_def) ⇒ Object
Given an object definition in the form of either an object or a class, id pair, grab the as_json representation from the cache if possible, otherwise create the as_json representation by loading the object from the database.
-
#resolve_json_reference(options, object, field, reference_def) ⇒ Object
If the reference is a symbol, we may be lucky and be able to figure out the as_json representation by the (class, id) pair definition of the reference.
Instance Method Details
#cached_json_key(options, cached_class, cached_id) ⇒ Object
Cache key.
109 110 111 112 |
# File 'lib/mongoid-cached-json/cached_json.rb', line 109 def cached_json_key(, cached_class, cached_id) base_class_name = cached_class.collection_name.to_s.singularize.camelize "as_json/#{[:version]}/#{base_class_name}/#{cached_id}/#{[:properties]}/#{!![:is_top_level_json]}" end |
#json_fields(defs) ⇒ Object
Define JSON fields for a class.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/mongoid-cached-json/cached_json.rb', line 21 def json_fields(defs) self.hide_as_child_json_when = defs.delete(:hide_as_child_json_when) || lambda { |a| false } self.all_json_properties = [ :short, :public, :all ] cached_json_defs = Hash[defs.map { |k,v| [k, { :type => :callable, :properties => :short, :definition => k }.merge(v)] }] self.cached_json_field_defs = {} self.cached_json_reference_defs = {} # Collect all versions for clearing cache self.all_json_versions = cached_json_defs.map do |field, definition| [ :unspecified, definition[:version], Array(definition[:versions]) ] end.flatten.compact.uniq self.all_json_properties.each_with_index do |property, i| self.cached_json_field_defs[property] = Hash[cached_json_defs.find_all do |field, definition| self.all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :callable end] self.cached_json_reference_defs[property] = Hash[cached_json_defs.find_all do |field, definition| self.all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :reference end] # If the field is a reference and is just specified as a symbol, reflect on it to get metadata self.cached_json_reference_defs[property].to_a.each do |field, definition| if definition[:definition].is_a?(Symbol) self.cached_json_reference_defs[property][field][:metadata] = self.reflect_on_association(definition[:definition]) end end end after_update :expire_cached_json after_destroy :expire_cached_json end |
#materialize_cached_json(clazz, id, object_reference, options) ⇒ Object
Materialize a cached JSON within a cache block.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/mongoid-cached-json/cached_json.rb', line 50 def materialize_cached_json(clazz, id, object_reference, ) is_top_level_json = [:is_top_level_json] || false object_reference = clazz.where({ :_id => id }).first if !object_reference if !object_reference || (!is_top_level_json && [:properties] != :all && clazz.hide_as_child_json_when.call(object_reference)) nil else Hash[clazz.cached_json_field_defs[[:properties]].map do |field, definition| # version match versions = ([definition[:version] ] | Array(definition[:versions])).compact next unless versions.empty? or versions.include?([:version]) json_value = (definition[:definition].is_a?(Symbol) ? object_reference.send(definition[:definition]) : definition[:definition].call(object_reference)) Mongoid::CachedJson.config.transform.each do |t| json_value = t.call(field, definition, json_value) end [field, json_value] end] end end |
#materialize_json(options, object_def) ⇒ Object
Given an object definition in the form of either an object or a class, id pair, grab the as_json representation from the cache if possible, otherwise create the as_json representation by loading the object from the database. For any references in the object’s JSON representation, we have to recursively materialize the JSON by calling resolve_json_reference on each of them (which may, in turn, call materialize_json)
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/mongoid-cached-json/cached_json.rb', line 75 def materialize_json(, object_def) return nil if !object_def[:object] and !object_def[:id] is_top_level_json = [:is_top_level_json] || false if object_def[:object] object_reference = object_def[:object] clazz, id = object_def[:object].class, object_def[:object].id else object_reference = nil clazz, id = object_def[:clazz], object_def[:id] end key = self.cached_json_key(, clazz, id) json = { :_ref => { :_clazz => self, :_key => key, :_materialize_cached_json => [ clazz, id, object_reference, ] }} keys = KeyReferences.new keys.set_and_add(key, json) reference_defs = clazz.cached_json_reference_defs[[:properties]] if !reference_defs.empty? object_reference = clazz.where({ :_id => id }).first if !object_reference if object_reference && (is_top_level_json || [:properties] == :all || !clazz.hide_as_child_json_when.call(object_reference)) json.merge!(Hash[reference_defs.map do |field, definition| json_properties_type = definition[:reference_properties] || (([:properties] == :all) ? :all : :short) reference_keys, reference = clazz.resolve_json_reference(.merge({ :properties => json_properties_type, :is_top_level_json => false}), object_reference, field, definition) if (reference.is_a?(Hash) && ref = reference[:_ref]) ref[:_parent] = json ref[:_field] = field end keys.merge_set(reference_keys) [field, reference] end]) end end [ keys, json ] end |
#resolve_json_reference(options, object, field, reference_def) ⇒ Object
If the reference is a symbol, we may be lucky and be able to figure out the as_json representation by the (class, id) pair definition of the reference. That is, we may be able to load the as_json representation from the cache without even getting the model from the database and materializing it through Mongoid. We’ll try to do this first.
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/mongoid-cached-json/cached_json.rb', line 118 def resolve_json_reference(, object, field, reference_def) keys = nil reference_json = nil if reference_def[:metadata] key = reference_def[:metadata].key.to_sym if reference_def[:metadata].polymorphic? clazz = reference_def[:metadata].inverse_class_name.constantize else clazz = reference_def[:metadata].class_name.constantize end if reference_def[:metadata].relation == Mongoid::Relations::Referenced::ManyToMany object_ids = object.send(key) reference_json = object_ids ? object_ids.map do |id| materialize_keys, json = materialize_json(, { :clazz => clazz, :id => id }) keys = keys ? keys.merge_set(materialize_keys) : materialize_keys json end.compact : [] end end # If we get to this point and reference_json is still nil, there's no chance we can # load the JSON from cache so we go ahead and call as_json on the object. if ! reference_json reference_def_definition = reference_def[:definition] reference = reference_def_definition.is_a?(Symbol) ? object.send(reference_def_definition) : reference_def_definition.call(object) reference_json = nil if reference if reference.respond_to?(:as_json_partial) reference_keys, reference_json = reference.as_json_partial() keys = keys ? keys.merge_set(reference_keys) : reference_keys else reference_json = reference.as_json() end end end [ keys, reference_json ] end |