attributor 5.0.2 → 5.1.0

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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/.travis.yml +6 -4
  4. data/CHANGELOG.md +6 -1
  5. data/Gemfile +1 -1
  6. data/Guardfile +14 -8
  7. data/Rakefile +4 -5
  8. data/attributor.gemspec +34 -29
  9. data/lib/attributor.rb +23 -29
  10. data/lib/attributor/attribute.rb +108 -127
  11. data/lib/attributor/attribute_resolver.rb +12 -26
  12. data/lib/attributor/dsl_compiler.rb +17 -21
  13. data/lib/attributor/dumpable.rb +1 -2
  14. data/lib/attributor/example_mixin.rb +5 -8
  15. data/lib/attributor/exceptions.rb +5 -6
  16. data/lib/attributor/extensions/randexp.rb +3 -5
  17. data/lib/attributor/extras/field_selector.rb +4 -4
  18. data/lib/attributor/extras/field_selector/transformer.rb +6 -7
  19. data/lib/attributor/families/numeric.rb +0 -2
  20. data/lib/attributor/families/temporal.rb +1 -4
  21. data/lib/attributor/hash_dsl_compiler.rb +22 -25
  22. data/lib/attributor/type.rb +24 -32
  23. data/lib/attributor/types/bigdecimal.rb +7 -14
  24. data/lib/attributor/types/boolean.rb +5 -8
  25. data/lib/attributor/types/class.rb +9 -10
  26. data/lib/attributor/types/collection.rb +34 -44
  27. data/lib/attributor/types/container.rb +9 -15
  28. data/lib/attributor/types/csv.rb +7 -10
  29. data/lib/attributor/types/date.rb +20 -25
  30. data/lib/attributor/types/date_time.rb +7 -14
  31. data/lib/attributor/types/float.rb +4 -6
  32. data/lib/attributor/types/hash.rb +171 -196
  33. data/lib/attributor/types/ids.rb +2 -6
  34. data/lib/attributor/types/integer.rb +12 -17
  35. data/lib/attributor/types/model.rb +39 -48
  36. data/lib/attributor/types/object.rb +2 -4
  37. data/lib/attributor/types/polymorphic.rb +118 -0
  38. data/lib/attributor/types/regexp.rb +4 -5
  39. data/lib/attributor/types/string.rb +6 -7
  40. data/lib/attributor/types/struct.rb +8 -15
  41. data/lib/attributor/types/symbol.rb +3 -6
  42. data/lib/attributor/types/tempfile.rb +5 -6
  43. data/lib/attributor/types/time.rb +11 -11
  44. data/lib/attributor/types/uri.rb +9 -10
  45. data/lib/attributor/version.rb +1 -1
  46. data/spec/attribute_resolver_spec.rb +57 -78
  47. data/spec/attribute_spec.rb +174 -216
  48. data/spec/attributor_spec.rb +11 -15
  49. data/spec/dsl_compiler_spec.rb +19 -33
  50. data/spec/dumpable_spec.rb +6 -7
  51. data/spec/extras/field_selector/field_selector_spec.rb +1 -1
  52. data/spec/families_spec.rb +1 -3
  53. data/spec/hash_dsl_compiler_spec.rb +65 -74
  54. data/spec/spec_helper.rb +9 -3
  55. data/spec/support/hashes.rb +2 -3
  56. data/spec/support/models.rb +30 -36
  57. data/spec/support/polymorphics.rb +10 -0
  58. data/spec/type_spec.rb +38 -61
  59. data/spec/types/bigdecimal_spec.rb +11 -15
  60. data/spec/types/boolean_spec.rb +12 -39
  61. data/spec/types/class_spec.rb +10 -11
  62. data/spec/types/collection_spec.rb +72 -81
  63. data/spec/types/container_spec.rb +22 -26
  64. data/spec/types/csv_spec.rb +15 -16
  65. data/spec/types/date_spec.rb +16 -33
  66. data/spec/types/date_time_spec.rb +16 -33
  67. data/spec/types/file_upload_spec.rb +1 -2
  68. data/spec/types/float_spec.rb +7 -14
  69. data/spec/types/hash_spec.rb +285 -289
  70. data/spec/types/ids_spec.rb +5 -7
  71. data/spec/types/integer_spec.rb +37 -46
  72. data/spec/types/model_spec.rb +111 -128
  73. data/spec/types/polymorphic_spec.rb +134 -0
  74. data/spec/types/regexp_spec.rb +4 -7
  75. data/spec/types/string_spec.rb +17 -21
  76. data/spec/types/struct_spec.rb +40 -47
  77. data/spec/types/tempfile_spec.rb +1 -2
  78. data/spec/types/temporal_spec.rb +9 -0
  79. data/spec/types/time_spec.rb +16 -32
  80. data/spec/types/type_spec.rb +15 -0
  81. data/spec/types/uri_spec.rb +6 -7
  82. metadata +77 -25
@@ -1,11 +1,9 @@
1
1
  require 'ostruct'
2
2
 
3
3
  module Attributor
4
-
5
-
6
4
  class AttributeResolver
7
5
  ROOT_PREFIX = '$'.freeze
8
- COLLECTION_INDEX_KEY = /^at\((\d+)\)$/.freeze
6
+ COLLECTION_INDEX_KEY = /^at\((\d+)\)$/
9
7
 
10
8
  class Data < ::Hash
11
9
  include Hashie::Extensions::MethodReader
@@ -17,8 +15,7 @@ module Attributor
17
15
  @data = Data.new
18
16
  end
19
17
 
20
-
21
- def query!(key_path, path_prefix=ROOT_PREFIX)
18
+ def query!(key_path, path_prefix = ROOT_PREFIX)
22
19
  # If the incoming key_path is not an absolute path, append the given prefix
23
20
  # NOTE: Need to index key_path by range here because Ruby 1.8 returns a
24
21
  # FixNum for the ASCII code, not the actual character, when indexing by a number.
@@ -49,7 +46,6 @@ module Attributor
49
46
  result
50
47
  end
51
48
 
52
-
53
49
  # Query for a certain key in the attribute hierarchy
54
50
  #
55
51
  # @param [String] key_path The name of the key to query and its path
@@ -57,21 +53,20 @@ module Attributor
57
53
  #
58
54
  # @return [String] The value of the specified attribute/key
59
55
  #
60
- def query(key_path,path_prefix=ROOT_PREFIX)
61
- query!(key_path,path_prefix)
62
- rescue NoMethodError => e
56
+ def query(key_path, path_prefix = ROOT_PREFIX)
57
+ query!(key_path, path_prefix)
58
+ rescue NoMethodError
63
59
  nil
64
60
  end
65
61
 
66
62
  def register(key_path, value)
67
63
  if key_path.split(SEPARATOR).size > 1
68
- raise AttributorException.new("can only register top-level attributes. got: #{key_path}")
64
+ raise AttributorException, "can only register top-level attributes. got: #{key_path}"
69
65
  end
70
66
 
71
67
  @data[key_path] = value
72
68
  end
73
69
 
74
-
75
70
  # Checks that the the condition is met. This means the attribute identified
76
71
  # by path_prefix and key_path satisfies the optional predicate, which when
77
72
  # nil simply checks for existence.
@@ -84,13 +79,11 @@ module Attributor
84
79
  #
85
80
  # @raise [AttributorException] When an unsupported predicate is passed
86
81
  #
87
- def check(path_prefix, key_path, predicate=nil)
88
- value = self.query(key_path, path_prefix)
82
+ def check(path_prefix, key_path, predicate = nil)
83
+ value = query(key_path, path_prefix)
89
84
 
90
85
  # we have a value, any value, which is good enough given no predicate
91
- if !value.nil? && predicate.nil?
92
- return true
93
- end
86
+ return true if !value.nil? && predicate.nil?
94
87
 
95
88
  case predicate
96
89
  when ::String, ::Regexp, ::Integer, ::Float, ::DateTime, true, false
@@ -101,9 +94,8 @@ module Attributor
101
94
  when nil
102
95
  return !value.nil?
103
96
  else
104
- raise AttributorException.new("predicate not supported: #{predicate.inspect}")
97
+ raise AttributorException, "predicate not supported: #{predicate.inspect}"
105
98
  end
106
-
107
99
  end
108
100
 
109
101
  # TODO: kill this when we also kill Taylor's IdentityMap.current
@@ -111,15 +103,9 @@ module Attributor
111
103
  Thread.current[:_attributor_attribute_resolver] = resolver
112
104
  end
113
105
 
114
-
115
106
  def self.current
116
- if resolver = Thread.current[:_attributor_attribute_resolver]
117
- return resolver
118
- else
119
- raise AttributorException, "No AttributeResolver set."
120
- end
107
+ raise AttributorException, 'No AttributeResolver set.' unless Thread.current[:_attributor_attribute_resolver]
108
+ Thread.current[:_attributor_attribute_resolver]
121
109
  end
122
-
123
110
  end
124
-
125
111
  end
@@ -1,6 +1,5 @@
1
- #Container of options and structure definition
1
+ # Container of options and structure definition
2
2
  module Attributor
3
-
4
3
  # RULES FOR ATTRIBUTES
5
4
  # The type of an attribute is:
6
5
  # the specified type
@@ -11,7 +10,6 @@ module Attributor
11
10
  # The reference option for an attribute is passed if a block is given
12
11
 
13
12
  class DSLCompiler
14
-
15
13
  attr_accessor :options, :target
16
14
 
17
15
  def initialize(target, **options)
@@ -21,7 +19,7 @@ module Attributor
21
19
 
22
20
  def parse(*blocks)
23
21
  blocks.push(Proc.new) if block_given?
24
- blocks.each { |block| self.instance_eval(&block) }
22
+ blocks.each { |block| instance_eval(&block) }
25
23
  self
26
24
  end
27
25
 
@@ -33,19 +31,19 @@ module Attributor
33
31
  end
34
32
  end
35
33
 
36
- def attribute(name, attr_type=nil, **opts, &block)
37
- raise AttributorException, "Attribute names must be symbols, got: #{name.inspect}" unless name.kind_of? ::Symbol
34
+ def attribute(name, attr_type = nil, **opts, &block)
35
+ raise AttributorException, "Attribute names must be symbols, got: #{name.inspect}" unless name.is_a? ::Symbol
38
36
  target.attributes[name] = define(name, attr_type, **opts, &block)
39
37
  end
40
38
 
41
- def key(name, attr_type=nil, **opts, &block)
42
- unless name.kind_of?(options.fetch(:key_type, Attributor::Object).native_type)
39
+ def key(name, attr_type = nil, **opts, &block)
40
+ unless name.is_a?(options.fetch(:key_type, Attributor::Object).native_type)
43
41
  raise "Invalid key: #{name.inspect}, must be instance of #{options[:key_type].native_type.name}"
44
42
  end
45
43
  target.keys[name] = define(name, attr_type, **opts, &block)
46
44
  end
47
45
 
48
- def extra(name, attr_type=nil, **opts, &block)
46
+ def extra(name, attr_type = nil, **opts, &block)
49
47
  if attr_type.nil?
50
48
  attr_type = Attributor::Hash.of(key: target.key_type, value: target.value_type)
51
49
  end
@@ -65,7 +63,7 @@ module Attributor
65
63
  # @param [Hash] opts describe opts param
66
64
  # @param [Block] block describe block param
67
65
  # @example
68
- # attribute :email, String, example: /[:email:]/
66
+ # attribute :email, String, example: Randgen.email
69
67
  # @overload define(name, opts, &block)
70
68
  # Assume a type of Attributor::Struct
71
69
  # @param [symbol] name describe name param
@@ -79,7 +77,7 @@ module Attributor
79
77
  # attribute :state, String
80
78
  # end
81
79
  # @api semiprivate
82
- def define(name, attr_type=nil, **opts, &block)
80
+ def define(name, attr_type = nil, **opts, &block)
83
81
  # add to existing attribute if present
84
82
  if (existing_attribute = attributes[name])
85
83
  if existing_attribute.attributes
@@ -89,8 +87,8 @@ module Attributor
89
87
  end
90
88
 
91
89
  # determine inherited attribute
92
- inherited_attribute = nil
93
- if (reference = self.options[:reference])
90
+ inherited_attribute = nil
91
+ if (reference = options[:reference])
94
92
  if (inherited_attribute = reference.attributes[name])
95
93
  opts = inherited_attribute.options.merge(opts) unless attr_type
96
94
  opts[:reference] = inherited_attribute.type if block_given?
@@ -101,12 +99,12 @@ module Attributor
101
99
  if attr_type.nil?
102
100
  if block_given?
103
101
  attr_type = if inherited_attribute && inherited_attribute.type < Attributor::Collection
104
- # override the reference to be the member_attribute's type for collections
105
- opts[:reference] = inherited_attribute.type.member_attribute.type
106
- Attributor::Collection.of(Struct)
107
- else
108
- Attributor::Struct
109
- end
102
+ # override the reference to be the member_attribute's type for collections
103
+ opts[:reference] = inherited_attribute.type.member_attribute.type
104
+ Attributor::Collection.of(Struct)
105
+ else
106
+ Attributor::Struct
107
+ end
110
108
  elsif inherited_attribute
111
109
  attr_type = inherited_attribute.type
112
110
  else
@@ -116,7 +114,5 @@ module Attributor
116
114
 
117
115
  Attributor::Attribute.new(attr_type, opts, &block)
118
116
  end
119
-
120
-
121
117
  end
122
118
  end
@@ -6,6 +6,5 @@ module Attributor
6
6
  def dump
7
7
  raise NotImplementedError, 'Dumpable requires the implementation of #dump'
8
8
  end
9
-
10
9
  end
11
- end
10
+ end
@@ -2,11 +2,9 @@
2
2
  # primarily enables support for lazy values.
3
3
 
4
4
  module Attributor
5
-
6
5
  module ExampleMixin
7
-
8
6
  def self.extended(obj)
9
- if obj.kind_of? Attributor::Model
7
+ if obj.is_a? Attributor::Model
10
8
  obj.class.attributes.each do |name, _|
11
9
  obj.define_singleton_method(name) do
12
10
  get(name)
@@ -32,7 +30,7 @@ module Attributor
32
30
  @contents[k]
33
31
  end
34
32
 
35
- def []=(k,v)
33
+ def []=(k, v)
36
34
  lazy_attributes.delete k
37
35
  @contents[k] = v
38
36
  end
@@ -41,7 +39,7 @@ module Attributor
41
39
  contents.each(&block)
42
40
  end
43
41
 
44
- alias_method :each_pair, :each
42
+ alias each_pair each
45
43
 
46
44
  def values
47
45
  contents.values
@@ -63,7 +61,7 @@ module Attributor
63
61
  @contents.key?(key) || lazy_attributes.key?(key)
64
62
  end
65
63
 
66
- def get(key, context: self.generate_subcontext(Attributor::DEFAULT_ROOT_CONTEXT,key))
64
+ def get(key, context: generate_subcontext(Attributor::DEFAULT_ROOT_CONTEXT, key))
67
65
  key = self.class.key_attribute.load(key, context)
68
66
 
69
67
  unless @contents.key? key
@@ -78,7 +76,7 @@ module Attributor
78
76
 
79
77
  def attributes
80
78
  lazy_attributes.keys.each do |name|
81
- self.__send__(name)
79
+ __send__(name)
82
80
  end
83
81
 
84
82
  super
@@ -93,5 +91,4 @@ module Attributor
93
91
  super
94
92
  end
95
93
  end
96
-
97
94
  end
@@ -6,14 +6,13 @@ module Attributor
6
6
  end
7
7
 
8
8
  class IncompatibleTypeError < LoadError
9
-
10
- def initialize(type:, value_type: , context: )
9
+ def initialize(type:, value_type:, context:)
11
10
  super "Type #{type} cannot load values of type #{value_type} while loading #{Attributor.humanize_context(context)}."
12
11
  end
13
12
  end
14
13
 
15
14
  class CoercionError < LoadError
16
- def initialize( context: , from: , to:, value: nil)
15
+ def initialize(context:, from:, to:, value: nil)
17
16
  msg = "Error coercing from #{from} to #{to} while loading #{Attributor.humanize_context(context)}."
18
17
  msg += " Received value #{Attributor.errorize_value(value)}" if value
19
18
  super msg
@@ -21,7 +20,7 @@ module Attributor
21
20
  end
22
21
 
23
22
  class DeserializationError < LoadError
24
- def initialize( context: , from:, encoding: , value: nil)
23
+ def initialize(context:, from:, encoding:, value: nil)
25
24
  msg = "Error deserializing a #{from} using #{encoding} while loading #{Attributor.humanize_context(context)}."
26
25
  msg += " Received value #{Attributor.errorize_value(value)}" if value
27
26
  super msg
@@ -29,10 +28,10 @@ module Attributor
29
28
  end
30
29
 
31
30
  class DumpError < AttributorException
32
- def initialize( context: , name: , type: , original_exception: )
31
+ def initialize(context:, name:, type:, original_exception:)
33
32
  msg = "Error while dumping attribute #{name} of type #{type} for context #{Attributor.humanize_context(context)}."
34
33
  msg << " Reason: #{original_exception}"
35
34
  super msg
36
35
  end
37
36
  end
38
- end
37
+ end
@@ -1,15 +1,13 @@
1
1
  require 'date'
2
2
 
3
-
4
3
  class Randgen
5
4
  DATE_TIME_EPOCH = ::DateTime.new(2015, 1, 1, 0, 0, 0)
6
5
 
7
6
  def self.date
8
- return DATE_TIME_EPOCH - rand(800)
7
+ DATE_TIME_EPOCH - rand(800)
9
8
  end
10
9
 
11
10
  def self.time
12
- return date.to_time
11
+ date.to_time
13
12
  end
14
-
15
- end
13
+ end
@@ -1,8 +1,8 @@
1
1
  begin
2
2
  require 'parslet'
3
3
  rescue LoadError
4
- warn "Attributor::FieldSelector requires the 'parslet' gem, which can not be found. " +
5
- "Please make sure it's in your Gemfile or installed in your system."
4
+ warn "Attributor::FieldSelector requires the 'parslet' gem, which can not be found. " \
5
+ "Please make sure it's in your Gemfile or installed in your system."
6
6
  end
7
7
 
8
8
  module Attributor
@@ -16,7 +16,7 @@ module Attributor
16
16
  ::Hash
17
17
  end
18
18
 
19
- def self.example(_context = nil, _options = {})
19
+ def self.example(_context = nil, options: {})
20
20
  3.times.each_with_object([]) do |_i, array|
21
21
  array << /\w{5,8}/.gen
22
22
  end.join(',')
@@ -24,7 +24,7 @@ module Attributor
24
24
 
25
25
  def self.load(value, context = Attributor::DEFAULT_ROOT_CONTEXT, **_options)
26
26
  return nil if value.nil?
27
- return value if self.valid_type? value
27
+ return value if valid_type? value
28
28
  return {} if value.empty?
29
29
 
30
30
  parsed = Parser.new.parse(value)
@@ -1,15 +1,14 @@
1
1
  module Attributor
2
2
  class FieldSelector
3
3
  class Transformer < Parslet::Transform
4
-
5
4
  rule(field: simple(:field_token), children: subtree(:children_tree)) do
6
5
  cs = if children_tree.empty?
7
- true
8
- else
9
- children_tree.each_with_object({}) do |item, hash|
10
- hash.merge! item
11
- end
12
- end
6
+ true
7
+ else
8
+ children_tree.each_with_object({}) do |item, hash|
9
+ hash.merge! item
10
+ end
11
+ end
13
12
  { field_token.to_sym => cs }
14
13
  end
15
14
 
@@ -1,7 +1,6 @@
1
1
  # Abstract type for the 'numeric' family
2
2
 
3
3
  module Attributor
4
-
5
4
  class Numeric
6
5
  include Type
7
6
 
@@ -12,6 +11,5 @@ module Attributor
12
11
  def self.family
13
12
  'numeric'
14
13
  end
15
-
16
14
  end
17
15
  end
@@ -1,7 +1,6 @@
1
1
  # Abstract type for the 'temporal' family
2
2
 
3
3
  module Attributor
4
-
5
4
  class Temporal
6
5
  include Type
7
6
 
@@ -13,10 +12,8 @@ module Attributor
13
12
  'temporal'
14
13
  end
15
14
 
16
- def self.dump(value,**opts)
15
+ def self.dump(value, **_opts)
17
16
  value && value.iso8601
18
17
  end
19
-
20
-
21
18
  end
22
19
  end
@@ -1,10 +1,7 @@
1
1
  require_relative 'dsl_compiler'
2
2
 
3
-
4
3
  module Attributor
5
-
6
4
  class HashDSLCompiler < DSLCompiler
7
-
8
5
  # A class that encapsulates the definition of a requirement for Hash attributes
9
6
  # It implements the validation against incoming values and it describes its format for documentation purposes
10
7
  class Requirement
@@ -18,9 +15,9 @@ module Attributor
18
15
  @type = spec.keys.first
19
16
  case type
20
17
  when :all
21
- self.of(*spec[type])
18
+ of(*spec[type])
22
19
  when :exclusive
23
- self.of(*spec[type])
20
+ of(*spec[type])
24
21
  else
25
22
  @number = spec[type]
26
23
  end
@@ -31,7 +28,7 @@ module Attributor
31
28
  self
32
29
  end
33
30
 
34
- def validate(keys,context=Attributor::DEFAULT_ROOT_CONTEXT,_attribute=nil)
31
+ def validate(keys, context = Attributor::DEFAULT_ROOT_CONTEXT, _attribute = nil)
35
32
  result = []
36
33
  case type
37
34
  when :all
@@ -49,13 +46,13 @@ module Attributor
49
46
  when :at_most
50
47
  rest = attr_names & keys
51
48
  if rest.size > number
52
- found = rest.empty? ? "none" : rest.inspect
49
+ found = rest.empty? ? 'none' : rest.inspect
53
50
  result.push "At most #{number} keys out of #{attr_names} can be passed in for #{Attributor.humanize_context(context)}. Found #{found}"
54
51
  end
55
52
  when :at_least
56
53
  rest = attr_names & keys
57
54
  if rest.size < number
58
- found = rest.empty? ? "none" : rest.inspect
55
+ found = rest.empty? ? 'none' : rest.inspect
59
56
  result.push "At least #{number} keys out of #{attr_names} are required to be passed in for #{Attributor.humanize_context(context)}. Found #{found}"
60
57
  end
61
58
  when :exclusive
@@ -67,15 +64,14 @@ module Attributor
67
64
  result
68
65
  end
69
66
 
70
- def describe(shallow=false, example: nil)
71
- hash = {type: type, attributes: attr_names}
67
+ def describe(_shallow = false, _example: nil)
68
+ hash = { type: type, attributes: attr_names }
72
69
  hash[:count] = number unless number.nil?
73
70
  hash[:description] = description unless description.nil?
74
71
  hash
75
72
  end
76
73
  end
77
74
 
78
-
79
75
  # A class that encapsulates the available DSL under the `requires` keyword.
80
76
  # In particular it allows to define requirements like:
81
77
  # requires.all :attr1, :attr2, :attr3
@@ -91,28 +87,33 @@ module Attributor
91
87
  self.target = target
92
88
  self.options = opts
93
89
  end
90
+
94
91
  def all(*attr_names, **opts)
95
- req = Requirement.new( options.merge(opts).merge(all: attr_names) )
92
+ req = Requirement.new(options.merge(opts).merge(all: attr_names))
96
93
  target.add_requirement req
97
94
  req
98
95
  end
96
+
99
97
  def at_most(number)
100
- req = Requirement.new( options.merge(at_most: number) )
98
+ req = Requirement.new(options.merge(at_most: number))
101
99
  target.add_requirement req
102
100
  req
103
101
  end
102
+
104
103
  def at_least(number)
105
- req = Requirement.new( options.merge(at_least: number) )
104
+ req = Requirement.new(options.merge(at_least: number))
106
105
  target.add_requirement req
107
106
  req
108
107
  end
108
+
109
109
  def exactly(number)
110
- req = Requirement.new( options.merge(exactly: number) )
110
+ req = Requirement.new(options.merge(exactly: number))
111
111
  target.add_requirement req
112
112
  req
113
113
  end
114
+
114
115
  def exclusive(*attr_names, **opts)
115
- req = Requirement.new( options.merge(opts).merge(exclusive: attr_names) )
116
+ req = Requirement.new(options.merge(opts).merge(exclusive: attr_names))
116
117
  target.add_requirement req
117
118
  req
118
119
  end
@@ -122,21 +123,17 @@ module Attributor
122
123
  @requirements_dsl ||= RequiresDSL.new(@target)
123
124
  end
124
125
 
125
- def requires(*spec,**opts,&block)
126
+ def requires(*spec, **opts, &block)
126
127
  if spec.empty?
127
- unless opts.empty?
128
- self._requirements_dsl.options.merge(opts)
129
- end
128
+ _requirements_dsl.options.merge(opts) unless opts.empty?
130
129
  if block_given?
131
- self._requirements_dsl.instance_eval(&block)
130
+ _requirements_dsl.instance_eval(&block)
132
131
  else
133
- self._requirements_dsl
132
+ _requirements_dsl
134
133
  end
135
134
  else
136
- self._requirements_dsl.all(*spec,opts)
135
+ _requirements_dsl.all(*spec, opts)
137
136
  end
138
137
  end
139
-
140
-
141
138
  end
142
139
  end