Class: ActiveModel::Csverizer

Inherits:
Object
  • Object
show all
Defined in:
lib/active_model/csverizer.rb,
lib/active_model/csverizer/version.rb

Defined Under Namespace

Classes: Railtie

Constant Summary collapse

EMBED_IN_ROOT_OPTIONS =
[
  :include,
  :embed_in_root,
  :embed_in_root_key,
  :embed_namespace
].freeze
VERSION =
'0.0.7'

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, options = {}) ⇒ Csverizer

Returns a new instance of Csverizer.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/active_model/csverizer.rb', line 134

def initialize(object, options={})
  @object        = object
  @scope         = options[:scope]
  @root          = options.fetch(:root, self.class._root)
  @polymorphic   = options.fetch(:polymorphic, false)
  @meta_key      = options[:meta_key] || :meta
  @meta          = options[@meta_key]
  @wrap_in_array = options[:_wrap_in_array]
  @only          = options[:only] ? Array(options[:only]) : nil
  @except        = options[:except] ? Array(options[:except]) : nil
  @key_format    = options[:key_format]
  @context       = options[:context]
  @namespace     = options[:namespace]
  @prefix        = options.fetch(:prefix, '')
end

Class Attribute Details

._associationsObject

Returns the value of attribute _associations.



68
69
70
# File 'lib/active_model/csverizer.rb', line 68

def _associations
  @_associations
end

._attributesObject

Returns the value of attribute _attributes.



68
69
70
# File 'lib/active_model/csverizer.rb', line 68

def _attributes
  @_attributes
end

._rootObject

Returns the value of attribute _root.



68
69
70
# File 'lib/active_model/csverizer.rb', line 68

def _root
  @_root
end

.key_formatObject (readonly)

Returns the value of attribute key_format.



49
50
51
# File 'lib/active_model/csverizer.rb', line 49

def key_format
  @key_format
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def context
  @context
end

#key_formatObject

Returns the value of attribute key_format.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def key_format
  @key_format
end

#metaObject

Returns the value of attribute meta.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def meta
  @meta
end

#meta_keyObject

Returns the value of attribute meta_key.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def meta_key
  @meta_key
end

#objectObject

Returns the value of attribute object.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def object
  @object
end

#polymorphicObject

Returns the value of attribute polymorphic.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def polymorphic
  @polymorphic
end

#rootObject

Returns the value of attribute root.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def root
  @root
end

#scopeObject

Returns the value of attribute scope.



149
150
151
# File 'lib/active_model/csverizer.rb', line 149

def scope
  @scope
end

#serialization_optionsObject



286
287
288
# File 'lib/active_model/csverizer.rb', line 286

def serialization_options
  @serialization_options || {}
end

Class Method Details

.attributes(*attrs) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
# File 'lib/active_model/csverizer.rb', line 79

def attributes(*attrs)
  attrs.each do |attr|
    striped_attr = strip_attribute attr

    @_attributes << striped_attr

    define_method striped_attr do
      object.read_attribute_for_serialization attr
    end unless method_defined?(attr)
  end
end

.embed(type, options = {}) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/active_model/csverizer.rb', line 27

def embed(type, options={})
  CONFIG.embed = type
  if EMBED_IN_ROOT_OPTIONS.any? { |opt| options[opt].present? }
    CONFIG.embed_in_root = true
  end
  if options[:embed_in_root_key].present?
    CONFIG.embed_in_root_key = options[:embed_in_root_key]
  end
  ActiveSupport::Deprecation.warn "** Notice: embed is deprecated. **\nThe use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.\nPlease use the global .setup method instead:\nActiveModel::Serializer.setup do |config|\n  config.embed = :\#{type}\n  config.embed_in_root = \#{CONFIG.embed_in_root || false}\nend\n  WARN\nend\n"

.format_keys(format) ⇒ Object



46
47
48
# File 'lib/active_model/csverizer.rb', line 46

def format_keys(format)
  @key_format = format
end

.has_many(*attrs) ⇒ Object



95
96
97
# File 'lib/active_model/csverizer.rb', line 95

def has_many(*attrs)
  associate(Association::HasMany, *attrs)
end

.has_one(*attrs) ⇒ Object



91
92
93
# File 'lib/active_model/csverizer.rb', line 91

def has_one(*attrs)
  associate(Association::HasOne, *attrs)
end

.inherited(base) ⇒ Object



8
9
10
11
12
# File 'lib/active_model/csverizer.rb', line 8

def inherited(base)
  base._root = _root
  base._attributes = (_attributes || []).dup
  base._associations = (_associations || {}).dup
end

.root_nameObject



72
73
74
75
76
77
# File 'lib/active_model/csverizer.rb', line 72

def root_name
  if name
    root_name = name.demodulize.underscore.sub(/_serializer$/, '')
    CONFIG.plural_default_root ? root_name.pluralize : root_name
  end
end

.serializer_for(resource, options = {}) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/active_model/csverizer.rb', line 51

def serializer_for(resource, options = {})
  if resource.respond_to?(:serializer_class)
    resource.serializer_class
  elsif resource.respond_to?(:to_ary)
    if Object.constants.include?(:ArraySerializer)
      ::ArraySerializer
    else
      ArraySerializer
    end
  else
    klass_name = build_serializer_class(resource, options)
    Serializer.serializers_cache.fetch_or_store(klass_name) do
      _const_get(klass_name)
    end
  end
end

.serializers_cacheObject



99
100
101
# File 'lib/active_model/csverizer.rb', line 99

def serializers_cache
  @serializers_cache ||= Concurrent::Map.new
end

.setupObject



14
15
16
17
18
# File 'lib/active_model/csverizer.rb', line 14

def setup
  @mutex.synchronize do
    yield CONFIG
  end
end

Instance Method Details

#associated_serializersObject



348
349
350
351
352
353
# File 'lib/active_model/csverizer.rb', line 348

def associated_serializers
  @associated_serializers ||= self.class._associations.collect do |hash|
    object = read_attribute(hash[:associated])
    hash[:serializer].new(object, prefix: hash[:associated].to_s + '_')
  end
end

#association_options_for_serializer(association) ⇒ Object



238
239
240
241
242
243
244
245
246
# File 'lib/active_model/csverizer.rb', line 238

def association_options_for_serializer(association)
  prefix    = association.options[:prefix]
  namespace = association.options[:namespace] || @namespace || self.namespace

  { scope: scope }.tap do |opts|
    opts[:namespace] = namespace if namespace
    opts[:prefix]    = prefix    if prefix
  end
end

#associations(options = {}) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/active_model/csverizer.rb', line 167

def associations(options={})
  associations = self.class._associations
  included_associations = filter(associations.keys)
  associations.each_with_object({}) do |(name, association), hash|
    if included_associations.include? name
      if association.embed_ids?
        ids = serialize_ids association
        if association.embed_namespace?
          hash = hash[association.embed_namespace] ||= {}
          hash[association.key] = ids
        else
          hash[association.key] = ids
        end
      elsif association.embed_objects?
        if association.embed_namespace?
          hash = hash[association.embed_namespace] ||= {}
        end
        hash[association.embedded_key] = serialize association, options
      end
    end
  end
end

#attribute_namesObject



330
331
332
333
334
335
336
337
# File 'lib/active_model/csverizer.rb', line 330

def attribute_names
  names = self.class._attributes.collect do |attribute|
    @prefix + attribute.to_s
  end
  associated_serializers.reduce(names) do |names, serializer|
    names.concat serializer.attribute_names
  end
end

#attributesObject



161
162
163
164
165
# File 'lib/active_model/csverizer.rb', line 161

def attributes
  filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
    hash[name] = send(name)
  end
end

#build_serializer(association) ⇒ Object



233
234
235
236
# File 'lib/active_model/csverizer.rb', line 233

def build_serializer(association)
  object = send(association.name)
  association.build_serializer(object, association_options_for_serializer(association))
end

#convert_keys(hash) ⇒ Object



273
274
275
276
277
278
279
280
281
282
283
# File 'lib/active_model/csverizer.rb', line 273

def convert_keys(hash)
  Hash[hash.map do |k,v|
    key = if k.is_a?(Symbol)
      format_key(k).to_sym
    else
      format_key(k)
    end

    [key ,v]
  end]
end

#embedded_in_root_associationsObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/active_model/csverizer.rb', line 200

def embedded_in_root_associations
  associations = self.class._associations
  included_associations = filter(associations.keys)
  associations.each_with_object({}) do |(name, association), hash|
    if included_associations.include? name
      association_serializer = build_serializer(association)
      # we must do this always because even if the current association is not
      # embedded in root, it might have its own associations that are embedded in root
      hash.merge!(association_serializer.embedded_in_root_associations) do |key, oldval, newval|
        if oldval.respond_to?(:to_ary)
          [oldval, newval].flatten.uniq
        else
          oldval.merge(newval) { |_, oldval, newval| [oldval, newval].flatten.uniq }
        end
      end

      if association.embed_in_root?
        if association.embed_in_root_key?
          hash = hash[association.embed_in_root_key] ||= {}
        end

        serialized_data = association_serializer.serializable_object
        key = association.root_key
        if hash.has_key?(key)
          hash[key].concat(serialized_data).uniq!
        else
          hash[key] = serialized_data
        end
      end
    end
  end
end

#filter(keys) ⇒ Object



190
191
192
193
194
195
196
197
198
# File 'lib/active_model/csverizer.rb', line 190

def filter(keys)
  if @only
    keys & @only
  elsif @except
    keys - @except
  else
    keys
  end
end

#format_key(key) ⇒ Object



265
266
267
268
269
270
271
# File 'lib/active_model/csverizer.rb', line 265

def format_key(key)
  if key_format == :lower_camel
    key.to_s.camelize(:lower)
  else
    key
  end
end

#json_keyObject



151
152
153
154
155
156
157
158
159
# File 'lib/active_model/csverizer.rb', line 151

def json_key
  key = if root == true || root.nil?
    self.class.root_name
  else
    root
  end

  key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
end

#read_association(name) ⇒ Object



344
345
346
# File 'lib/active_model/csverizer.rb', line 344

def read_association(name)
  respond_to?(name) ? send(name) : object.send(name)
end

#read_attribute(name) ⇒ Object



339
340
341
342
# File 'lib/active_model/csverizer.rb', line 339

def read_attribute(name)
  return send(name) if respond_to?(name)
  object.read_attribute_for_serialization(name)
end

#serializable_object(options = {}) ⇒ Object Also known as: serializable_hash



290
291
292
293
294
295
296
297
298
# File 'lib/active_model/csverizer.rb', line 290

def serializable_object(options={})
  self.serialization_options = options
  return @wrap_in_array ? [] : nil if @object.nil?
  hash = attributes
  hash.merge! associations(options)
  hash = convert_keys(hash) if key_format.present?
  hash = { :type => type_name(@object), type_name(@object) => hash } if @polymorphic
  @wrap_in_array ? [hash] : hash
end

#serialize(association, options = {}) ⇒ Object



248
249
250
# File 'lib/active_model/csverizer.rb', line 248

def serialize(association,options={})
  build_serializer(association).serializable_object(options)
end

#serialize_id(elem, association) ⇒ Object



301
302
303
304
# File 'lib/active_model/csverizer.rb', line 301

def serialize_id(elem, association)
  id = elem.read_attribute_for_serialization(association.embed_key)
  association.polymorphic? ? { id: id, type: type_name(elem) } : id
end

#serialize_ids(association) ⇒ Object



252
253
254
255
256
257
258
259
# File 'lib/active_model/csverizer.rb', line 252

def serialize_ids(association)
  associated_data = send(association.name)
  if associated_data.respond_to?(:to_ary)
    associated_data.map { |elem| serialize_id(elem, association) }
  else
    serialize_id(associated_data, association) if associated_data
  end
end

#to_aObject



317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/active_model/csverizer.rb', line 317

def to_a
  return [[]] unless @object

  values = []
  values << self.class._attributes.collect { |name| read_attribute(name) }

  associated_serializers.each do |serializer|
    values = values.product(serializer.to_a).collect(&:flatten)
  end

  values
end

#to_csvObject



310
311
312
313
314
315
# File 'lib/active_model/csverizer.rb', line 310

def to_csv
  CSV.generate do |csv|
    csv << attribute_names
    to_a.each { |record| csv << record }
  end
end

#type_name(elem) ⇒ Object



306
307
308
# File 'lib/active_model/csverizer.rb', line 306

def type_name(elem)
  elem.class.to_s.demodulize.underscore.to_sym
end