fast_serializer_ruby 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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.