active_model_serializers 0.8.3 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -5
  3. data/CONTRIBUTING.md +20 -0
  4. data/DESIGN.textile +4 -4
  5. data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
  6. data/README.md +395 -95
  7. data/lib/action_controller/serialization.rb +50 -12
  8. data/lib/action_controller/serialization_test_case.rb +79 -0
  9. data/lib/active_model/array_serializer.rb +46 -78
  10. data/lib/active_model/default_serializer.rb +32 -0
  11. data/lib/active_model/serializable/utils.rb +16 -0
  12. data/lib/active_model/serializable.rb +62 -0
  13. data/lib/active_model/serializer/association/has_many.rb +39 -0
  14. data/lib/active_model/serializer/association/has_one.rb +25 -0
  15. data/lib/active_model/serializer/association.rb +58 -0
  16. data/lib/active_model/serializer/config.rb +31 -0
  17. data/lib/active_model/serializer/generators/resource_override.rb +13 -0
  18. data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
  19. data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
  20. data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
  21. data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
  22. data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
  23. data/lib/active_model/serializer/railtie.rb +18 -0
  24. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  25. data/lib/active_model/serializer.rb +209 -422
  26. data/lib/active_model/serializer_support.rb +5 -0
  27. data/lib/active_model_serializers.rb +12 -87
  28. data/test/fixtures/active_record.rb +92 -0
  29. data/test/fixtures/poro.rb +184 -0
  30. data/test/fixtures/template.html.erb +1 -0
  31. data/test/integration/action_controller/namespaced_serialization_test.rb +96 -0
  32. data/test/integration/action_controller/serialization_test.rb +303 -0
  33. data/test/integration/action_controller/serialization_test_case_test.rb +71 -0
  34. data/test/integration/active_record/active_record_test.rb +77 -0
  35. data/test/integration/generators/resource_generator_test.rb +26 -0
  36. data/test/integration/generators/scaffold_controller_generator_test.rb +64 -0
  37. data/test/integration/generators/serializer_generator_test.rb +41 -0
  38. data/test/test_app.rb +14 -0
  39. data/test/test_helper.rb +10 -18
  40. data/test/tmp/app/serializers/account_serializer.rb +3 -0
  41. data/test/unit/active_model/array_serializer/except_test.rb +18 -0
  42. data/test/unit/active_model/array_serializer/key_format_test.rb +18 -0
  43. data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
  44. data/test/unit/active_model/array_serializer/only_test.rb +18 -0
  45. data/test/unit/active_model/array_serializer/root_test.rb +102 -0
  46. data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
  47. data/test/unit/active_model/array_serializer/serialization_test.rb +199 -0
  48. data/test/unit/active_model/default_serializer_test.rb +13 -0
  49. data/test/unit/active_model/serializer/associations/build_serializer_test.rb +36 -0
  50. data/test/unit/active_model/serializer/associations_test.rb +19 -0
  51. data/test/unit/active_model/serializer/attributes_test.rb +57 -0
  52. data/test/unit/active_model/serializer/config_test.rb +91 -0
  53. data/test/unit/active_model/serializer/filter_test.rb +69 -0
  54. data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
  55. data/test/unit/active_model/serializer/has_many_test.rb +265 -0
  56. data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
  57. data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
  58. data/test/unit/active_model/serializer/has_one_test.rb +239 -0
  59. data/test/unit/active_model/serializer/key_format_test.rb +25 -0
  60. data/test/unit/active_model/serializer/meta_test.rb +39 -0
  61. data/test/unit/active_model/serializer/options_test.rb +34 -0
  62. data/test/unit/active_model/serializer/root_test.rb +117 -0
  63. data/test/unit/active_model/serializer/scope_test.rb +49 -0
  64. data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
  65. metadata +104 -63
  66. data/.gitignore +0 -18
  67. data/.travis.yml +0 -28
  68. data/Gemfile +0 -4
  69. data/Gemfile.edge +0 -9
  70. data/Rakefile +0 -18
  71. data/active_model_serializers.gemspec +0 -24
  72. data/bench/perf.rb +0 -43
  73. data/cruft.md +0 -19
  74. data/lib/active_model/serializer/associations.rb +0 -233
  75. data/lib/active_record/serializer_override.rb +0 -16
  76. data/lib/generators/resource_override.rb +0 -13
  77. data/lib/generators/serializer/serializer_generator.rb +0 -42
  78. data/lib/generators/serializer/templates/serializer.rb +0 -19
  79. data/test/array_serializer_test.rb +0 -75
  80. data/test/association_test.rb +0 -592
  81. data/test/caching_test.rb +0 -96
  82. data/test/generators_test.rb +0 -85
  83. data/test/no_serialization_scope_test.rb +0 -34
  84. data/test/serialization_scope_name_test.rb +0 -67
  85. data/test/serialization_test.rb +0 -392
  86. data/test/serializer_support_test.rb +0 -51
  87. data/test/serializer_test.rb +0 -1465
  88. data/test/test_fakes.rb +0 -217
@@ -1,3 +1,5 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+
1
3
  module ActionController
2
4
  # Action Controller Serialization
3
5
  #
@@ -27,34 +29,70 @@ module ActionController
27
29
 
28
30
  include ActionController::Renderers
29
31
 
32
+ class << self
33
+ attr_accessor :enabled
34
+ end
35
+ self.enabled = true
36
+
30
37
  included do
31
38
  class_attribute :_serialization_scope
32
39
  self._serialization_scope = :current_user
33
40
  end
34
41
 
35
- def serialization_scope
36
- send(_serialization_scope) if _serialization_scope &&
37
- respond_to?(_serialization_scope, true)
38
- end
39
-
40
- def default_serializer_options
42
+ module ClassMethods
43
+ def serialization_scope(scope)
44
+ self._serialization_scope = scope
45
+ end
41
46
  end
42
47
 
43
48
  [:_render_option_json, :_render_with_renderer_json].each do |renderer_method|
44
49
  define_method renderer_method do |resource, options|
45
- json = ActiveModel::Serializer.build_json(self, resource, options)
50
+ serializer = build_json_serializer(resource, options)
46
51
 
47
- if json
48
- super(json, options)
52
+ if serializer
53
+ super(serializer, options)
49
54
  else
50
55
  super(resource, options)
51
56
  end
52
57
  end
53
58
  end
54
59
 
55
- module ClassMethods
56
- def serialization_scope(scope)
57
- self._serialization_scope = scope
60
+ private
61
+
62
+ def namespace_for_serializer
63
+ @namespace_for_serializer ||= self.class.parent unless self.class.parent == Object
64
+ end
65
+
66
+ def default_serializer(resource)
67
+ options = {}.tap do |o|
68
+ o[:namespace] = namespace_for_serializer if namespace_for_serializer
69
+ end
70
+
71
+ ActiveModel::Serializer.serializer_for(resource, options)
72
+ end
73
+
74
+ def default_serializer_options
75
+ {}
76
+ end
77
+
78
+ def serialization_scope
79
+ _serialization_scope = self.class._serialization_scope
80
+ send(_serialization_scope) if _serialization_scope && respond_to?(_serialization_scope, true)
81
+ end
82
+
83
+ def build_json_serializer(resource, options = {})
84
+ options = default_serializer_options.merge(options)
85
+ @namespace_for_serializer = options.fetch(:namespace, nil)
86
+
87
+ if serializer = options.fetch(:serializer, default_serializer(resource))
88
+ options[:scope] = serialization_scope unless options.has_key?(:scope)
89
+
90
+ if resource.respond_to?(:each)
91
+ options[:resource_name] = controller_name
92
+ options[:namespace] = namespace_for_serializer if namespace_for_serializer
93
+ end
94
+
95
+ serializer.new(resource, options)
58
96
  end
59
97
  end
60
98
  end
@@ -0,0 +1,79 @@
1
+ module ActionController
2
+ module SerializationAssertions
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ setup :setup_serialization_subscriptions
7
+ teardown :teardown_serialization_subscriptions
8
+ end
9
+
10
+ def setup_serialization_subscriptions
11
+ @serializers = Hash.new(0)
12
+
13
+ ActiveSupport::Notifications.subscribe("!serialize.active_model_serializers") do |name, start, finish, id, payload|
14
+ serializer = payload[:serializer]
15
+ @serializers[serializer] += 1
16
+ end
17
+ end
18
+
19
+ def teardown_serialization_subscriptions
20
+ ActiveSupport::Notifications.unsubscribe("!serialize.active_model_serializers")
21
+ end
22
+
23
+ def process(*args)
24
+ @serializers = Hash.new(0)
25
+ super
26
+ end
27
+
28
+ # Asserts that the request was rendered with the appropriate serializers.
29
+ #
30
+ # # assert that the "PostSerializer" serializer was rendered
31
+ # assert_serializer "PostSerializer"
32
+ #
33
+ # # assert that the instance of PostSerializer was rendered
34
+ # assert_serializer PostSerializer
35
+ #
36
+ # # assert that the "PostSerializer" serializer was rendered
37
+ # assert_serializer :post_serializer
38
+ #
39
+ # # assert that the rendered serializer starts with "Post"
40
+ # assert_serializer %r{\APost.+\Z}
41
+ #
42
+ # # assert that no serializer was rendered
43
+ # assert_serializer nil
44
+ #
45
+ #
46
+ def assert_serializer(options = {}, message = nil)
47
+ # Force body to be read in case the template is being streamed.
48
+ response.body
49
+
50
+ rendered = @serializers
51
+ msg = message || "expecting <#{options.inspect}> but rendering with <#{rendered.keys}>"
52
+
53
+ matches_serializer = case options
54
+ when lambda { |options| options.kind_of?(Class) && options < ActiveModel::Serializer }
55
+ rendered.any? do |serializer, count|
56
+ options.name == serializer
57
+ end
58
+ when Symbol
59
+ options = options.to_s.camelize
60
+ rendered.any? do |serializer, count|
61
+ serializer == options
62
+ end
63
+ when String
64
+ !options.empty? && rendered.any? do |serializer, count|
65
+ serializer == options
66
+ end
67
+ when Regexp
68
+ rendered.any? do |serializer, count|
69
+ serializer.match(options)
70
+ end
71
+ when NilClass
72
+ rendered.blank?
73
+ else
74
+ raise ArgumentError, "assert_serializer only accepts a String, Symbol, Regexp, ActiveModel::Serializer, or nil"
75
+ end
76
+ assert matches_serializer, msg
77
+ end
78
+ end
79
+ end
@@ -1,104 +1,72 @@
1
- require "active_support/core_ext/class/attribute"
2
- require 'active_support/dependencies'
3
- require 'active_support/descendants_tracker'
1
+ require 'active_model/default_serializer'
2
+ require 'active_model/serializable'
4
3
 
5
4
  module ActiveModel
6
- # Active Model Array Serializer
7
- #
8
- # Serializes an Array, checking if each element implements
9
- # the +active_model_serializer+ method.
10
- #
11
- # To disable serialization of root elements:
12
- #
13
- # ActiveModel::ArraySerializer.root = false
14
- #
15
5
  class ArraySerializer
16
- extend ActiveSupport::DescendantsTracker
17
-
18
- attr_reader :object, :options
19
-
20
- class_attribute :root
21
-
22
- class_attribute :cache
23
- class_attribute :perform_caching
6
+ include Serializable
24
7
 
25
8
  class << self
26
- # set perform caching like root
27
- def cached(value = true)
28
- self.perform_caching = value
29
- end
9
+ attr_accessor :_root
10
+ alias root _root=
11
+ alias root= _root=
30
12
  end
31
13
 
32
14
  def initialize(object, options={})
33
- @object, @options = object, options
15
+ @object = object
16
+ @scope = options[:scope]
17
+ @root = options.fetch(:root, self.class._root)
18
+ @polymorphic = options.fetch(:polymorphic, false)
19
+ @meta_key = options[:meta_key] || :meta
20
+ @meta = options[@meta_key]
21
+ @each_serializer = options[:each_serializer]
22
+ @resource_name = options[:resource_name]
23
+ @only = options[:only] ? Array(options[:only]) : nil
24
+ @except = options[:except] ? Array(options[:except]) : nil
25
+ @namespace = options[:namespace]
26
+ @key_format = options[:key_format] || options[:each_serializer].try(:key_format)
34
27
  end
28
+ attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
35
29
 
36
- def meta_key
37
- @options[:meta_key].try(:to_sym) || :meta
38
- end
30
+ def json_key
31
+ key = root.nil? ? @resource_name : root
39
32
 
40
- def include_meta(hash)
41
- hash[meta_key] = @options[:meta] if @options.has_key?(:meta)
33
+ key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
42
34
  end
43
35
 
44
- def as_json(*args)
45
- @options[:hash] = hash = {}
46
- @options[:unique_values] = {}
47
-
48
- if root = @options[:root]
49
- hash.merge!(root => serializable_array)
50
- include_meta hash
51
- hash
52
- else
53
- serializable_array
54
- end
36
+ def serializer_for(item)
37
+ serializer_class = @each_serializer || Serializer.serializer_for(item, namespace: @namespace) || DefaultSerializer
38
+ serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except, polymorphic: @polymorphic, namespace: @namespace)
55
39
  end
56
40
 
57
- def to_json(*args)
58
- if perform_caching?
59
- cache.fetch expand_cache_key([self.class.to_s.underscore, cache_key, 'to-json']) do
60
- super
61
- end
62
- else
63
- super
41
+ def serializable_object(options={})
42
+ @object.map do |item|
43
+ serializer_for(item).serializable_object_with_notification(options)
64
44
  end
65
45
  end
66
-
67
- def serializable_array
68
- if perform_caching?
69
- cache.fetch expand_cache_key([self.class.to_s.underscore, cache_key, 'serializable-array']) do
70
- _serializable_array
46
+ alias_method :serializable_array, :serializable_object
47
+
48
+ def embedded_in_root_associations
49
+ @object.each_with_object({}) do |item, hash|
50
+ serializer_for(item).embedded_in_root_associations.each_pair do |type, objects|
51
+ next if !objects || objects.flatten.empty?
52
+
53
+ if hash.has_key?(type)
54
+ case hash[type] when Hash
55
+ hash[type].deep_merge!(objects){ |key, old, new| (Array(old) + Array(new)).uniq }
56
+ else
57
+ hash[type].concat(objects).uniq!
58
+ end
59
+ else
60
+ hash[type] = objects
61
+ end
71
62
  end
72
- else
73
- _serializable_array
74
63
  end
75
64
  end
76
65
 
77
66
  private
78
- def _serializable_array
79
- @object.map do |item|
80
- if @options.has_key? :each_serializer
81
- serializer = @options[:each_serializer]
82
- elsif item.respond_to?(:active_model_serializer)
83
- serializer = item.active_model_serializer
84
- end
85
-
86
- serializable = serializer ? serializer.new(item, @options) : DefaultSerializer.new(item, @options.merge(:root => false))
87
-
88
- if serializable.respond_to?(:serializable_hash)
89
- serializable.serializable_hash
90
- else
91
- serializable.as_json
92
- end
93
- end
94
- end
95
-
96
- def expand_cache_key(*args)
97
- ActiveSupport::Cache.expand_cache_key(args)
98
- end
99
67
 
100
- def perform_caching?
101
- perform_caching && cache && respond_to?(:cache_key)
68
+ def instrumentation_keys
69
+ [:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
102
70
  end
103
71
  end
104
72
  end
@@ -0,0 +1,32 @@
1
+ require 'active_model/serializable'
2
+
3
+ module ActiveModel
4
+ # DefaultSerializer
5
+ #
6
+ # Provides a constant interface for all items
7
+ class DefaultSerializer
8
+ include ActiveModel::Serializable
9
+
10
+ attr_reader :object
11
+
12
+ def initialize(object, options={})
13
+ @object = object
14
+ @wrap_in_array = options[:_wrap_in_array]
15
+ end
16
+
17
+ def as_json(options={})
18
+ instrument('!serialize') do
19
+ return [] if @object.nil? && @wrap_in_array
20
+ hash = @object.as_json
21
+ @wrap_in_array ? [hash] : hash
22
+ end
23
+ end
24
+ alias serializable_hash as_json
25
+ alias serializable_object as_json
26
+
27
+ private
28
+ def instrumentation_keys
29
+ [:object, :wrap_in_array]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module ActiveModel
2
+ module Serializable
3
+ module Utils
4
+ extend self
5
+
6
+ def _const_get(const)
7
+ begin
8
+ method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get
9
+ Object.send method, const
10
+ rescue NameError
11
+ const.safe_constantize
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_model/serializable/utils'
2
+
3
+ module ActiveModel
4
+ module Serializable
5
+ def self.included(base)
6
+ base.extend Utils
7
+ end
8
+
9
+ def as_json(options={})
10
+ instrument('!serialize') do
11
+ if root = options.fetch(:root, json_key)
12
+ hash = { root => serializable_object(options) }
13
+ hash.merge!(serializable_data)
14
+ hash
15
+ else
16
+ serializable_object(options)
17
+ end
18
+ end
19
+ end
20
+
21
+ def serializable_object_with_notification(options={})
22
+ instrument('!serialize') do
23
+ serializable_object(options)
24
+ end
25
+ end
26
+
27
+ def serializable_data
28
+ embedded_in_root_associations.tap do |hash|
29
+ if respond_to?(:meta) && meta
30
+ hash[meta_key] = meta
31
+ end
32
+ end
33
+ end
34
+
35
+ def namespace
36
+ get_namespace && Utils._const_get(get_namespace)
37
+ end
38
+
39
+ def embedded_in_root_associations
40
+ {}
41
+ end
42
+
43
+ private
44
+
45
+ def get_namespace
46
+ modules = self.class.name.split('::')
47
+ modules[0..-2].join('::') if modules.size > 1
48
+ end
49
+
50
+ def instrument(action, &block)
51
+ payload = instrumentation_keys.inject({ serializer: self.class.name }) do |payload, key|
52
+ payload[:payload] = self.instance_variable_get(:"@#{key}")
53
+ payload
54
+ end
55
+ ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
56
+ end
57
+
58
+ def instrumentation_keys
59
+ [:object, :scope, :root, :meta_key, :meta, :wrap_in_array, :only, :except, :key_format]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,39 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ class Association
4
+ class HasMany < Association
5
+ def initialize(name, *args)
6
+ super
7
+ @root_key = @embedded_key.to_s
8
+ @key ||= case CONFIG.default_key_type
9
+ when :name then name.to_s.pluralize
10
+ else "#{name.to_s.singularize}_ids"
11
+ end
12
+ end
13
+
14
+ def serializer_class(object, _)
15
+ if use_array_serializer?
16
+ ArraySerializer
17
+ else
18
+ serializer_from_options
19
+ end
20
+ end
21
+
22
+ def options
23
+ if use_array_serializer?
24
+ { each_serializer: serializer_from_options }.merge! super
25
+ else
26
+ super
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def use_array_serializer?
33
+ !serializer_from_options ||
34
+ serializer_from_options && !(serializer_from_options <= ArraySerializer)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,25 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ class Association
4
+ class HasOne < Association
5
+ def initialize(name, *args)
6
+ super
7
+ @root_key = @embedded_key.to_s.pluralize
8
+ @key ||= case CONFIG.default_key_type
9
+ when :name then name.to_s.singularize
10
+ else "#{name}_id"
11
+ end
12
+ end
13
+
14
+ def serializer_class(object, options = {})
15
+ serializer_from_options || serializer_from_object(object, options) || default_serializer
16
+ end
17
+
18
+ def build_serializer(object, options = {})
19
+ options[:_wrap_in_array] = embed_in_root?
20
+ super
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ require 'active_model/default_serializer'
2
+ require 'active_model/serializer/association/has_one'
3
+ require 'active_model/serializer/association/has_many'
4
+
5
+ module ActiveModel
6
+ class Serializer
7
+ class Association
8
+ def initialize(name, options={})
9
+ if options.has_key?(:include)
10
+ ActiveSupport::Deprecation.warn <<-WARN
11
+ ** Notice: include was renamed to embed_in_root. **
12
+ WARN
13
+ end
14
+
15
+ @name = name.to_s
16
+ @options = options
17
+ self.embed = options.fetch(:embed) { CONFIG.embed }
18
+ @polymorphic = options.fetch(:polymorphic, false)
19
+ @embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
20
+ @key_format = options.fetch(:key_format) { CONFIG.key_format }
21
+ @embed_key = options[:embed_key] || :id
22
+ @key = options[:key]
23
+ @embedded_key = options[:root] || name
24
+ @embed_in_root_key = options.fetch(:embed_in_root_key) { CONFIG.embed_in_root_key }
25
+ @embed_namespace = options.fetch(:embed_namespace) { CONFIG.embed_namespace }
26
+
27
+ serializer = @options[:serializer]
28
+ @serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
29
+ end
30
+
31
+ attr_reader :name, :embed_ids, :embed_objects, :polymorphic
32
+ attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
33
+ alias embed_ids? embed_ids
34
+ alias embed_objects? embed_objects
35
+ alias embed_in_root? embed_in_root
36
+ alias embed_in_root_key? embed_in_root_key
37
+ alias embed_namespace? embed_namespace
38
+ alias polymorphic? polymorphic
39
+
40
+ def embed=(embed)
41
+ @embed_ids = embed == :id || embed == :ids
42
+ @embed_objects = embed == :object || embed == :objects
43
+ end
44
+
45
+ def serializer_from_object(object, options = {})
46
+ Serializer.serializer_for(object, options)
47
+ end
48
+
49
+ def default_serializer
50
+ DefaultSerializer
51
+ end
52
+
53
+ def build_serializer(object, options = {})
54
+ serializer_class(object, options).new(object, options.merge(self.options))
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,31 @@
1
+ module ActiveModel
2
+ class Serializer
3
+ class Config
4
+ def initialize(data = {})
5
+ @data = data
6
+ end
7
+
8
+ def each(&block)
9
+ @data.each(&block)
10
+ end
11
+
12
+ def clear
13
+ @data.clear
14
+ end
15
+
16
+ def method_missing(name, *args)
17
+ name = name.to_s
18
+ return @data[name] if @data.include?(name)
19
+ match = name.match(/\A(.*?)([?=]?)\Z/)
20
+ case match[2]
21
+ when "="
22
+ @data[match[1]] = args.first
23
+ when "?"
24
+ !!@data[match[1]]
25
+ end
26
+ end
27
+ end
28
+
29
+ CONFIG = Config.new('embed' => :objects) # :nodoc:
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/resource/resource_generator'
3
+
4
+ module Rails
5
+ module Generators
6
+ class ResourceGenerator
7
+ def add_serializer
8
+ invoke 'serializer'
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,14 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
3
+
4
+ module Rails
5
+ module Generators
6
+ class ScaffoldControllerGenerator
7
+ if Rails::VERSION::MAJOR >= 4
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ hook_for :serializer, default: true
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,37 @@
1
+ module Rails
2
+ module Generators
3
+ class SerializerGenerator < NamedBase
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ check_class_collision suffix: 'Serializer'
6
+
7
+ argument :attributes, type: :array, default: [], banner: 'field:type field:type'
8
+
9
+ class_option :parent, type: :string, desc: 'The parent class for the generated serializer'
10
+
11
+ def create_serializer_file
12
+ template 'serializer.rb', File.join('app/serializers', class_path, "#{file_name}_serializer.rb")
13
+ end
14
+
15
+ private
16
+
17
+ def attributes_names
18
+ [:id] + attributes.select { |attr| !attr.reference? }.map { |a| a.name.to_sym }
19
+ end
20
+
21
+ def association_names
22
+ attributes.select { |attr| attr.reference? }.map { |a| a.name.to_sym }
23
+ end
24
+
25
+ def parent_class_name
26
+ if options[:parent]
27
+ options[:parent]
28
+ elsif (ns = Rails::Generators.namespace) && ns.const_defined?(:ApplicationSerializer) ||
29
+ (Object.const_get(:ApplicationSerializer) rescue nil)
30
+ 'ApplicationSerializer'
31
+ else
32
+ 'ActiveModel::Serializer'
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end