page_ez 0.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.standard.yml +3 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +148 -0
- data/LICENSE.txt +21 -0
- data/README.md +575 -0
- data/Rakefile +10 -0
- data/lib/page_ez/configuration.rb +33 -0
- data/lib/page_ez/delegates_to.rb +25 -0
- data/lib/page_ez/errors.rb +17 -0
- data/lib/page_ez/has_many_result.rb +35 -0
- data/lib/page_ez/has_one_result.rb +14 -0
- data/lib/page_ez/method_generators/define_has_many_result_methods.rb +48 -0
- data/lib/page_ez/method_generators/define_has_one_predicate_methods.rb +42 -0
- data/lib/page_ez/method_generators/define_has_one_result_methods.rb +35 -0
- data/lib/page_ez/method_generators/has_many_dynamic_selector.rb +39 -0
- data/lib/page_ez/method_generators/has_many_ordered_dynamic_selector.rb +39 -0
- data/lib/page_ez/method_generators/has_many_ordered_selector.rb +47 -0
- data/lib/page_ez/method_generators/has_many_static_selector.rb +41 -0
- data/lib/page_ez/method_generators/has_one_composed_class.rb +40 -0
- data/lib/page_ez/method_generators/has_one_dynamic_selector.rb +39 -0
- data/lib/page_ez/method_generators/has_one_static_selector.rb +25 -0
- data/lib/page_ez/method_generators/identity_processor.rb +11 -0
- data/lib/page_ez/null_logger.rb +12 -0
- data/lib/page_ez/options.rb +37 -0
- data/lib/page_ez/page.rb +162 -0
- data/lib/page_ez/page_visitor.rb +72 -0
- data/lib/page_ez/parameters.rb +54 -0
- data/lib/page_ez/pluralization.rb +25 -0
- data/lib/page_ez/selector_evaluator.rb +76 -0
- data/lib/page_ez/version.rb +5 -0
- data/lib/page_ez/visitors/debug_visitor.rb +59 -0
- data/lib/page_ez/visitors/depth_visitor.rb +44 -0
- data/lib/page_ez/visitors/macro_pluralization_visitor.rb +70 -0
- data/lib/page_ez/visitors/matcher_collision_visitor.rb +75 -0
- data/lib/page_ez/visitors/registered_name_visitor.rb +100 -0
- data/lib/page_ez.rb +41 -0
- data/page_ez.gemspec +43 -0
- metadata +238 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative "identity_processor"
|
2
|
+
|
3
|
+
module PageEz
|
4
|
+
module MethodGenerators
|
5
|
+
class DefineHasManyResultMethods
|
6
|
+
def initialize(name, evaluator_class:, constructor:, processor: IdentityProcessor)
|
7
|
+
@name = name
|
8
|
+
@evaluator_class = evaluator_class
|
9
|
+
@constructor = constructor
|
10
|
+
@processor = processor
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
name = @name
|
15
|
+
evaluator_class = @evaluator_class
|
16
|
+
constructor = @constructor
|
17
|
+
processor = @processor
|
18
|
+
|
19
|
+
target.logged_define_method(name) do |*args|
|
20
|
+
evaluator = evaluator_class.run(processor.run_args(args), target: self)
|
21
|
+
|
22
|
+
selector = processor.selector(evaluator.selector, args)
|
23
|
+
|
24
|
+
PageEz.reraise_selector_error(selector) do
|
25
|
+
PageEz::HasManyResult.new(
|
26
|
+
container: container,
|
27
|
+
selector: selector,
|
28
|
+
options: evaluator.options,
|
29
|
+
constructor: constructor.method(:new)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
target.logged_define_method("has_#{name}_count?") do |count, *args|
|
35
|
+
send(name, *args).has_count_of?(count)
|
36
|
+
end
|
37
|
+
|
38
|
+
target.logged_define_method("has_#{name}?") do |*args|
|
39
|
+
send(name, *args).has_any_elements?
|
40
|
+
end
|
41
|
+
|
42
|
+
target.logged_define_method("has_no_#{name}?") do |*args|
|
43
|
+
send(name, *args).has_no_elements?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class DefineHasOnePredicateMethods
|
4
|
+
def initialize(name, evaluator_class:, processor: IdentityProcessor)
|
5
|
+
@name = name
|
6
|
+
@evaluator_class = evaluator_class
|
7
|
+
@processor = processor
|
8
|
+
end
|
9
|
+
|
10
|
+
def run(target)
|
11
|
+
evaluator_class = @evaluator_class
|
12
|
+
processor = @processor
|
13
|
+
|
14
|
+
target.logged_define_method("has_#{@name}?") do |*args|
|
15
|
+
evaluator = evaluator_class.run(processor.run_args(args), target: self)
|
16
|
+
|
17
|
+
selector = processor.selector(evaluator.selector, args)
|
18
|
+
|
19
|
+
PageEz.reraise_selector_error(selector) do
|
20
|
+
has_css?(
|
21
|
+
selector,
|
22
|
+
**evaluator.options
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
target.logged_define_method("has_no_#{@name}?") do |*args|
|
28
|
+
evaluator = evaluator_class.run(processor.run_args(args), target: self)
|
29
|
+
|
30
|
+
selector = processor.selector(evaluator.selector, args)
|
31
|
+
|
32
|
+
PageEz.reraise_selector_error(selector) do
|
33
|
+
has_no_css?(
|
34
|
+
selector,
|
35
|
+
**evaluator.options
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative "identity_processor"
|
2
|
+
|
3
|
+
module PageEz
|
4
|
+
module MethodGenerators
|
5
|
+
class DefineHasOneResultMethods
|
6
|
+
def initialize(name, evaluator_class:, constructor:, processor: IdentityProcessor)
|
7
|
+
@name = name
|
8
|
+
@evaluator_class = evaluator_class
|
9
|
+
@processor = processor
|
10
|
+
@constructor = constructor
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
evaluator_class = @evaluator_class
|
15
|
+
processor = @processor
|
16
|
+
constructor = @constructor
|
17
|
+
|
18
|
+
target.logged_define_method(@name) do |*args|
|
19
|
+
evaluator = evaluator_class.run(processor.run_args(args), target: self)
|
20
|
+
|
21
|
+
selector = processor.selector(evaluator.selector, args)
|
22
|
+
|
23
|
+
PageEz.reraise_selector_error(selector) do
|
24
|
+
PageEz::HasOneResult.new(
|
25
|
+
container: container,
|
26
|
+
selector: selector,
|
27
|
+
options: evaluator.options,
|
28
|
+
constructor: constructor.method(:new)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasManyDynamicSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, options, &block)
|
7
|
+
@run = false
|
8
|
+
@name = name
|
9
|
+
@options = options
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
return if run?
|
15
|
+
|
16
|
+
if target.method_defined?(@name)
|
17
|
+
target.rename_method from: @name, to: :"_#{@name}"
|
18
|
+
@run = true
|
19
|
+
|
20
|
+
@selector = target.instance_method(:"_#{@name}")
|
21
|
+
else
|
22
|
+
@selector = @name.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
HasManyStaticSelector.new(@name, @selector, nil, @options, &@block).run(target)
|
26
|
+
end
|
27
|
+
|
28
|
+
def selector_type
|
29
|
+
:dynamic
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def run?
|
35
|
+
@run
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasManyOrderedDynamicSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, options, &block)
|
7
|
+
@run = false
|
8
|
+
@name = name
|
9
|
+
@options = options
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
return if run?
|
15
|
+
|
16
|
+
if target.method_defined?(@name)
|
17
|
+
target.rename_method from: @name, to: :"_#{@name}"
|
18
|
+
@run = true
|
19
|
+
|
20
|
+
@selector = target.instance_method(:"_#{@name}")
|
21
|
+
else
|
22
|
+
@selector = @name.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
HasManyOrderedSelector.new(@name, @selector, nil, @options, &@block).run(target)
|
26
|
+
end
|
27
|
+
|
28
|
+
def selector_type
|
29
|
+
:dynamic
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def run?
|
35
|
+
@run
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasManyOrderedSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, selector, dynamic_options, options, &block)
|
7
|
+
@name = name
|
8
|
+
@selector = selector
|
9
|
+
@core_selector = HasManyStaticSelector.new(name, selector, dynamic_options, options, &block)
|
10
|
+
@evaluator_class = SelectorEvaluator.build(@name, dynamic_options: dynamic_options, options: options, selector: selector)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
singularized_name = Pluralization.new(@name).singularize
|
15
|
+
|
16
|
+
constructor = @core_selector.run(target)
|
17
|
+
|
18
|
+
DefineHasOneResultMethods.new(
|
19
|
+
"#{singularized_name}_at",
|
20
|
+
evaluator_class: @evaluator_class,
|
21
|
+
constructor: constructor,
|
22
|
+
processor: IndexedProcessor
|
23
|
+
).run(target)
|
24
|
+
|
25
|
+
DefineHasOnePredicateMethods.new(
|
26
|
+
"#{singularized_name}_at",
|
27
|
+
evaluator_class: @evaluator_class,
|
28
|
+
processor: IndexedProcessor
|
29
|
+
).run(target)
|
30
|
+
end
|
31
|
+
|
32
|
+
def selector_type
|
33
|
+
@core_selector.selector_type
|
34
|
+
end
|
35
|
+
|
36
|
+
class IndexedProcessor
|
37
|
+
def self.run_args(args)
|
38
|
+
args[1..]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.selector(selector, args)
|
42
|
+
"#{selector}:nth-of-type(#{args[0] + 1})"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasManyStaticSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, selector, dynamic_options, options, &block)
|
7
|
+
@name = name
|
8
|
+
@selector = selector
|
9
|
+
@block = block
|
10
|
+
@evaluator_class = SelectorEvaluator.build(name, dynamic_options: dynamic_options, options: options, selector: selector)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
target.constructor_from_block(&@block).tap do |constructor|
|
15
|
+
DefineHasManyResultMethods.new(
|
16
|
+
@name,
|
17
|
+
evaluator_class: @evaluator_class,
|
18
|
+
constructor: constructor
|
19
|
+
).run(target)
|
20
|
+
|
21
|
+
singularized_name = Pluralization.new(@name).singularize
|
22
|
+
|
23
|
+
DefineHasOneResultMethods.new(
|
24
|
+
"#{singularized_name}_matching",
|
25
|
+
evaluator_class: @evaluator_class,
|
26
|
+
constructor: constructor
|
27
|
+
).run(target)
|
28
|
+
|
29
|
+
DefineHasOnePredicateMethods.new(
|
30
|
+
"#{singularized_name}_matching",
|
31
|
+
evaluator_class: @evaluator_class
|
32
|
+
).run(target)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def selector_type
|
37
|
+
:static
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasOneComposedClass
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, composed_class, options, &block)
|
7
|
+
@name = name
|
8
|
+
@composed_class = composed_class
|
9
|
+
@options = options
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
constructor = target.constructor_from_block(@composed_class, &@block)
|
15
|
+
|
16
|
+
base_selector = @options.delete(:base_selector)
|
17
|
+
|
18
|
+
target.logged_define_method(@name) do |*args|
|
19
|
+
if base_selector
|
20
|
+
Class.new(constructor).tap do |new_constructor|
|
21
|
+
new_constructor.base_selector base_selector
|
22
|
+
end.new(self)
|
23
|
+
else
|
24
|
+
constructor.new(self)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if base_selector
|
29
|
+
evaluator_class = SelectorEvaluator.build(
|
30
|
+
@name,
|
31
|
+
dynamic_options: nil,
|
32
|
+
options: @options,
|
33
|
+
selector: base_selector
|
34
|
+
)
|
35
|
+
DefineHasOnePredicateMethods.new(@name, evaluator_class: evaluator_class).run(target)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasOneDynamicSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, options, &block)
|
7
|
+
@run = false
|
8
|
+
@name = name
|
9
|
+
@options = options
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
return if run?
|
15
|
+
|
16
|
+
if target.method_defined?(@name)
|
17
|
+
target.rename_method from: @name, to: :"_#{@name}"
|
18
|
+
@run = true
|
19
|
+
|
20
|
+
@selector = target.instance_method(:"_#{@name}")
|
21
|
+
else
|
22
|
+
@selector = @name.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
HasOneStaticSelector.new(@name, @selector, nil, @options, &@block).run(target)
|
26
|
+
end
|
27
|
+
|
28
|
+
def selector_type
|
29
|
+
:dynamic
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def run?
|
35
|
+
@run
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PageEz
|
2
|
+
module MethodGenerators
|
3
|
+
class HasOneStaticSelector
|
4
|
+
attr_reader :selector
|
5
|
+
|
6
|
+
def initialize(name, selector, dynamic_options, options, &block)
|
7
|
+
@name = name
|
8
|
+
@selector = selector
|
9
|
+
@evaluator_class = SelectorEvaluator.build(name, dynamic_options: dynamic_options, options: options, selector: selector)
|
10
|
+
@block = block
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(target)
|
14
|
+
constructor = target.constructor_from_block(&@block)
|
15
|
+
|
16
|
+
DefineHasOneResultMethods.new(@name, evaluator_class: @evaluator_class, constructor: constructor).run(target)
|
17
|
+
DefineHasOnePredicateMethods.new(@name, evaluator_class: @evaluator_class).run(target)
|
18
|
+
end
|
19
|
+
|
20
|
+
def selector_type
|
21
|
+
:static
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "active_support/core_ext/hash/keys"
|
2
|
+
|
3
|
+
module PageEz
|
4
|
+
class Options
|
5
|
+
def self.merge(options, dynamic_options = nil, *args)
|
6
|
+
dynamic_options ||= -> { {} }
|
7
|
+
|
8
|
+
keys_to_extract = dynamic_options.parameters.filter_map do |type, name|
|
9
|
+
if type == :keyreq || type == :key
|
10
|
+
name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if args.last.is_a?(Hash)
|
15
|
+
if dynamic_options.arity == 0
|
16
|
+
options.merge(*args)
|
17
|
+
else
|
18
|
+
kwargs = args.pop
|
19
|
+
|
20
|
+
if keys_to_extract.empty?
|
21
|
+
options.merge(dynamic_options.call(*args, **kwargs))
|
22
|
+
else
|
23
|
+
sliced = kwargs.slice(*keys_to_extract)
|
24
|
+
except = kwargs.except(*keys_to_extract)
|
25
|
+
options.merge(
|
26
|
+
dynamic_options.call(*args, **sliced)
|
27
|
+
).merge(
|
28
|
+
except
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
else
|
33
|
+
options.merge(dynamic_options.call(*args))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/page_ez/page.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require "capybara/dsl"
|
2
|
+
require "active_support/core_ext/class/attribute"
|
3
|
+
require "active_support/core_ext/module/delegation"
|
4
|
+
|
5
|
+
module PageEz
|
6
|
+
class Page
|
7
|
+
include DelegatesTo[:container]
|
8
|
+
class_attribute :visitor, :macro_registrar, :nested_macro, :container_base_selector
|
9
|
+
|
10
|
+
self.visitor = PageVisitor.new
|
11
|
+
self.macro_registrar = {}
|
12
|
+
self.nested_macro = false
|
13
|
+
self.container_base_selector = nil
|
14
|
+
|
15
|
+
undef_method :select
|
16
|
+
|
17
|
+
def container
|
18
|
+
if container_base_selector
|
19
|
+
@container.find(container_base_selector)
|
20
|
+
else
|
21
|
+
@container
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.base_selector(value)
|
26
|
+
self.container_base_selector = value
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.contains(page_object, only: nil)
|
30
|
+
delegation_target = :"__page_object_#{page_object.object_id}__"
|
31
|
+
|
32
|
+
has_one(delegation_target, page_object)
|
33
|
+
|
34
|
+
if only
|
35
|
+
methods_delegated_that_do_not_exist = only - page_object.instance_methods(false)
|
36
|
+
if methods_delegated_that_do_not_exist.any?
|
37
|
+
raise NoMethodError, "Attempting to delegate non-existent method(s) to #{page_object}: #{methods_delegated_that_do_not_exist.join(", ")}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
delegate(*(only || page_object.instance_methods(false)), to: delegation_target)
|
42
|
+
end
|
43
|
+
|
44
|
+
def initialize(container = nil)
|
45
|
+
@container = container || Class.new do
|
46
|
+
include Capybara::DSL
|
47
|
+
end.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.method_added(name)
|
51
|
+
visitor.track_method_added(name, macro_registrar[name])
|
52
|
+
|
53
|
+
if macro_registrar.key?(name)
|
54
|
+
macro_registrar[name].run(self)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.delegate(...)
|
59
|
+
super(...).tap do |method_names|
|
60
|
+
method_names.each do |method_name|
|
61
|
+
visitor.track_method_delegated(method_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.method_undefined(name)
|
67
|
+
visitor.track_method_undefined(name)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.rename_method(from:, to:)
|
71
|
+
alias_method to, from
|
72
|
+
undef_method from
|
73
|
+
visitor.track_method_renamed(from, to)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.has_one(name, *args, **options, &block)
|
77
|
+
construction_strategy = case [args.length, args.first]
|
78
|
+
in [2, _] then
|
79
|
+
MethodGenerators::HasOneStaticSelector.new(name, args.first.to_s, args[1], options, &block)
|
80
|
+
in [1, Class] then
|
81
|
+
MethodGenerators::HasOneComposedClass.new(name, args.first, options, &block)
|
82
|
+
in [1, String] | [1, Symbol] then
|
83
|
+
MethodGenerators::HasOneStaticSelector.new(name, args.first.to_s, nil, options, &block)
|
84
|
+
in [0, _] then
|
85
|
+
MethodGenerators::HasOneDynamicSelector.new(name, options, &block)
|
86
|
+
end
|
87
|
+
|
88
|
+
visitor.process_macro(:has_one, name, construction_strategy)
|
89
|
+
|
90
|
+
construction_strategy.run(self)
|
91
|
+
|
92
|
+
self.macro_registrar = macro_registrar.merge(name => construction_strategy)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.has_many(name, *args, **options, &block)
|
96
|
+
construction_strategy = case [args.length, args.first]
|
97
|
+
in [2, _] then
|
98
|
+
MethodGenerators::HasManyStaticSelector.new(name, args.first.to_s, args[1], options, &block)
|
99
|
+
in [1, String] | [1, Symbol] then
|
100
|
+
MethodGenerators::HasManyStaticSelector.new(name, args.first.to_s, nil, options, &block)
|
101
|
+
in [0, _] then
|
102
|
+
MethodGenerators::HasManyDynamicSelector.new(name, options, &block)
|
103
|
+
end
|
104
|
+
|
105
|
+
visitor.process_macro(:has_many, name, construction_strategy)
|
106
|
+
|
107
|
+
construction_strategy.run(self)
|
108
|
+
|
109
|
+
self.macro_registrar = macro_registrar.merge(name => construction_strategy)
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.has_many_ordered(name, *args, **options, &block)
|
113
|
+
construction_strategy = case [args.length, args.first]
|
114
|
+
in [2, _] then
|
115
|
+
MethodGenerators::HasManyOrderedSelector.new(name, args.first.to_s, args[1], options, &block)
|
116
|
+
in [1, String] | [1, Symbol] then
|
117
|
+
MethodGenerators::HasManyOrderedSelector.new(name, args.first.to_s, nil, options, &block)
|
118
|
+
in [0, _] then
|
119
|
+
MethodGenerators::HasManyOrderedDynamicSelector.new(name, options, &block)
|
120
|
+
end
|
121
|
+
|
122
|
+
visitor.process_macro(:has_many_ordered, name, construction_strategy)
|
123
|
+
|
124
|
+
construction_strategy.run(self)
|
125
|
+
|
126
|
+
self.macro_registrar = macro_registrar.merge(name => construction_strategy)
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.inherited(subclass)
|
130
|
+
if !nested_macro
|
131
|
+
visitor.reset
|
132
|
+
end
|
133
|
+
|
134
|
+
visitor.inherit_from(subclass)
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.constructor_from_block(superclass = nil, &block)
|
138
|
+
if block
|
139
|
+
self.nested_macro = true
|
140
|
+
Class.new(superclass || self).tap do |klass|
|
141
|
+
visitor.begin_block_evaluation
|
142
|
+
klass.macro_registrar = {}
|
143
|
+
klass.class_eval(&block)
|
144
|
+
visitor.end_block_evaluation
|
145
|
+
end
|
146
|
+
elsif superclass
|
147
|
+
superclass
|
148
|
+
else
|
149
|
+
Class.new(BasicObject) do
|
150
|
+
def self.new(value)
|
151
|
+
value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.logged_define_method(name, &block)
|
158
|
+
visitor.define_method(name)
|
159
|
+
define_method(name, &block)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|