fast_serializer_ruby 0.6.0 → 0.6.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 443a464f8f7d09a40c3457933896eaa35a27c841db28a259dd6fd95edbf2ddd1
4
- data.tar.gz: 1ab61528123941c2d6905795ca0c9f5bc95dab2982635300344b0eabdd3d62d6
3
+ metadata.gz: 4adafc96834175b06d1d49a72269b461f0d72419286a03e3c6422d145e027672
4
+ data.tar.gz: 5422eeac009a270dffbc56a7234b74da8c6a38eb56fbca9a66121f96ee129e3c
5
5
  SHA512:
6
- metadata.gz: cbe8efbf120d930648abb69eca0b541ffe73181a2f63b1f0e0b4132506fb699e7a3b7007cf1f5c2e97415ef3936539222c282d7ea8766214b4a69e5c73b5d4b9
7
- data.tar.gz: 8f66f7174aa206a31c1b7885c2e1f2deae54fe882870db55017bef74363cae428bc8e14d20fcd925cca9cedb8041ef10349672a21feaf279a97577e4932d9cdb
6
+ metadata.gz: b6571bed32c87ef3dacb6ad00a6d0054aa547f8afe4f196b1a9186d6d6eedc649aaa81c8f22a72114e74547a9ec8d61a9df0229415ff92370a58c06e3ad3c91b
7
+ data.tar.gz: 0567dc3d3513358831e4571833daeb941ebc94660d945240038669e3f2c20deedb99d16337055336b88afe1110b6061800b994ab7fe8f6a40ef54cfd1bfa6c06
data/.gitignore CHANGED
@@ -13,3 +13,5 @@
13
13
  .rspec_status
14
14
  .rspec
15
15
  .history
16
+ /.vscode
17
+ .rubocop.yml
data/Gemfile CHANGED
@@ -6,8 +6,8 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
7
  gemspec
8
8
 
9
- group :development do
10
- gem 'pry-byebug', '~> 3.7.0'
9
+ group :development, :test do
10
+ gem 'rake'
11
11
  gem 'pry'
12
12
  end
13
13
 
@@ -15,6 +15,7 @@ group :test do
15
15
  gem 'active_model_serializers', '~> 0.10.0'
16
16
  gem 'factory_bot'
17
17
  gem 'faker'
18
+ gem 'activesupport', '< 6'
18
19
  gem 'allocation_stats'
19
20
  gem 'simplecov', '~> 0.17.1'
20
21
  gem 'benchmark-memory', '~> 0.1'
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fast_serializer_ruby (0.6.0)
4
+ fast_serializer_ruby (0.6.2)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -32,28 +32,29 @@ GEM
32
32
  minitest (~> 5.1)
33
33
  tzinfo (~> 1.1)
34
34
  allocation_stats (0.1.5)
35
- benchmark-malloc (0.1.0)
35
+ benchmark-malloc (0.2.0)
36
36
  benchmark-memory (0.1.2)
37
37
  memory_profiler (~> 0.9)
38
- benchmark-perf (0.5.0)
39
- benchmark-trend (0.3.0)
38
+ benchmark-perf (0.6.0)
39
+ benchmark-trend (0.4.0)
40
40
  builder (3.2.4)
41
- byebug (11.0.1)
42
41
  case_transform (0.2)
43
42
  activesupport
44
43
  coderay (1.1.2)
45
- concurrent-ruby (1.1.5)
44
+ concurrent-ruby (1.1.6)
46
45
  crass (1.0.6)
47
46
  diff-lcs (1.3)
48
47
  docile (1.3.2)
49
48
  erubi (1.9.0)
50
49
  factory_bot (5.1.1)
51
50
  activesupport (>= 4.2.0)
52
- faker (2.10.1)
51
+ faker (2.10.2)
53
52
  i18n (>= 1.6, < 2)
53
+ ffi (1.12.2-java)
54
54
  i18n (1.8.2)
55
55
  concurrent-ruby (~> 1.0)
56
56
  json (2.3.0)
57
+ json (2.3.0-java)
57
58
  jsonapi-renderer (0.2.2)
58
59
  loofah (2.4.0)
59
60
  crass (~> 1.0.2)
@@ -62,15 +63,17 @@ GEM
62
63
  method_source (0.9.2)
63
64
  mini_portile2 (2.4.0)
64
65
  minitest (5.14.0)
65
- nokogiri (1.10.7)
66
+ nokogiri (1.10.9)
66
67
  mini_portile2 (~> 2.4.0)
68
+ nokogiri (1.10.9-java)
67
69
  pry (0.12.2)
68
70
  coderay (~> 1.1.0)
69
71
  method_source (~> 0.9.0)
70
- pry-byebug (3.7.0)
71
- byebug (~> 11.0)
72
- pry (~> 0.10)
73
- rack (2.1.2)
72
+ pry (0.12.2-java)
73
+ coderay (~> 1.1.0)
74
+ method_source (~> 0.9.0)
75
+ spoon (~> 0.0)
76
+ rack (2.2.2)
74
77
  rack-test (1.1.0)
75
78
  rack (>= 1.0, < 3)
76
79
  rails-dom-testing (2.0.3)
@@ -78,18 +81,19 @@ GEM
78
81
  nokogiri (>= 1.6)
79
82
  rails-html-sanitizer (1.3.0)
80
83
  loofah (~> 2.3)
84
+ rake (13.0.1)
81
85
  rspec (3.9.0)
82
86
  rspec-core (~> 3.9.0)
83
87
  rspec-expectations (~> 3.9.0)
84
88
  rspec-mocks (~> 3.9.0)
85
- rspec-benchmark (0.5.1)
86
- benchmark-malloc (~> 0.1.0)
87
- benchmark-perf (~> 0.5.0)
88
- benchmark-trend (~> 0.3.0)
89
- rspec (>= 3.0.0, < 4.0.0)
89
+ rspec-benchmark (0.6.0)
90
+ benchmark-malloc (~> 0.2)
91
+ benchmark-perf (~> 0.6)
92
+ benchmark-trend (~> 0.4)
93
+ rspec (>= 3.0)
90
94
  rspec-core (3.9.1)
91
95
  rspec-support (~> 3.9.1)
92
- rspec-expectations (3.9.0)
96
+ rspec-expectations (3.9.1)
93
97
  diff-lcs (>= 1.2.0, < 2.0)
94
98
  rspec-support (~> 3.9.0)
95
99
  rspec-mocks (3.9.1)
@@ -101,22 +105,27 @@ GEM
101
105
  json (>= 1.8, < 3)
102
106
  simplecov-html (~> 0.10.0)
103
107
  simplecov-html (0.10.2)
108
+ spoon (0.0.6)
109
+ ffi
104
110
  thread_safe (0.3.6)
111
+ thread_safe (0.3.6-java)
105
112
  tzinfo (1.2.6)
106
113
  thread_safe (~> 0.1)
107
114
 
108
115
  PLATFORMS
116
+ java
109
117
  ruby
110
118
 
111
119
  DEPENDENCIES
112
120
  active_model_serializers (~> 0.10.0)
121
+ activesupport (< 6)
113
122
  allocation_stats
114
123
  benchmark-memory (~> 0.1)
115
124
  factory_bot
116
125
  faker
117
126
  fast_serializer_ruby!
118
127
  pry
119
- pry-byebug (~> 3.7.0)
128
+ rake
120
129
  rspec (~> 3.0)
121
130
  rspec-benchmark
122
131
  simplecov (~> 0.17.1)
data/README.md CHANGED
@@ -9,9 +9,9 @@
9
9
  This library intends to solve such a typical and on the other hand important problem as efficient ruby object to hash transformation.
10
10
 
11
11
  ## Performance 🚀
12
- - running on ruby 2.6 is **at least 5 times faster** than AMS (benchmarks was borrowed from fast_jsonapi repository)
13
- - running on ruby 2.6 it consumes **3 times less RAM**
14
- - running on jruby 9.2.7.0 **is at least 15 times faster** than AMS after warming up
12
+ - running on ruby 2.7 is **at least 6 times faster** than AMS (benchmarks was borrowed from fast_jsonapi repository)
13
+ - running on ruby 2.7 it consumes **6 times less RAM**
14
+ - running on jruby 9.2.7.0 **is at least 4 times faster** than AMS after warming up
15
15
 
16
16
  ## Compatibility 👌
17
17
  I tried to keep the API as close as possible to active_model_serializer implementation because we all got used to it.
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
34
34
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{(test|spec|features|git|rspec|travis)/}) }
35
35
  end
36
+
36
37
  spec.bindir = 'bin'
37
38
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
39
  spec.require_paths = ['lib']
@@ -4,35 +4,26 @@ require 'json'
4
4
 
5
5
  module FastSerializer
6
6
  class Configuration
7
-
8
- RubyVer = Struct.new(:major, :feature, :fix) do
9
-
10
- def is_2_4_or_less
11
- major == 2 && feature <= 4
12
- end
13
- end
14
-
15
- attr_reader :coder, :ruby_ver
7
+ attr_reader :coder
16
8
  attr_accessor :strict
17
9
 
18
10
  def initialize
19
11
  @coder = JSON
20
12
  @strict = false
21
- @ruby_ver = RubyVer.new(*RUBY_VERSION.split(".").map(&:to_i))
22
13
  end
23
14
 
24
15
  def coder=(obj)
25
- if obj.respond_to?(:dump) && obj.respond_to?(:load)
26
- @coder = obj
27
- else
28
- raise ArgumentError, "must respond to #load and #dump methods"
16
+ unless obj.respond_to?(:dump) && obj.respond_to?(:load)
17
+ raise ArgumentError, 'must respond to #load and #dump methods'
29
18
  end
19
+
20
+ @coder = obj
30
21
  end
31
22
  end
32
23
 
33
24
  class << self
34
25
  def config
35
- @_config ||= Configuration.new
26
+ @config ||= Configuration.new
36
27
  end
37
28
 
38
29
  def configure(&block)
@@ -3,6 +3,10 @@
3
3
  module FastSerializer
4
4
  module JsonModel
5
5
  class Array < Relationship
6
+ # @param resource [Object]
7
+ # @param params [Hash]
8
+ # @param context [Hash]
9
+ # @return [Array]
6
10
  def serialize(resources, params, context)
7
11
  return if resources.nil?
8
12
 
@@ -11,8 +11,9 @@ module FastSerializer
11
11
  :cond_method_name,
12
12
  :injected
13
13
 
14
- def initialize(_)
14
+ def initialize(*)
15
15
  super
16
+
16
17
  @mixin = nil
17
18
  @method_name = nil
18
19
  @injected = false
@@ -20,32 +21,8 @@ module FastSerializer
20
21
  @cond = nil
21
22
  @cond = @opts[:if] || @opts[:unless] || @cond
22
23
 
23
- if method.is_a?(Proc)
24
- @method_name = "__#{key}__"
25
- @method_arity = method.arity.abs
26
- @mixin = Module.new
27
-
28
- if FastSerializer.config.ruby_ver.is_2_4_or_less
29
- @mixin.redefine_method @method_name, &method
30
- else
31
- @mixin.define_method @method_name, &method
32
- end
33
-
34
- end
35
-
36
- if !cond.nil? && cond.is_a?(Proc)
37
- @cond_method_name = "__#{key}_cond__"
38
- @cond_arity = cond.arity.abs
39
- @mixin ||= Module.new
40
-
41
- if FastSerializer.config.ruby_ver.is_2_4_or_less
42
- @mixin.redefine_method @cond_method_name, &cond
43
- else
44
- @mixin.define_method @cond_method_name, &cond
45
- end
46
-
47
- end
48
-
24
+ init_with_proc if method.is_a?(Proc)
25
+ init_with_cond if !cond.nil? && cond.is_a?(Proc)
49
26
  end
50
27
 
51
28
  def injectable?
@@ -57,32 +34,39 @@ module FastSerializer
57
34
  self.injected = true
58
35
  end
59
36
 
37
+ # @param resource [Object]
38
+ # @param params [Hash]
39
+ # @param context [Hash]
40
+ # @return [Object]
60
41
  def serialize(resource, params, context)
42
+ can_execute_on_mixin = injected && !method_name.nil? && !context.nil?
61
43
 
62
- val = if injected && !method_name.nil? && !context.nil?
63
- call_method_on_context(context, method_name, method_arity, resource, params)
64
-
65
- elsif method.is_a?(Proc)
66
- call_proc_binding_to_context(context, method, method_arity, resource, params)
67
-
68
- else
69
- resource.public_send(method)
70
- end
44
+ val = if can_execute_on_mixin
45
+ call_method_on_context(context, method_name, method_arity, resource, params)
46
+ elsif method.is_a?(Proc)
47
+ call_proc_binding_to_context(context, method, method_arity, resource, params)
48
+ else
49
+ resource.public_send(method)
50
+ end
71
51
 
72
52
  val.freeze
73
53
 
74
54
  val
75
55
  end
76
56
 
57
+ # @param resource [Object]
58
+ # @param params [Hash]
59
+ # @param context [Hash]
60
+ # @return [Boolean]
77
61
  def included?(resource, params, context)
78
62
  return true if cond.nil?
79
63
 
80
- res = if injected && !cond_method_name.nil? && !context.nil?
81
- call_method_on_context(context, cond_method_name, cond_arity, resource, params)
64
+ can_execute_on_mixin = injected && !cond_method_name.nil? && !context.nil?
82
65
 
66
+ res = if can_execute_on_mixin
67
+ call_method_on_context(context, cond_method_name, cond_arity, resource, params)
83
68
  elsif cond.is_a?(Proc)
84
69
  call_proc_binding_to_context(context, cond, cond_arity, resource, params)
85
-
86
70
  else
87
71
  context.public_send(cond)
88
72
  end
@@ -94,6 +78,30 @@ module FastSerializer
94
78
 
95
79
  private
96
80
 
81
+ def init_with_cond
82
+ @cond_method_name = "__#{key}_cond__"
83
+ @cond_arity = cond.arity.abs
84
+ @mixin ||= Module.new
85
+
86
+ if RUBY_VERSION <= '2.5.0'
87
+ @mixin.redefine_method @cond_method_name, &cond
88
+ else
89
+ @mixin.define_method @cond_method_name, &cond
90
+ end
91
+ end
92
+
93
+ def init_with_proc
94
+ @method_name = "__#{key}__"
95
+ @method_arity = method.arity.abs
96
+ @mixin = Module.new
97
+
98
+ if RUBY_VERSION <= '2.5.0'
99
+ @mixin.redefine_method @method_name, &method
100
+ else
101
+ @mixin.define_method @method_name, &method
102
+ end
103
+ end
104
+
97
105
  def call_proc_binding_to_context(context, prc, arity, resource, params)
98
106
  case arity
99
107
  when 1
@@ -3,16 +3,18 @@
3
3
  module FastSerializer
4
4
  module JsonModel
5
5
  class HasManyRelationship < Relationship
6
- def serialize(resource, params, context)
6
+ # @param resource [Object]
7
+ # @param params [Hash]
8
+ # @return [Array<Hash>]
9
+ def serialize(resource, params, _context)
7
10
  collection = resource.public_send(method)
8
11
  return if collection.nil?
9
12
 
10
13
  if @serializer_klass
11
14
  @serializer_klass.new(collection, params).serializable_hash
12
15
  elsif @schema
13
- collection.map { |resource| @schema.serialize_resource(resource, params) }
16
+ collection.map { |entry| @schema.serialize_resource(entry, params) }
14
17
  end
15
-
16
18
  end
17
19
  end
18
20
  end
@@ -3,7 +3,10 @@
3
3
  module FastSerializer
4
4
  module JsonModel
5
5
  class HasOneRelationship < Relationship
6
- def serialize(resource, params, context)
6
+ # @param resource [Object]
7
+ # @param params [Hash]
8
+ # @return [Hash]
9
+ def serialize(resource, params, _)
7
10
  relation = resource.public_send(method)
8
11
 
9
12
  if @serializer_klass
@@ -5,21 +5,25 @@ module FastSerializer
5
5
  class Node
6
6
  attr_accessor :key, :method, :context
7
7
 
8
+ # @param key [String]
9
+ # @param method [String]
10
+ # @param opts [Hash]
8
11
  def initialize(key: nil, method: nil, opts: {}, **_)
9
12
  @key = key&.to_sym
10
13
  @method = method || key
11
14
  @opts = opts || {}
12
15
  end
13
16
 
17
+ # @return [Boolean]
14
18
  def injectable?
15
19
  false
16
20
  end
17
21
 
18
- def serialize(_resource, _params, context = nil)
22
+ def serialize(_resource, _params, _context = nil)
19
23
  raise NotImplementedError
20
24
  end
21
25
 
22
- def included?(_resource, _params, context = nil)
26
+ def included?(_resource, _params, _context = nil)
23
27
  raise NotImplementedError
24
28
  end
25
29
  end
@@ -10,23 +10,31 @@ module FastSerializer
10
10
  @attributes = {}
11
11
  end
12
12
 
13
+ # @param attribute [FastSerializer::JsonModel::Node]
13
14
  def add_attribute(attribute)
14
15
  attributes[attribute.key] = attribute
15
16
  end
16
17
 
18
+ # @param resource [Object]
19
+ # @param params [Hash]
20
+ # @param context [Hash]
21
+ # @return [Hash]
17
22
  def serialize(resource, params, context)
18
23
  return if resource.nil?
19
24
 
20
- res = attributes.values.each_with_object({}) do |attribute, res|
21
- next res unless attribute.included?(resource, params, context)
25
+ result = {}
26
+
27
+ attributes.each do |_, attribute|
28
+ next unless attribute.included?(resource, params, context)
22
29
 
23
30
  val = attribute.serialize(resource, params, context)
24
- res[attribute.key] = val
31
+ result[attribute.key] = val
25
32
  end
26
33
 
27
- res
34
+ result
28
35
  end
29
36
 
37
+ # @return [Boolean]
30
38
  def included?(*)
31
39
  true
32
40
  end
@@ -5,32 +5,49 @@ module FastSerializer
5
5
  class Relationship < Attribute
6
6
  attr_accessor :serialization_schema
7
7
 
8
- def initialize(key: nil, method: nil, opts: {}, serializer: nil, schema: nil, strict: false)
8
+ # @param serializer [FastSerializer::Schema::Mixin]
9
+ # @param schema [FastSerializer::Schema]
10
+ def initialize(serializer: nil, schema: nil, **)
9
11
  super
12
+
10
13
  @serializer_klass = serializer
11
14
  @schema = schema
12
15
 
13
- raise ArgumentError, "must provide serializer or schema" if @serializer_klass.nil? && @schema.nil?
16
+ if @serializer_klass.nil? && @schema.nil?
17
+ raise ArgumentError, 'must provide serializer or schema'
18
+ end
14
19
  end
15
20
 
21
+ # @param resource [Object]
22
+ # @param params [Hash]
23
+ # @param context [Hash]
24
+ # @return [Boolean]
16
25
  def included?(resource, params, context)
17
26
  super && include_relation?(params)
18
27
  end
19
28
 
29
+ # @param params [Hash]
30
+ # @return [Boolean]
20
31
  def include_relation?(params)
21
32
  include?(params) && !exclude?(params)
22
33
  end
23
34
 
35
+ # @param params [Hash]
36
+ # @return [Boolean]
24
37
  def exclude?(params)
25
38
  return false if params[:exclude].nil?
26
39
  return false if params[:exclude].empty?
40
+
27
41
  params[:exclude_index].key?(key)
28
42
  end
29
43
 
44
+ # @param params [Hash]
45
+ # @return [Boolean]
30
46
  def include?(params)
31
47
  return true if params[:include].nil?
32
48
  return false if params[:include].empty?
33
- params[:include_index].has_key?(key)
49
+
50
+ params[:include_index].key?(key)
34
51
  end
35
52
  end
36
53
  end
@@ -3,13 +3,9 @@
3
3
  require 'forwardable'
4
4
 
5
5
  module FastSerializer
6
-
7
6
  class Schema
8
-
9
7
  attr_reader :_root, :serialization_schema, :params, :strict
10
8
 
11
- public
12
-
13
9
  def initialize(params = {}, root = nil, strict = nil)
14
10
  @root = root
15
11
  @strict = strict || FastSerializer.config.strict
@@ -24,79 +20,98 @@ module FastSerializer
24
20
  end
25
21
 
26
22
  def include=(list)
27
- return if !list
23
+ return unless list
24
+ return if list.empty?
28
25
 
29
- if list.any?
30
- @params[:include] = list.map(&:to_sym)
31
- @params[:include_index] = @params[:include].map { |key| [key, nil] }.to_h
32
- end
26
+ @params[:include] = list.map(&:to_sym)
27
+ @params[:include_index] = @params[:include].map { |key| [key, nil] }.to_h
33
28
  end
34
29
 
35
30
  def exclude=(list)
36
- return if !list
31
+ return unless list
32
+ return if list.empty?
37
33
 
38
- if list.any?
39
- @params[:exclude] = list.map(&:to_sym)
40
- @params[:exclude_index] = @params[:exclude].map { |key| [key, nil] }.to_h
41
- end
34
+ @params[:exclude] = list.map(&:to_sym)
35
+ @params[:exclude_index] = @params[:exclude].map { |key| [key, nil] }.to_h
42
36
  end
43
37
 
44
- # @param [Array] attribute_names
38
+ # Defines a list of attributes for serialization
39
+ #
40
+ # @param attribute_names [Array<String, Symbol>] a list of attributes to serialize
41
+ # each of these attributes value is fetched calling a corresponding method from a resource instance
42
+ # passed to the serializer
45
43
  def attributes(*attribute_names)
46
44
  attribute_names.each do |attribute_name|
47
- serialization_schema.add_attribute JsonModel::Attribute.new(
48
- key: attribute_name,
49
- method: attribute_name,
45
+ serialization_schema.add_attribute(
46
+ JsonModel::Attribute.new(key: attribute_name, method: attribute_name)
50
47
  )
51
48
  end
52
49
  end
53
50
 
54
- # @param [String] attribute_name
55
- # @param [Hash] opts - attribute options
56
- # @param [Proc] block - result is used as the attribute value
51
+ # Defines an attribute for serialization
52
+ #
53
+ # @param attribute_name [String, Symbol] an attribute name
54
+ # @param opts [Hash] attribute options
55
+ # @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
56
+ # @option opts [Proc] :unless (see opts:if)
57
+ # @param block [Proc] result is used as the attribute value
58
+ #
57
59
  def attribute(attribute_name, opts = {}, &block)
58
- serialization_schema.add_attribute JsonModel::Attribute.new(
59
- key: attribute_name,
60
- method: block,
61
- opts: opts,
60
+ serialization_schema.add_attribute(
61
+ JsonModel::Attribute.new(
62
+ key: attribute_name,
63
+ method: block,
64
+ opts: opts
65
+ )
62
66
  )
63
67
  end
64
68
 
65
- # @param [String] attribute_name
66
- # @param [Hash] opts - attribute options
69
+ # Defines an attribute for serialization
70
+ #
71
+ # @param attribute_name [String, Symbol] an attribute name
72
+ # @param opts [Hash] attribute options
73
+ # @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
74
+ # @option opts [Proc] :unless (see opts:if)
75
+ # @option opts [FastSerializer::Schema::Mixin, nil] :serializer a serializer class with injected module or a inherited class
76
+ # @option opts [FastSerializer::Schema] :schema
77
+ #
67
78
  def has_one(attribute_name, opts = {})
68
79
  serialization_schema.add_attribute JsonModel::HasOneRelationship.new(
69
- key: opts.delete(:key) || attribute_name,
70
- method: opts.delete(:method) || attribute_name,
71
- opts: opts,
72
- schema: opts.delete(:schema),
73
- serializer: opts.delete(:serializer),
80
+ key: opts.delete(:key) || attribute_name,
81
+ method: opts.delete(:method) || attribute_name,
82
+ opts: opts,
83
+ schema: opts.delete(:schema),
84
+ serializer: opts.delete(:serializer)
74
85
  )
75
86
  end
76
87
 
77
88
  alias belongs_to has_one
78
89
 
79
- # @param [String] attribute_name
80
- # @param [Hash] opts - attribute options
90
+ # @param attribute_name [String]
91
+ # @param opts [Hash] attribute options
81
92
  def has_many(attribute_name, opts = {})
82
- serialization_schema.add_attribute JsonModel::HasManyRelationship.new(
83
- key: opts.delete(:key) || attribute_name,
84
- method: opts.delete(:method) || attribute_name,
85
- opts: opts,
86
- schema: opts.delete(:schema),
87
- serializer: opts.delete(:serializer),
93
+ serialization_schema.add_attribute(
94
+ JsonModel::HasManyRelationship.new(
95
+ key: opts.delete(:key) || attribute_name,
96
+ method: opts.delete(:method) || attribute_name,
97
+ opts: opts,
98
+ schema: opts.delete(:schema),
99
+ serializer: opts.delete(:serializer)
100
+ )
88
101
  )
89
102
  end
90
103
 
91
104
  # @param [String] attribute_name
92
105
  # @param [Hash] opts - attribute options
93
106
  def list(attribute_name, opts = {})
94
- serialization_schema.add_attribute JsonModel::Array.new(
95
- key: attribute_name,
96
- method: attribute_name,
97
- opts: opts,
98
- schema: opts.delete(:schema),
99
- serializer: opts.delete(:serializer),
107
+ serialization_schema.add_attribute(
108
+ JsonModel::Array.new(
109
+ key: attribute_name,
110
+ method: attribute_name,
111
+ opts: opts,
112
+ schema: opts.delete(:schema),
113
+ serializer: opts.delete(:serializer)
114
+ )
100
115
  )
101
116
  end
102
117
 
@@ -116,11 +131,15 @@ module FastSerializer
116
131
  end
117
132
 
118
133
  def serialize_resource(resource, params = {}, context = self)
119
- _params_dup = FastSerializer::Utils.symbolize_keys(self.params.merge(params))
134
+ Utils.ref_merge(self.params, params)
135
+ _params_dup = FastSerializer::Utils.symbolize_keys(self.params)
120
136
  meta = _params_dup.delete(:meta)
121
137
 
122
- is_collection = resource.respond_to?(:size) && !resource.respond_to?(:each_pair)
123
- is_collection = params.delete(:is_collection) if params.has_key?(:is_collection)
138
+ is_collection = if params.key?(:is_collection)
139
+ params.delete(:is_collection)
140
+ else
141
+ resource.respond_to?(:size) && !resource.respond_to?(:each_pair)
142
+ end
124
143
 
125
144
  root = (_root || _params_dup.delete(:root))
126
145
 
@@ -139,7 +158,7 @@ module FastSerializer
139
158
 
140
159
  end
141
160
 
142
- res = { root => res } if root && !root.empty?
161
+ res = { root => res } if root && !root.empty?
143
162
 
144
163
  res[:meta] = meta if res.is_a?(Hash) && meta
145
164
 
@@ -1,12 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FastSerializer
2
4
  class Schema
3
5
  module Mixin
4
-
5
6
  module ClassMethods
6
7
  attr_accessor :__schema__, :__patched__
7
8
 
8
9
  def inherited(subclass)
9
- subclass.__schema__ = self.__schema__.deep_copy
10
+ subclass.__schema__ = __schema__.deep_copy
10
11
  end
11
12
 
12
13
  def method_missing(method, *args, &block)
@@ -16,6 +17,18 @@ module FastSerializer
16
17
  super
17
18
  end
18
19
  end
20
+
21
+ def respond_to_missing?(method_name, include_private = false)
22
+ __schema__.respond_to?(method_name) || super
23
+ end
24
+
25
+ def __patch_with_attribute_definition
26
+ injectable_attributes = __schema__.serialization_schema.attributes.select { |_key, attribute| attribute.injectable? }
27
+ injectable_attributes.each { |_, attribute| attribute.inject(self) }
28
+ self.__patched__ = true
29
+
30
+ __patched__.freeze
31
+ end
19
32
  end
20
33
 
21
34
  module InstanceMethods
@@ -26,16 +39,14 @@ module FastSerializer
26
39
  self.params = params || {}
27
40
  end
28
41
 
29
- alias_method :object, :resource
42
+ alias object resource
30
43
 
31
44
  def serializable_hash(opts = {})
32
- self.params = params.merge(opts)
45
+ Utils.ref_merge(params, opts)
46
+ self.params = params
33
47
 
34
- if !self.class.__patched__
35
- injectable_attributes = self.class.__schema__.serialization_schema.attributes.select { |key, attribute| attribute.injectable? }
36
- injectable_attributes.each { |key, attribute| attribute.inject(self.class) }
37
- self.class.__patched__ = true
38
- self.class.__patched__.freeze
48
+ unless self.class.__patched__
49
+ self.class.__patch_with_attribute_definition
39
50
  end
40
51
 
41
52
  self.class.__schema__.serialize_resource(resource, params, self)
@@ -57,4 +68,4 @@ module FastSerializer
57
68
  end
58
69
  end
59
70
  end
60
- end
71
+ end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FastSerializer
2
4
  module Utils
3
5
  def self.symbolize_keys(hash)
4
6
  res = {}
5
- hash.each { |key, _| res[key.to_sym] = hash[key] }
7
+ hash.each { |key, value| res[key.to_sym] = value }
6
8
  hash
7
9
  end
10
+
11
+ def self.ref_merge(hash_a, hash_b)
12
+ hash_b.each do |key, value|
13
+ hash_a[key] = value
14
+ end
15
+ end
8
16
  end
9
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FastSerializer
4
- VERSION = '0.6.0'
4
+ VERSION = '0.6.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_serializer_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgeny Stepanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-01 00:00:00.000000000 Z
11
+ date: 2020-03-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This library intends to solve such a typical and on the other hand important
14
14
  problem as efficient ruby object to hash transformation.
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
66
  - !ruby/object:Gem::Version
67
67
  version: '0'
68
68
  requirements: []
69
- rubygems_version: 3.0.4
69
+ rubygems_version: 3.1.2
70
70
  signing_key:
71
71
  specification_version: 4
72
72
  summary: fast_serializer is a lightweight ruby objects serializer.