metaruby 1.0.0.rc2 → 1.0.0.rc3
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +4 -0
- data/README.md +4 -4
- data/lib/metaruby.rb +8 -1
- data/lib/metaruby/class.rb +13 -9
- data/lib/metaruby/dsls.rb +6 -0
- data/lib/metaruby/gui.rb +16 -0
- data/lib/metaruby/gui/exception_rendering.rb +281 -0
- data/lib/metaruby/gui/exception_view.rb +32 -111
- data/lib/metaruby/gui/html.rb +7 -0
- data/lib/metaruby/gui/html/button.rb +54 -12
- data/lib/metaruby/gui/html/collection.rb +33 -9
- data/lib/metaruby/gui/html/exception_view.css +4 -6
- data/lib/metaruby/gui/html/list.rhtml +3 -3
- data/lib/metaruby/gui/html/page.rb +233 -53
- data/lib/metaruby/gui/html/page.rhtml +6 -5
- data/lib/metaruby/gui/model_browser.rb +15 -6
- data/lib/metaruby/gui/model_selector.rb +57 -11
- data/lib/metaruby/gui/rendering_manager.rb +36 -7
- data/lib/metaruby/gui/ruby_constants_item_model.rb +155 -42
- data/lib/metaruby/inherited_attribute.rb +59 -8
- data/lib/metaruby/module.rb +29 -12
- data/lib/metaruby/registration.rb +44 -12
- data/lib/metaruby/test.rb +6 -10
- data/lib/metaruby/version.rb +2 -1
- data/lib/yard-metaruby.rb +10 -3
- data/manifest.xml +1 -0
- data/metaruby.gemspec +1 -1
- metadata +5 -4
@@ -1,8 +1,44 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'utilrb/module/dsl_attribute'
|
3
3
|
module MetaRuby
|
4
|
+
# Basic functionality for attributes that are aware of inheritance
|
5
|
+
#
|
6
|
+
# There's basically two main interfaces: {.inherited_single_value_attribute}
|
7
|
+
# and {.inherited_attribute}.
|
8
|
+
#
|
9
|
+
# The former will return the value as set at the lowest level in the
|
10
|
+
# model hierarchy (i.e. on self, then on supermodel if self is unset and so
|
11
|
+
# forth).
|
12
|
+
#
|
13
|
+
# The latter enumerates a collection (e.g. Array, Set or Hash). If a map
|
14
|
+
# is used (such as a Hash), additional functionality gives different choices
|
15
|
+
# as to how the key-value mapping is handled w.r.t. model hierarchy.
|
16
|
+
#
|
17
|
+
# In both cases, a value returned by a submodel is optionally passed through
|
18
|
+
# a promotion method (called #promote_#attributename) which allows to update
|
19
|
+
# the returned value (as e.g. update a possible back-reference of the
|
20
|
+
# enumerated value to its containing model from the original model to the
|
21
|
+
# receiver).
|
22
|
+
#
|
23
|
+
# @example promotion to update back references
|
24
|
+
# class Port; attr_accessor :component_model end
|
25
|
+
# class Component
|
26
|
+
# inherited_attribute(:ports, :port, map: true) { Hash.new }
|
27
|
+
#
|
28
|
+
# # Update #component_model to make it point to the receiver instead
|
29
|
+
# # of the original model. Note that metaruby does not memoize the
|
30
|
+
# # result, so it has to be done in the promote method if it is
|
31
|
+
# # desired
|
32
|
+
# def promote_port(port)
|
33
|
+
# port = port.dup
|
34
|
+
# port.component_model = self
|
35
|
+
# port
|
36
|
+
# end
|
37
|
+
# end
|
4
38
|
module Attributes
|
5
|
-
|
39
|
+
# Internal representation of inherited attributes
|
40
|
+
class InheritedAttribute < Struct.new(:single_value, :name, :accessor_name, :init)
|
41
|
+
end
|
6
42
|
|
7
43
|
# The set of inherited attributes defined on this object
|
8
44
|
# @return [Array<InheritedAttribute>]
|
@@ -35,6 +71,9 @@ module MetaRuby
|
|
35
71
|
|
36
72
|
# Defines an attribute that holds at most a single value
|
37
73
|
#
|
74
|
+
# The value returned by the defined accessor will be the one set at the
|
75
|
+
# lowest level in the model hierarchy (i.e. self, then superclass, ...)
|
76
|
+
#
|
38
77
|
# @param [String] name the attribute name
|
39
78
|
# @return [InheritedAttribute] the attribute definition
|
40
79
|
# @raise [ArgumentError] if no attribute with that name exists
|
@@ -62,6 +101,8 @@ module MetaRuby
|
|
62
101
|
nil
|
63
102
|
end
|
64
103
|
|
104
|
+
# @api private
|
105
|
+
#
|
65
106
|
# Helper method for {#inherited_single_value_attribute} in case there
|
66
107
|
# are no promotion method(s) defined
|
67
108
|
def define_single_value_without_promotion(method_name, ivar)
|
@@ -99,6 +140,8 @@ module MetaRuby
|
|
99
140
|
EOF
|
100
141
|
end
|
101
142
|
|
143
|
+
# @api private
|
144
|
+
#
|
102
145
|
# Helper method for {#inherited_single_value_attribute} in case there is
|
103
146
|
# a promotion method defined
|
104
147
|
def define_single_value_with_promotion(method_name, promotion_method_name, ivar)
|
@@ -146,14 +189,14 @@ module MetaRuby
|
|
146
189
|
# relevant methods and accessors to allow accessing it in a way that
|
147
190
|
# makes sense when embedded in a model hierarchy
|
148
191
|
#
|
149
|
-
# More specifically, it defines a <tt>each_#
|
150
|
-
# instance method and a <tt>each_#
|
192
|
+
# More specifically, it defines a <tt>each_#name(&iterator)</tt>
|
193
|
+
# instance method and a <tt>each_#name(&iterator)</tt>
|
151
194
|
# class method which iterates (in order) on
|
152
|
-
# - the instance #
|
153
|
-
# - the singleton class #
|
154
|
-
# - the class #
|
155
|
-
# - the superclass #
|
156
|
-
# - the superclass' superclass #
|
195
|
+
# - the instance #name attribute
|
196
|
+
# - the singleton class #name attribute
|
197
|
+
# - the class #name attribute
|
198
|
+
# - the superclass #name attribute
|
199
|
+
# - the superclass' superclass #name attribute
|
157
200
|
# ...
|
158
201
|
#
|
159
202
|
# This method can be used on modules, in which case the module is used as if
|
@@ -314,6 +357,8 @@ module MetaRuby
|
|
314
357
|
end
|
315
358
|
end
|
316
359
|
|
360
|
+
# @api private
|
361
|
+
#
|
317
362
|
# Helper class that defines the iteration method for inherited_attribute
|
318
363
|
# when :map is set and there is not promotion method
|
319
364
|
def self.map_without_promotion(name, attribute_name, options)
|
@@ -364,6 +409,8 @@ module MetaRuby
|
|
364
409
|
return code, file, line
|
365
410
|
end
|
366
411
|
|
412
|
+
# @api private
|
413
|
+
#
|
367
414
|
# Helper class that defines the iteration method for inherited_attribute
|
368
415
|
# when :map is not set and there is no promotion method
|
369
416
|
def self.nomap_without_promotion(name, attribute_name, options)
|
@@ -388,6 +435,8 @@ module MetaRuby
|
|
388
435
|
return code, file, line
|
389
436
|
end
|
390
437
|
|
438
|
+
# @api private
|
439
|
+
#
|
391
440
|
# Helper class that defines the iteration method for inherited_attribute
|
392
441
|
# when :map is set and there is a promotion method
|
393
442
|
def self.map_with_promotion(name, attribute_name, options)
|
@@ -453,6 +502,8 @@ module MetaRuby
|
|
453
502
|
return code, file, line
|
454
503
|
end
|
455
504
|
|
505
|
+
# @api private
|
506
|
+
#
|
456
507
|
# Helper class that defines the iteration method for inherited_attribute
|
457
508
|
# when :map is not set and there is a promotion method
|
458
509
|
def self.nomap_with_promotion(name, attribute_name, options)
|
data/lib/metaruby/module.rb
CHANGED
@@ -24,9 +24,18 @@ module MetaRuby
|
|
24
24
|
include Registration
|
25
25
|
extend Attributes
|
26
26
|
|
27
|
-
#
|
27
|
+
# @!method doc
|
28
|
+
# @overload doc
|
29
|
+
# @return [String] the documentation text for this model
|
30
|
+
# @overload doc(new_doc)
|
31
|
+
# @param [String] new_doc the new documentation
|
32
|
+
# @return [String] the documentation text for this model
|
28
33
|
inherited_single_value_attribute :doc
|
29
34
|
|
35
|
+
# Validate that a string can be used as a constant name
|
36
|
+
#
|
37
|
+
# @param [String] name the name to validate
|
38
|
+
# @raise [ArgumentError] if the name cannot be used as a constant name
|
30
39
|
def self.validate_constant_name(name)
|
31
40
|
if name !~ /^[A-Z]\w+$/
|
32
41
|
raise ArgumentError, "#{name} is not a valid model name"
|
@@ -38,6 +47,16 @@ module MetaRuby
|
|
38
47
|
#
|
39
48
|
# It is usually used to create specific DSL-like methods that allow to
|
40
49
|
# create these models
|
50
|
+
#
|
51
|
+
# @param [Module,Class] namespace
|
52
|
+
# @param [String] name the model name, it must be valid for a Ruby
|
53
|
+
# constant name
|
54
|
+
# @param [Module] base_model the base model, which should include
|
55
|
+
# {ModelAsModule} itself
|
56
|
+
# @param [Array] args additional arguments to pass to base_model's
|
57
|
+
# #setup_submodel
|
58
|
+
# @param [#call] block block passed to base_model's #setup_submodel
|
59
|
+
# @return [Module] the new model
|
41
60
|
def self.create_and_register_submodel(namespace, name, base_model, *args, &block)
|
42
61
|
ModelAsModule.validate_constant_name(name)
|
43
62
|
|
@@ -68,6 +87,8 @@ module MetaRuby
|
|
68
87
|
# True if this model is a root model
|
69
88
|
attr_predicate :root?, true
|
70
89
|
|
90
|
+
# @!attribute [rw] name
|
91
|
+
#
|
71
92
|
# Sets a name on this model
|
72
93
|
#
|
73
94
|
# Only use this on 'anonymous models', i.e. on models that are not
|
@@ -83,25 +104,21 @@ module MetaRuby
|
|
83
104
|
@name = name
|
84
105
|
end
|
85
106
|
|
86
|
-
# Set the root model
|
107
|
+
# Set or get the root model
|
87
108
|
attr_accessor :supermodel
|
88
109
|
|
89
110
|
# Creates a new DataServiceModel that is a submodel of +self+
|
90
111
|
#
|
91
|
-
# @param [
|
92
|
-
# @option options [String] :name the submodel name. Use this option
|
112
|
+
# @param [String] name the submodel name. Use this option
|
93
113
|
# only for "anonymous" models, i.e. models that won't be
|
94
114
|
# registered on a Ruby constant
|
95
|
-
# @
|
115
|
+
# @param [Class] type (self.class) the type of the submodel
|
96
116
|
#
|
97
|
-
def new_submodel(
|
98
|
-
|
99
|
-
:name => nil, :type => self.class
|
100
|
-
|
101
|
-
model = options[:type].new
|
117
|
+
def new_submodel(name: nil, type: self.class, **submodel_options, &block)
|
118
|
+
model = type.new
|
102
119
|
model.extend ModelAsModule
|
103
|
-
if
|
104
|
-
model.name =
|
120
|
+
if name
|
121
|
+
model.name = name.dup
|
105
122
|
end
|
106
123
|
model.definition_location = call_stack
|
107
124
|
setup_submodel(model, submodel_options, &block)
|
@@ -3,6 +3,7 @@ require 'facets/module/basename'
|
|
3
3
|
require 'facets/kernel/call_stack'
|
4
4
|
require 'utilrb/object/attribute'
|
5
5
|
require 'utilrb/module/attr_predicate'
|
6
|
+
|
6
7
|
module MetaRuby
|
7
8
|
# Handling of registration of model hierarchies
|
8
9
|
#
|
@@ -21,8 +22,10 @@ module MetaRuby
|
|
21
22
|
# @return [Boolean]
|
22
23
|
attr_predicate :permanent_model?, true
|
23
24
|
|
24
|
-
# @
|
25
|
-
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
# @return [Array<WeakRef>] the set of models that are children of this one
|
28
|
+
attribute(:submodels) { Array.new }
|
26
29
|
|
27
30
|
# Returns the model that is parent of this one
|
28
31
|
#
|
@@ -34,6 +37,11 @@ module MetaRuby
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
40
|
+
# Returns whether a model is a submodel of self
|
41
|
+
def has_submodel?(model)
|
42
|
+
each_submodel.any? { |m| m == model }
|
43
|
+
end
|
44
|
+
|
37
45
|
# @return [Boolean] true if the definition context (module, class) in
|
38
46
|
# which self is registered is permanent or not w.r.t. the model
|
39
47
|
# registration functionality of metaruby
|
@@ -75,7 +83,7 @@ module MetaRuby
|
|
75
83
|
klass.definition_location = call_stack
|
76
84
|
end
|
77
85
|
|
78
|
-
submodels << klass
|
86
|
+
submodels << WeakRef.new(klass)
|
79
87
|
if m = supermodel
|
80
88
|
m.register_submodel(klass)
|
81
89
|
end
|
@@ -84,11 +92,23 @@ module MetaRuby
|
|
84
92
|
# Enumerates all models that are submodels of this class
|
85
93
|
def each_submodel
|
86
94
|
return enum_for(:each_submodel) if !block_given?
|
87
|
-
submodels.
|
88
|
-
|
95
|
+
submodels.delete_if do |obj|
|
96
|
+
begin
|
97
|
+
yield(obj.__getobj__)
|
98
|
+
false
|
99
|
+
rescue WeakRef::RefError
|
100
|
+
true
|
101
|
+
end
|
89
102
|
end
|
90
103
|
end
|
91
104
|
|
105
|
+
# Clears this model
|
106
|
+
#
|
107
|
+
# It deregisters sef if it is not a {#permanent_model?}, and clears the
|
108
|
+
# submodels
|
109
|
+
#
|
110
|
+
# Model classes and modules should also clear their respective
|
111
|
+
# attributes (if there are any)
|
92
112
|
def clear_model
|
93
113
|
if !permanent_model?
|
94
114
|
if m = supermodel
|
@@ -110,9 +130,9 @@ module MetaRuby
|
|
110
130
|
constant("::#{obj.spacename}").send(:remove_const, obj.basename)
|
111
131
|
end
|
112
132
|
|
113
|
-
#
|
133
|
+
# Recursively deregisters all non-permanent submodels
|
114
134
|
def clear_submodels
|
115
|
-
children =
|
135
|
+
children = each_submodel.find_all { |m| !m.permanent_model? }
|
116
136
|
if !children.empty?
|
117
137
|
deregister_submodels(children)
|
118
138
|
end
|
@@ -130,25 +150,37 @@ module MetaRuby
|
|
130
150
|
# We can call #clear_submodels while iterating here as it is a
|
131
151
|
# constraint that all models in #submodels are permanent (and
|
132
152
|
# will therefore not be removed)
|
133
|
-
|
153
|
+
each_submodel { |m| m.clear_submodels }
|
134
154
|
# And this the non-permanent ones
|
135
155
|
children.each { |m| m.clear_submodels }
|
136
156
|
true
|
137
157
|
end
|
138
158
|
|
159
|
+
# @api private
|
160
|
+
#
|
139
161
|
# Deregisters a set of submodels on this model and all its
|
140
162
|
# supermodels
|
141
163
|
#
|
142
164
|
# This is usually not called directly. Use #clear_submodels instead
|
143
165
|
#
|
144
|
-
# @param [
|
166
|
+
# @param [Set] set the set of submodels to remove
|
145
167
|
def deregister_submodels(set)
|
146
|
-
|
147
|
-
submodels.
|
168
|
+
has_match = false
|
169
|
+
submodels.delete_if do |m|
|
170
|
+
begin
|
171
|
+
m = m.__getobj__
|
172
|
+
if set.include?(m)
|
173
|
+
has_match = true
|
174
|
+
end
|
175
|
+
rescue WeakRef::RefError
|
176
|
+
true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
148
180
|
if m = supermodel
|
149
181
|
m.deregister_submodels(set)
|
150
182
|
end
|
151
|
-
|
183
|
+
has_match
|
152
184
|
end
|
153
185
|
end
|
154
186
|
end
|
data/lib/metaruby/test.rb
CHANGED
@@ -34,30 +34,26 @@ end
|
|
34
34
|
module MetaRuby
|
35
35
|
# This module is the common setup for all tests
|
36
36
|
#
|
37
|
-
# It
|
37
|
+
# It is included in all the minitest tests
|
38
38
|
#
|
39
39
|
# @example
|
40
40
|
# require 'metaruby/test'
|
41
41
|
# describe MetaRuby do
|
42
|
-
#
|
42
|
+
# # Use helpers methods from SelfTest here
|
43
43
|
# end
|
44
44
|
#
|
45
45
|
module SelfTest
|
46
|
+
# Common setup code for all metaruby tests
|
46
47
|
def setup
|
47
|
-
# Setup code for all the tests
|
48
48
|
end
|
49
49
|
|
50
|
+
# Common teardown code for all metaruby tests
|
50
51
|
def teardown
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
include MetaRuby::SelfTest
|
58
|
-
end
|
59
|
-
class Test
|
60
|
-
include MetaRuby::SelfTest
|
61
|
-
end
|
56
|
+
class Minitest::Test
|
57
|
+
include MetaRuby::SelfTest
|
62
58
|
end
|
63
59
|
|
data/lib/metaruby/version.rb
CHANGED
data/lib/yard-metaruby.rb
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
require 'pp'
|
2
2
|
module MetaRuby
|
3
|
+
# Yard plugin to handle some of the metaruby DSL methods
|
4
|
+
#
|
5
|
+
# This is used by adding
|
6
|
+
#
|
7
|
+
# --plugin metaruby
|
8
|
+
#
|
9
|
+
# to the .yardopts file
|
3
10
|
module YARD
|
4
11
|
include ::YARD
|
12
|
+
|
13
|
+
# Handling of {Attributes#inherited_attribute}
|
5
14
|
class InheritedAttributeHandler < YARD::Handlers::Ruby::AttributeHandler
|
6
15
|
handles method_call(:inherited_attribute)
|
7
16
|
namespace_only
|
8
17
|
|
9
|
-
|
10
|
-
end
|
11
|
-
|
18
|
+
# Callback handled by YARD
|
12
19
|
def process
|
13
20
|
name = statement.parameters[0].jump(:tstring_content, :ident).source
|
14
21
|
if statement.parameters.size == 4
|
data/manifest.xml
CHANGED
data/metaruby.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.extra_rdoc_files = ["README.md"]
|
19
19
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
20
|
|
21
|
-
s.add_runtime_dependency "utilrb", ">=
|
21
|
+
s.add_runtime_dependency "utilrb", ">= 3.0.0.a"
|
22
22
|
s.add_runtime_dependency "kramdown"
|
23
23
|
s.add_development_dependency "flexmock", ">= 2.0.0"
|
24
24
|
s.add_development_dependency "minitest", ">= 5.0", "~> 5.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metaruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Joyeux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: utilrb
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 3.0.0.a
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 3.0.0.a
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: kramdown
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,6 +106,7 @@ files:
|
|
106
106
|
- lib/metaruby/dsls/doc.rb
|
107
107
|
- lib/metaruby/dsls/find_through_method_missing.rb
|
108
108
|
- lib/metaruby/gui.rb
|
109
|
+
- lib/metaruby/gui/exception_rendering.rb
|
109
110
|
- lib/metaruby/gui/exception_view.rb
|
110
111
|
- lib/metaruby/gui/html.rb
|
111
112
|
- lib/metaruby/gui/html/button.rb
|