sinclair 1.12.0 → 1.13.0

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: 1a194ca690bacbcb4a928dc5295a60f6e574b6cf567cc81ab33a293dbe9d3643
4
- data.tar.gz: 77d34d971fee05045d57e73939a0a299707cad027bb770c09e348ca35fb76bce
3
+ metadata.gz: 46b430c9db3658979d128e45ecbbb03aab30bb993d8651ecc8cc3bd9fe1b18e3
4
+ data.tar.gz: fa78aa3bde540b7f90675566086e65d884cea51b2874b6cd5166ffc50018ab73
5
5
  SHA512:
6
- metadata.gz: aa8cc30f12639711e53e3e2396fa59075ea59673fb49469be8ad757f8502b75ed07df9b57a0a4c863dd0067b1cd655455bdf649189318d04a71f8c758af7c7d5
7
- data.tar.gz: 29942c828c7621d728307f16731fbc5ac715371512e35a8872d9f6102b07c54256a4571e0324cc82e69703d7b75a6ce87b2658ff26ef54886b69bc0d15a3f6ec
6
+ metadata.gz: 9a290bcea44d39854bd7b8bd99b28c18d0a6c827b31f140fb339b82d49a9add6e505f738b4925b27c25ddedd695d06963a4221c55ff9b869157aaec5753a5747
7
+ data.tar.gz: dfdc3723b6a6d31611eceb727007680aafc3f56d9cda1e16922768df7e9ce14238d0c982ff7e4232a914015c8d22850b869ab08601b8121727ce0673c43ca10b
data/.rubocop.yml CHANGED
@@ -4,7 +4,6 @@ inherit_from: .rubocop_todo.yml
4
4
  AllCops:
5
5
  TargetRubyVersion: 2.5
6
6
 
7
-
8
7
  RSpec/DescribeClass:
9
8
  Exclude:
10
9
  - 'spec/integration/yard/**/*_spec.rb'
data/README.md CHANGED
@@ -13,13 +13,13 @@ This gem helps the creation of complex gems/concerns
13
13
  that enables creation of methods on the fly through class
14
14
  methods
15
15
 
16
- Current Release: [1.12.0](https://github.com/darthjee/sinclair/tree/1.12.0)
16
+ Current Release: [1.13.0](https://github.com/darthjee/sinclair/tree/1.13.0)
17
17
 
18
- [Next release](https://github.com/darthjee/sinclair/compare/1.12.0...master)
18
+ [Next release](https://github.com/darthjee/sinclair/compare/1.13.0...master)
19
19
 
20
20
  Yard Documentation
21
21
  -------------------
22
- [https://www.rubydoc.info/gems/sinclair/1.12.0](https://www.rubydoc.info/gems/sinclair/1.12.0)
22
+ [https://www.rubydoc.info/gems/sinclair/1.13.0](https://www.rubydoc.info/gems/sinclair/1.13.0)
23
23
 
24
24
  Installation
25
25
  ---------------
@@ -616,6 +616,44 @@ model1 == model2 # returns true
616
616
  ```
617
617
  </details>
618
618
 
619
+ ### Sinclair::Model
620
+ Model class for quickly creation of plain simple classes/models
621
+
622
+ When creating a model class, options can be passed
623
+ - writter: Adds writter/setter methods (defaults to true)
624
+ - comparable: Adds the fields when running a `==` method (defaults to true)
625
+
626
+ <details>
627
+ <summary>Example of simple usage</summary>
628
+
629
+ ```ruby
630
+ class Human < Sinclair::Model.for(:name, :age, { gender: :undefined }, **{})
631
+ end
632
+
633
+ human1 = Human.new(name: 'John Doe', age: 22)
634
+ human2 = Human.new(name: 'John Doe', age: 22)
635
+
636
+ human1.name # returns 'John Doe'
637
+ human1.age # returns 22
638
+ human1.gender # returns :undefined
639
+ human1 == human2 # returns true
640
+ ```
641
+ </details>
642
+
643
+ <details>
644
+ <summary>Example with options</summary>
645
+
646
+ ```ruby
647
+ class Tv < Sinclair::Model.for(:model, writter: false, comparable: false)
648
+ end
649
+
650
+ tv1 = Tv.new(model: 'Sans Sunga Xt')
651
+ tv2 = Tv.new(model: 'Sans Sunga Xt')
652
+
653
+ tv1 == tv2 # returns false
654
+ ```
655
+ </details>
656
+
619
657
  RSspec matcher
620
658
  ---------------
621
659
 
@@ -1,4 +1,5 @@
1
1
  ignore:
2
+ - lib/sinclair/model/builder.rb
2
3
  - lib/sinclair/comparable/class_methods.rb
3
4
  - lib/sinclair/exception.rb
4
5
  - lib/sinclair/matchers/add_method.rb
@@ -6,5 +7,4 @@ ignore:
6
7
  - lib/sinclair/matchers/base.rb
7
8
  - lib/sinclair/matchers/change_method_on.rb
8
9
  - lib/sinclair/matchers/method_to.rb
9
- - lib/sinclair/method_definition/parameter_helper.rb
10
10
  - lib/sinclair/version.rb
data/config/yardstick.yml CHANGED
@@ -29,6 +29,7 @@ rules:
29
29
  - Sinclair::Matchers#add_class_method
30
30
  - Sinclair::Matchers#change_method
31
31
  - Sinclair::Matchers#change_class_method
32
+ - Sinclair::Model.for
32
33
  ReturnTag:
33
34
  enabled: true
34
35
  exclude:
@@ -63,6 +64,7 @@ rules:
63
64
  - Sinclair::MethodDefinition::ParameterBuilder#initialize
64
65
  - Sinclair::MethodDefinition::ParameterHelper#initialize
65
66
  - Sinclair::MethodDefinition::StringDefinition#initialize
67
+ - Sinclair::Model::Builder#initialize
66
68
  - Sinclair::Options#initialize
67
69
  - Sinclair::Options::Builder#initialize
68
70
  Summary::Length:
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api public
4
+ # @author darthjee
5
+ #
6
+ # Extension to core class Object
7
+ class Object
8
+ # rubocop:disable Naming/PredicateName
9
+
10
+ # @api public
11
+ # Checks if an object is an instance of any of the given classes
12
+ #
13
+ # @param classes [Array<Class>] classes to be checked against object
14
+ #
15
+ # @example
16
+ # object = [1, 2, 3]
17
+ #
18
+ # object.is_any?(Hash, Class) # returns false
19
+ # object.is_any?(Hash, Array) # returns true
20
+ #
21
+ # @return [TrueClass,FalseClass]
22
+ def is_any?(*classes)
23
+ classes.any?(method(:is_a?))
24
+ end
25
+ # rubocop:enable Naming/PredicateName
26
+ end
@@ -45,6 +45,7 @@ class Sinclair
45
45
 
46
46
  private
47
47
 
48
+ delegate :value_string, to: Stringifier
48
49
  attr_reader :parameters_list, :named
49
50
  alias named? named
50
51
 
@@ -114,11 +115,29 @@ class Sinclair
114
115
  #
115
116
  # @return [Array<String>]
116
117
  def defaults_strings
117
- joinner = named? ? ': ' : ' = '
118
- defaults.map do |key, value|
119
- "#{key}#{joinner}#{value}"
118
+ defaults.map do |parameter, value|
119
+ default_string(parameter, value)
120
120
  end
121
121
  end
122
+
123
+ # Returns the string for one default parameter
124
+ #
125
+ # @param parameter [Symbol] name of the parameter
126
+ # @param value [Object] default value
127
+ #
128
+ # @return [String]
129
+ def default_string(parameter, value)
130
+ "#{parameter}#{joinner}#{value_string(value)}"
131
+ end
132
+
133
+ # Returns the string used when joining a parameter with it's default value
134
+ #
135
+ # @see #named?
136
+ #
137
+ # @return [String]
138
+ def joinner
139
+ @joinner ||= named? ? ': ' : ' = '
140
+ end
122
141
  end
123
142
  end
124
143
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sinclair/core_ext/object'
4
+
5
+ class Sinclair
6
+ class MethodDefinition
7
+ # @api private
8
+ # @author darthjee
9
+ #
10
+ # Stringgify a value for {StringDefinition}
11
+ class Stringifier
12
+ # Convert a value to a string format
13
+ #
14
+ # The returned string can be evaluated as code, returning the
15
+ # original value
16
+ #
17
+ # @param value [Object] object to be converted
18
+ #
19
+ # @return [String]
20
+ def self.value_string(value)
21
+ return 'nil' if value.nil?
22
+ return ":#{value}" if value.is_a?(Symbol)
23
+
24
+ return value.to_s if value.is_any?(Class, Hash, Array)
25
+
26
+ value.to_json
27
+ end
28
+ end
29
+ end
30
+ end
@@ -14,6 +14,7 @@ class Sinclair
14
14
  autoload :StringDefinition, 'sinclair/method_definition/string_definition'
15
15
  autoload :ParameterBuilder, 'sinclair/method_definition/parameter_builder'
16
16
  autoload :ParameterHelper, 'sinclair/method_definition/parameter_helper'
17
+ autoload :Stringifier, 'sinclair/method_definition/stringifier'
17
18
 
18
19
  # @method name
19
20
  #
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ class Model
5
+ # @api private
6
+ # @author Darthjee
7
+ #
8
+ # Builder responsible for building methods to a new {Sinclair::Model} class
9
+ #
10
+ # The building adds readers/setters and an initializer with named parameters
11
+ class Builder < Sinclair
12
+ # @overload initialize(klass, *attributes, writter: true, comparable: true)
13
+ # @param klass [Class<Sinclair::Model>] the new class to receive the methods
14
+ # @param attributes [Array<Symbol>] attributes to be added in both the
15
+ # initialization and adding the methos to the model
16
+ # @param writter [TrueClass,FalseClass] flag informing if the writter/setter
17
+ # method should be added
18
+ # @param comparable [TrueClass,FalseClass] flag to make the class {Comparable}
19
+ # by the fields
20
+ # @overload initialize(klass, *attributes, defaults, writter: true, comparable: true)
21
+ # @param klass [Class<Sinclair::Model>] the new class to receive the methods
22
+ # @param attributes [Array<Symbol>] attributes to be added in both the
23
+ # initialization and adding the methos to the model
24
+ # @param defaults [Hash] attributes to be added with a default value in the initializer
25
+ # @param writter [TrueClass,FalseClass] flag informing if the writter/setter
26
+ # method should be added
27
+ # @param comparable [TrueClass,FalseClass] flag to make the class {Comparable}
28
+ # by the fields
29
+ def initialize(klass, *attributes, writter: true, comparable: true)
30
+ super(klass)
31
+ @attributes = attributes.flatten
32
+ @writter = writter
33
+ @comparable = comparable
34
+
35
+ add_methods
36
+ change_equals
37
+ change_initializer
38
+ end
39
+
40
+ private
41
+
42
+ attr_reader :attributes, :writter, :comparable
43
+ alias writter? writter
44
+ alias comparable? comparable
45
+
46
+ # @!method attributes
47
+ # @api private
48
+ # @private
49
+ #
50
+ # Attributes to be added in the class
51
+ #
52
+ # Attributes without default values are symbols
53
+ # while attributes with defaults values are defined in a Hash
54
+ #
55
+ # @return [Array<Symbol,Hash>]
56
+
57
+ # @!method writter
58
+ # @api private
59
+ # @private
60
+ #
61
+ # Flag if writter methods (setter) should be added or not
62
+ #
63
+ # @return [TrueClass,FalseClass]
64
+
65
+ # @!method comparable
66
+ # @api private
67
+ # @private
68
+ #
69
+ # flag to make the class {Comparable} by the fields
70
+ #
71
+ # @return [TrueClass,FalseClass]
72
+
73
+ # @!method writter?
74
+ # @api private
75
+ # @private
76
+ #
77
+ # Flag if writter methods (setter) should be added or not
78
+ #
79
+ # @return [TrueClass,FalseClass]
80
+
81
+ # @!method comparable?
82
+ # @api private
83
+ # @private
84
+ #
85
+ # flag to make the class {Comparable} by the fields
86
+ #
87
+ # @return [TrueClass,FalseClass]
88
+
89
+ # @private
90
+ # Adds readers and setters
91
+ #
92
+ # Readers are always added, while setters depends on the flag {#writter?}
93
+ #
94
+ # @return [Array<MethodDefinition>]
95
+ def add_methods
96
+ call = writter? ? :attr_accessor : :attr_reader
97
+
98
+ add_method(call, *attributes_names, type: :call)
99
+ end
100
+
101
+ # @private
102
+ # Change the method +==+
103
+ #
104
+ # The change happens using {Sinclair::Comparable}
105
+ # and adding all the fields to be included in the comparisom
106
+ #
107
+ # @return [Array<MethodDefinition>]
108
+ def change_equals
109
+ return unless comparable?
110
+
111
+ add_method(:include, Comparable, type: :call)
112
+ add_method(:comparable_by, *attributes_names, type: :call)
113
+ end
114
+
115
+ # @private
116
+ #
117
+ # Changes the initializer to accept the parameters
118
+ #
119
+ # @return [Array<MethodDefinition>]
120
+ def change_initializer
121
+ code = attributes_names.map do |attr|
122
+ "@#{attr} = #{attr}"
123
+ end.join("\n")
124
+
125
+ add_method(:initialize, code, named_parameters: attributes)
126
+ end
127
+
128
+ # @private
129
+ # Returns the list of attributes
130
+ #
131
+ # This is used when defining the readers / setters
132
+ #
133
+ # @return [Array<Symbol>]
134
+ def attributes_names
135
+ @attributes_names ||= attributes.map do |attr|
136
+ attr.try(:keys) || attr.to_s
137
+ end.flatten
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Sinclair
4
+ # @api public
5
+ # @author Darthjee
6
+ #
7
+ # Basic model to be used when defining new classes quickly
8
+ class Model
9
+ autoload :Builder, 'sinclair/model/builder'
10
+
11
+ class << self
12
+ # Returns a new class that inherits from model
13
+ #
14
+ # @overload for(*attributes, writter: true, comparable: true)
15
+ # @param attributes [Array<Symbol>] attributes to be added in both the
16
+ # initialization and adding the methos to the model
17
+ # @param writter [TrueClass,FalseClass] flag informing if the writter/setter
18
+ # method should be added
19
+ # @param comparable [TrueClass,FalseClass] flag to make the class {Comparable}
20
+ # by the fields
21
+ #
22
+ # @example A model with readers
23
+ # class Car < Sinclair::Model.for(:brand, :model, writter: false)
24
+ # end
25
+ #
26
+ # car = Car.new(brand: :ford, model: :T)
27
+ #
28
+ # car.brand # returns :ford
29
+ # car.model # returns :T
30
+ #
31
+ # @overload for(*attributes, defaults, writter: true, comparable: true)
32
+ # @param attributes [Array<Symbol>] attributes to be added in both the
33
+ # initialization and adding the methos to the model
34
+ # @param defaults [Hash] attributes to be added with a default value in the initializer
35
+ # @param writter [TrueClass,FalseClass] flag informing if the writter/setter
36
+ # method should be added
37
+ # @param comparable [TrueClass,FalseClass] flag to make the class {Comparable}
38
+ # by the fields
39
+ #
40
+ # @example A model with writters
41
+ # class Job < Sinclair::Model.for({ state: :starting }, writter: true)
42
+ # end
43
+ #
44
+ # job = Job.new
45
+ #
46
+ # job.state # returns :starting
47
+ # job.state = :done
48
+ # job.state # returns :done
49
+ #
50
+ # @return [Class<Model>] a new class with the chosen attributes
51
+ def for(*attributes, **options)
52
+ Class.new(self) do |klass|
53
+ Builder.new(klass, *attributes, **options).build
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Sinclair
4
- VERSION = '1.12.0'
4
+ VERSION = '1.13.0'
5
5
  end
data/lib/sinclair.rb CHANGED
@@ -96,6 +96,7 @@ class Sinclair
96
96
  autoload :MethodBuilder, 'sinclair/method_builder'
97
97
  autoload :MethodDefinition, 'sinclair/method_definition'
98
98
  autoload :MethodDefinitions, 'sinclair/method_definitions'
99
+ autoload :Model, 'sinclair/model'
99
100
  autoload :Options, 'sinclair/options'
100
101
 
101
102
  include OptionsParser
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Model do
6
+ describe 'readme' do
7
+ it 'Simple usage' do
8
+ human1 = Human.new(name: 'John Doe', age: 22)
9
+ human2 = Human.new(name: 'John Doe', age: 22)
10
+
11
+ expect(human1.name).to eq('John Doe')
12
+ expect(human1.age).to eq(22)
13
+ expect(human1.gender).to eq(:undefined)
14
+ expect(human1 == human2).to eq(true)
15
+ end
16
+
17
+ it 'Without comparable' do
18
+ tv1 = Tv.new(model: 'Sans Sunga Xt')
19
+ tv2 = Tv.new(model: 'Sans Sunga Xt')
20
+
21
+ expect(tv1 == tv2).to eq(false)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Object do
4
+ describe 'yard' do
5
+ describe '#is_any?' do
6
+ context 'when none match' do
7
+ it do
8
+ object = [1, 2, 3]
9
+
10
+ expect(object.is_any?(Hash, Class)).to eq(false)
11
+ expect(object.is_any?(Hash, Array)).to eq(true)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'yard Sinclair::Model#for' do
6
+ it 'Creating a Simple model' do
7
+ car = Car.new(brand: :ford, model: :T)
8
+
9
+ expect(car.brand).to eq(:ford)
10
+ expect(car.model).to eq(:T)
11
+ end
12
+
13
+ it 'Creating a model with default values and writter' do
14
+ job = Job.new
15
+
16
+ expect(job.state).to eq(:starting)
17
+ job.state = :done
18
+ expect(job.state).to eq(:done)
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Object do
6
+ describe '#is_any?' do
7
+ subject(:object) { 1 }
8
+
9
+ it do
10
+ expect(object).to respond_to(:is_any?)
11
+ end
12
+
13
+ context 'when no argument is passed' do
14
+ it do
15
+ expect(object).not_to be_is_any
16
+ end
17
+ end
18
+
19
+ context 'when passing the correct class as argument' do
20
+ it do
21
+ expect(object).to be_is_any(object.class)
22
+ end
23
+
24
+ context 'when passing any other class' do
25
+ it do
26
+ expect(object).to be_is_any(Symbol, object.class)
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'when passing the wrong class' do
32
+ it do
33
+ expect(object).not_to be_is_any(Symbol)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::MethodDefinition::ParameterHelper do
6
+ describe '.parameters_from' do
7
+ context 'when parameters are not named' do
8
+ context 'when there are no defaults' do
9
+ it 'returns a list of parameters' do
10
+ expect(described_class.parameters_from(%i[a b]))
11
+ .to eq(%w[a b])
12
+ end
13
+ end
14
+
15
+ context 'when there are defaults' do
16
+ let(:parameters) do
17
+ [{ a: 10, b: 'word', c: true, d: false, e: nil, f: :symbol }]
18
+ end
19
+
20
+ it 'returns a list of parameters' do
21
+ expect(described_class.parameters_from(parameters))
22
+ .to eq(['a = 10', 'b = "word"', 'c = true', 'd = false', 'e = nil', 'f = :symbol'])
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'when parameters are named' do
28
+ context 'when there are no defaults' do
29
+ it 'returns a list of parameters' do
30
+ expect(described_class.parameters_from(%i[a b], named: true))
31
+ .to eq(%w[a: b:])
32
+ end
33
+ end
34
+
35
+ context 'when there are defaults' do
36
+ let(:parameters) do
37
+ [{ a: 10, b: 'word', c: true, d: false, e: nil, f: :symbol }]
38
+ end
39
+
40
+ it 'returns a list of parameters' do
41
+ expect(described_class.parameters_from(parameters, named: true))
42
+ .to eq(['a: 10', 'b: "word"', 'c: true', 'd: false', 'e: nil', 'f: :symbol'])
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::MethodDefinition::Stringifier do
6
+ describe '.value_string' do
7
+ context 'when value is nil' do
8
+ it 'returns string representing nil' do
9
+ expect(described_class.value_string(nil)).to eq('nil')
10
+ end
11
+ end
12
+
13
+ context 'when value is a symbol' do
14
+ it 'returns string representing a symbol' do
15
+ expect(described_class.value_string(:symbol)).to eq(':symbol')
16
+ end
17
+ end
18
+
19
+ context 'when value is a string' do
20
+ it 'returns string representing a string' do
21
+ expect(described_class.value_string('string')).to eq('"string"')
22
+ end
23
+ end
24
+
25
+ context 'when value is a number' do
26
+ it 'returns string representing a number' do
27
+ expect(described_class.value_string(10)).to eq('10')
28
+ end
29
+ end
30
+
31
+ context 'when value is a float' do
32
+ it 'returns string representing a float' do
33
+ expect(described_class.value_string(1.20)).to eq('1.2')
34
+ end
35
+ end
36
+
37
+ context 'when value is a true' do
38
+ it 'returns string representing a true' do
39
+ expect(described_class.value_string(true)).to eq('true')
40
+ end
41
+ end
42
+
43
+ context 'when value is a false' do
44
+ it 'returns string representing a false' do
45
+ expect(described_class.value_string(false)).to eq('false')
46
+ end
47
+ end
48
+
49
+ context 'when value is a class' do
50
+ it 'returns string representing a class' do
51
+ expect(described_class.value_string(Sinclair::Model)).to eq('Sinclair::Model')
52
+ end
53
+ end
54
+
55
+ context 'when value is a hash' do
56
+ it 'returns string representing a Hash' do
57
+ expect(described_class.value_string({ a: 10, 'b' => 'value' }))
58
+ .to eq('{:a=>10, "b"=>"value"}')
59
+ end
60
+ end
61
+
62
+ context 'when value is an Array' do
63
+ it 'returns string representing a Array' do
64
+ expect(described_class.value_string([:a, 10, 'b', true, nil]))
65
+ .to eq('[:a, 10, "b", true, nil]')
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Sinclair::Model do
6
+ describe '.with_attributes' do
7
+ subject(:model) { klass.new(name: name) }
8
+
9
+ let(:name) { SecureRandom.hex(10) }
10
+ let(:attributes) { %i[name] }
11
+
12
+ context 'when the call happens with no options' do
13
+ subject(:klass) { described_class.for(*attributes) }
14
+
15
+ it 'Returns a new class' do
16
+ expect(klass.superclass)
17
+ .to eq(described_class)
18
+ end
19
+
20
+ it 'returns a class with getter' do
21
+ expect(klass.instance_method(:name))
22
+ .to be_a(UnboundMethod)
23
+ end
24
+
25
+ it 'returns a class with setter' do
26
+ expect(klass.instance_method(:name=))
27
+ .to be_a(UnboundMethod)
28
+ end
29
+
30
+ it 'returns a new class with a comparable that finds matches' do
31
+ expect(model).to eq(klass.new(name: name))
32
+ end
33
+
34
+ it 'returns a new class with a comparable that find misses' do
35
+ expect(model).not_to eq(klass.new(name: SecureRandom.hex(10)))
36
+ end
37
+
38
+ context 'when reader is called' do
39
+ it do
40
+ expect(model.name).to eq(name)
41
+ end
42
+ end
43
+
44
+ context 'when setter is called' do
45
+ let(:name) { SecureRandom.hex(10) }
46
+ let(:model) { klass.new(name: nil) }
47
+
48
+ it do
49
+ expect { model.name = name }
50
+ .to change(model, :name)
51
+ .from(nil)
52
+ .to(name)
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'when the call happens with comparable false' do
58
+ subject(:klass) { described_class.for(*attributes, **options) }
59
+
60
+ let(:options) { { comparable: false } }
61
+
62
+ it 'returns a new class without comparable' do
63
+ expect(model).not_to eq(klass.new(name: name))
64
+ end
65
+ end
66
+
67
+ context 'when the call happens with reader options' do
68
+ subject(:klass) { described_class.for(*attributes, **options) }
69
+
70
+ let(:options) { { writter: false } }
71
+
72
+ it 'Returns a new class' do
73
+ expect(klass.superclass)
74
+ .to eq(described_class)
75
+ end
76
+
77
+ it 'returns a class with getter' do
78
+ expect(klass.instance_method(:name))
79
+ .to be_a(UnboundMethod)
80
+ end
81
+
82
+ it 'returns a class without setter' do
83
+ expect { klass.instance_method(:name=) }
84
+ .to raise_error(NameError)
85
+ end
86
+
87
+ context 'when reader is called' do
88
+ it do
89
+ expect(model.name).to eq(name)
90
+ end
91
+ end
92
+ end
93
+
94
+ context 'when the call happens with defaults' do
95
+ subject(:klass) do
96
+ described_class.for({ name: 'John Doe' }, **{})
97
+ end
98
+
99
+ it 'Returns a new class' do
100
+ expect(klass.superclass)
101
+ .to eq(described_class)
102
+ end
103
+
104
+ it 'returns a class with getter' do
105
+ expect(klass.instance_method(:name))
106
+ .to be_a(UnboundMethod)
107
+ end
108
+
109
+ it 'returns a class with setter' do
110
+ expect(klass.instance_method(:name=))
111
+ .to be_a(UnboundMethod)
112
+ end
113
+
114
+ context 'when reader is called' do
115
+ subject(:model) { klass.new }
116
+
117
+ let(:name) { SecureRandom.hex(10) }
118
+
119
+ it 'returns the dfault value' do
120
+ expect(model.name).to eq('John Doe')
121
+ end
122
+ end
123
+
124
+ context 'when setter is called' do
125
+ subject(:model) { klass.new }
126
+
127
+ let(:name) { SecureRandom.hex(10) }
128
+
129
+ it do
130
+ expect { model.name = name }
131
+ .to change(model, :name)
132
+ .from('John Doe')
133
+ .to(name)
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: false
2
+
3
+ class Car < Sinclair::Model.for(:brand, :model, writter: false)
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Human < Sinclair::Model.for(:name, :age, { gender: :undefined }, **{})
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: false
2
+
3
+ class Job < Sinclair::Model.for({ state: :starting }, writter: true)
4
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tv < Sinclair::Model.for(:model, writter: false, comparable: false)
4
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinclair
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.12.0
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - DarthJee
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-14 00:00:00.000000000 Z
11
+ date: 2023-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -280,6 +280,7 @@ files:
280
280
  - lib/sinclair/config_class.rb
281
281
  - lib/sinclair/config_factory.rb
282
282
  - lib/sinclair/configurable.rb
283
+ - lib/sinclair/core_ext/object.rb
283
284
  - lib/sinclair/env_settable.rb
284
285
  - lib/sinclair/env_settable/builder.rb
285
286
  - lib/sinclair/equals_checker.rb
@@ -311,7 +312,10 @@ files:
311
312
  - lib/sinclair/method_definition/parameter_builder.rb
312
313
  - lib/sinclair/method_definition/parameter_helper.rb
313
314
  - lib/sinclair/method_definition/string_definition.rb
315
+ - lib/sinclair/method_definition/stringifier.rb
314
316
  - lib/sinclair/method_definitions.rb
317
+ - lib/sinclair/model.rb
318
+ - lib/sinclair/model/builder.rb
315
319
  - lib/sinclair/options.rb
316
320
  - lib/sinclair/options/builder.rb
317
321
  - lib/sinclair/options/class_methods.rb
@@ -325,6 +329,7 @@ files:
325
329
  - spec/integration/readme/sinclair/configurable_spec.rb
326
330
  - spec/integration/readme/sinclair/env_settable_spec.rb
327
331
  - spec/integration/readme/sinclair/matchers_spec.rb
332
+ - spec/integration/readme/sinclair/model_spec.rb
328
333
  - spec/integration/readme/sinclair/options_spec.rb
329
334
  - spec/integration/readme/sinclair/types_of_definition_spec.rb
330
335
  - spec/integration/readme/sinclair_spec.rb
@@ -337,6 +342,7 @@ files:
337
342
  - spec/integration/yard/sinclair/config_factory_spec.rb
338
343
  - spec/integration/yard/sinclair/config_spec.rb
339
344
  - spec/integration/yard/sinclair/configurable_spec.rb
345
+ - spec/integration/yard/sinclair/core_ext/object_spec.rb
340
346
  - spec/integration/yard/sinclair/env_settable_spec.rb
341
347
  - spec/integration/yard/sinclair/equals_checker_spec.rb
342
348
  - spec/integration/yard/sinclair/eval_and_add_method_spec.rb
@@ -347,6 +353,7 @@ files:
347
353
  - spec/integration/yard/sinclair/matchers/add_instance_method_to_spec.rb
348
354
  - spec/integration/yard/sinclair/matchers/change_class_method_spec.rb
349
355
  - spec/integration/yard/sinclair/matchers/change_instance_method_spec.rb
356
+ - spec/integration/yard/sinclair/model_spec.rb
350
357
  - spec/integration/yard/sinclair/options_parser_spec.rb
351
358
  - spec/integration/yard/sinclair/options_spec.rb
352
359
  - spec/integration/yard/sinclair_spec.rb
@@ -357,6 +364,7 @@ files:
357
364
  - spec/lib/sinclair/config_factory_spec.rb
358
365
  - spec/lib/sinclair/config_spec.rb
359
366
  - spec/lib/sinclair/configurable_spec.rb
367
+ - spec/lib/sinclair/core_ext/object_spec.rb
360
368
  - spec/lib/sinclair/env_settable/builder_spec.rb
361
369
  - spec/lib/sinclair/env_settable_spec.rb
362
370
  - spec/lib/sinclair/equals_checker_spec.rb
@@ -380,9 +388,12 @@ files:
380
388
  - spec/lib/sinclair/method_definition/block_helper_spec.rb
381
389
  - spec/lib/sinclair/method_definition/call_definition_spec.rb
382
390
  - spec/lib/sinclair/method_definition/parameter_builder_spec.rb
391
+ - spec/lib/sinclair/method_definition/parameter_helper_spec.rb
383
392
  - spec/lib/sinclair/method_definition/string_definition_spec.rb
393
+ - spec/lib/sinclair/method_definition/stringifier_spec.rb
384
394
  - spec/lib/sinclair/method_definition_spec.rb
385
395
  - spec/lib/sinclair/method_definitions_spec.rb
396
+ - spec/lib/sinclair/model_spec.rb
386
397
  - spec/lib/sinclair/options/builder_spec.rb
387
398
  - spec/lib/sinclair/options/class_methods_spec.rb
388
399
  - spec/lib/sinclair/options_parser_spec.rb
@@ -393,6 +404,7 @@ files:
393
404
  - spec/support/models/app_client.rb
394
405
  - spec/support/models/app_config.rb
395
406
  - spec/support/models/builder_options.rb
407
+ - spec/support/models/car.rb
396
408
  - spec/support/models/client.rb
397
409
  - spec/support/models/connection_options.rb
398
410
  - spec/support/models/default_value.rb
@@ -407,7 +419,9 @@ files:
407
419
  - spec/support/models/host_config.rb
408
420
  - spec/support/models/http_json_model.rb
409
421
  - spec/support/models/http_person.rb
422
+ - spec/support/models/human.rb
410
423
  - spec/support/models/initial_valuer.rb
424
+ - spec/support/models/job.rb
411
425
  - spec/support/models/login_config.rb
412
426
  - spec/support/models/login_configurable.rb
413
427
  - spec/support/models/my_app_client.rb
@@ -425,6 +439,7 @@ files:
425
439
  - spec/support/models/server.rb
426
440
  - spec/support/models/server_config.rb
427
441
  - spec/support/models/service_client.rb
442
+ - spec/support/models/tv.rb
428
443
  - spec/support/models/validator_builder.rb
429
444
  - spec/support/sample_model.rb
430
445
  - spec/support/shared_examples/attribute_accessor.rb