prop_initializer 0.3.0 → 0.5.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 +4 -4
- data/README.md +21 -6
- data/Rakefile +8 -2
- data/lib/prop_initializer/null.rb +4 -4
- data/lib/prop_initializer/properties/schema.rb +121 -114
- data/lib/prop_initializer/properties.rb +14 -2
- data/lib/prop_initializer/property.rb +183 -179
- data/lib/prop_initializer/version.rb +1 -1
- data/lib/prop_initializer.rb +0 -2
- metadata +3 -5
- data/lib/prop_initializer/railtie.rb +0 -6
- data/lib/tasks/prop_initializer_tasks.rake +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4dc72d5e414e9bd4690aeab766d53f8d00258f9a917ad40ca74300acab1cec12
|
|
4
|
+
data.tar.gz: '068996afcdb7cb460c9fcf90b8bec7b30b5694675628b1f9efc0799b6e6e9aaa'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9393c607fb3f5fcf2e2cac36d69ea4bd07c5bcdad53954e32b34f599ce037f86ccacae6d050312b5b2a879e558521aad77113a94548c64ed371f5fb4f43f1ee
|
|
7
|
+
data.tar.gz: 14ec41b36d29501ef2e8cf8f58993a5f63d0549c3eebc8e182ee3e49c27b15e4522db669919c28caddb788e82361ece5bd1a9f6dee99dce7ab32c3de6d4e44e3
|
data/README.md
CHANGED
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
# Prop Initializer
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
## Overview
|
|
6
8
|
|
|
7
9
|
The `prop_initializer` gem is a flexible tool for defining properties on Ruby classes.
|
|
8
10
|
|
|
9
|
-

|
|
10
|
-
|
|
11
11
|
It's a fork of the [Literal Gem](https://github.com/joeldrapper/literal), with a few tweaks. We sincerely thank [Joel Drapper](https://github.com/joeldrapper) for the inspiration and base code that made this possible.
|
|
12
12
|
|
|
13
13
|
With `prop_initializer`, you can easily declare properties for any class, giving you flexible options for default values and more. However, the scope is narrowed down by removing strict typing requirements, providing a more lightweight and adaptable interface.
|
|
14
14
|
|
|
15
15
|
## Installation
|
|
16
16
|
|
|
17
|
-
To use `prop_initializer
|
|
17
|
+
To use `prop_initializer` in your Ruby project, add the following to your Gemfile:
|
|
18
18
|
|
|
19
19
|
```ruby
|
|
20
20
|
gem "prop_initializer"
|
|
@@ -28,7 +28,7 @@ bundle install
|
|
|
28
28
|
|
|
29
29
|
## Usage
|
|
30
30
|
|
|
31
|
-
To start using `prop_initializer
|
|
31
|
+
To start using `prop_initializer`, you need to extend the class with the module where you want to define properties.
|
|
32
32
|
|
|
33
33
|
### Step 1: Extend the Properties Module
|
|
34
34
|
|
|
@@ -42,7 +42,7 @@ end
|
|
|
42
42
|
|
|
43
43
|
### Step 2: Define Properties
|
|
44
44
|
|
|
45
|
-
Properties can be declared using the `prop` method
|
|
45
|
+
Properties can be declared using the `prop` method. The generated initializer assigns each one to an instance variable (e.g., `@name`, `@size`, etc.).
|
|
46
46
|
|
|
47
47
|
#### Basic Syntax:
|
|
48
48
|
|
|
@@ -53,6 +53,13 @@ prop :args, kind: :* # A property for handling splat arguments
|
|
|
53
53
|
prop :kwargs, kind: :** # A property for handling keyword arguments
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
A default must be a frozen value or a proc. A proc runs on each new instance once the positional and splat properties, and the keyword properties declared before it, are assigned, so it can read them:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
prop :count, default: 2
|
|
60
|
+
prop :items, default: -> { Array.new(@count) }
|
|
61
|
+
```
|
|
62
|
+
|
|
56
63
|
#### Custom Property with Block:
|
|
57
64
|
|
|
58
65
|
You can define a custom processing block when declaring a property, for example:
|
|
@@ -65,7 +72,7 @@ end
|
|
|
65
72
|
|
|
66
73
|
### Step 3: Accessing Properties
|
|
67
74
|
|
|
68
|
-
By default, `PropInitializer` generates
|
|
75
|
+
By default, `PropInitializer` generates no reader or writer. The properties are stored as instance variables, which can be accessed within the class:
|
|
69
76
|
|
|
70
77
|
```ruby
|
|
71
78
|
@name # Accesses the value of the 'name' property
|
|
@@ -86,6 +93,14 @@ This will automatically generate a public getter method, allowing you to retriev
|
|
|
86
93
|
my_class_instance.title # Public getter for the 'title' property
|
|
87
94
|
```
|
|
88
95
|
|
|
96
|
+
#### Writer and Predicate:
|
|
97
|
+
|
|
98
|
+
`writer: :public` adds a setter and `predicate: :public` a `title?` method. A setter runs the property's block, if it has one, the same way the initializer does.
|
|
99
|
+
|
|
100
|
+
#### after_initialize:
|
|
101
|
+
|
|
102
|
+
Define `after_initialize`, public or private, and it runs once every property is assigned.
|
|
103
|
+
|
|
89
104
|
### Example:
|
|
90
105
|
|
|
91
106
|
```ruby
|
data/Rakefile
CHANGED
|
@@ -2,118 +2,125 @@
|
|
|
2
2
|
|
|
3
3
|
# @api private
|
|
4
4
|
class PropInitializer::Properties::Schema
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def initialize(properties_index: {}, sorted_properties: [])
|
|
8
|
+
@properties_index = properties_index
|
|
9
|
+
@sorted_properties = sorted_properties
|
|
10
|
+
@mutex = Mutex.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :properties_index
|
|
14
|
+
|
|
15
|
+
def [](key)
|
|
16
|
+
@properties_index[key]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def <<(value)
|
|
20
|
+
@mutex.synchronize do
|
|
21
|
+
@properties_index[value.name] = value
|
|
22
|
+
# ruby's sort is unstable, this trick makes it stable
|
|
23
|
+
n = 0
|
|
24
|
+
@sorted_properties = @properties_index.values.sort_by! { |it| n += 1; [ it, n ] }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def dup
|
|
31
|
+
self.class.new(
|
|
32
|
+
properties_index: @properties_index.dup,
|
|
33
|
+
sorted_properties: @sorted_properties.dup,
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def each(&)
|
|
38
|
+
@sorted_properties.each(&)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def size
|
|
42
|
+
@sorted_properties.size
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def generate_initializer(buffer = +"")
|
|
46
|
+
buffer << "alias initialize initialize\n" \
|
|
47
|
+
"def initialize(#{generate_initializer_params})\n"
|
|
48
|
+
generate_initializer_body(buffer)
|
|
49
|
+
buffer << "" \
|
|
50
|
+
" after_initialize() if respond_to?(:after_initialize, true)\n" \
|
|
51
|
+
"end\n"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def generate_to_h(buffer = +"")
|
|
55
|
+
buffer << "alias to_h to_h\n" \
|
|
56
|
+
"def to_h\n" << " {\n"
|
|
57
|
+
|
|
58
|
+
sorted_properties = @sorted_properties
|
|
59
|
+
i, n = 0, sorted_properties.size
|
|
60
|
+
while i < n
|
|
61
|
+
property = sorted_properties[i]
|
|
62
|
+
buffer << " " << property.name.name << ": @" << property.name.name << ",\n"
|
|
63
|
+
i += 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
buffer << " }\n" << "end\n"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def generate_initializer_params(buffer = +"")
|
|
72
|
+
sorted_properties = @sorted_properties
|
|
73
|
+
i, n = 0, sorted_properties.size
|
|
74
|
+
while i < n
|
|
75
|
+
property = sorted_properties[i]
|
|
76
|
+
|
|
77
|
+
case property.kind
|
|
78
|
+
when :*
|
|
79
|
+
buffer << "*" << property.escaped_name
|
|
80
|
+
when :**
|
|
81
|
+
buffer << "**" << property.escaped_name
|
|
82
|
+
when :&
|
|
83
|
+
buffer << "&" << property.escaped_name
|
|
84
|
+
when :positional
|
|
85
|
+
buffer << property.escaped_name << " = " << generate_initializer_default(property)
|
|
86
|
+
when :keyword
|
|
87
|
+
buffer << property.name.name << ": " << generate_initializer_default(property)
|
|
88
|
+
else
|
|
89
|
+
raise "You should never see this error."
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
i += 1
|
|
93
|
+
buffer << ", " if i < n
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
buffer
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def generate_initializer_default(property)
|
|
100
|
+
if property.inline_default?
|
|
101
|
+
property.default.inspect
|
|
102
|
+
elsif property.default?
|
|
103
|
+
"PropInitializer::Null"
|
|
104
|
+
else
|
|
105
|
+
"nil"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def generate_initializer_body(buffer = +"")
|
|
110
|
+
if @sorted_properties.any?(&:lookup?)
|
|
111
|
+
buffer << " __pi_properties = self.class.prop_initializer_properties.properties_index\n"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
generate_initializer_handle_properties(@sorted_properties, buffer)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def generate_initializer_handle_properties(properties, buffer = +"")
|
|
118
|
+
i, n = 0, properties.size
|
|
119
|
+
while i < n
|
|
120
|
+
properties[i].generate_initializer_handle_property(buffer)
|
|
121
|
+
i += 1
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
buffer
|
|
125
|
+
end
|
|
119
126
|
end
|
|
@@ -13,7 +13,7 @@ module PropInitializer::Properties
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
unless PropInitializer::Property::VISIBILITY_OPTIONS.include?(predicate)
|
|
16
|
-
raise ArgumentError.new(
|
|
16
|
+
raise ArgumentError.new("The predicate must be one of #{PropInitializer::Property::VISIBILITY_OPTIONS.map(&:inspect).join(', ')}.")
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
if reader && :class == name
|
|
@@ -39,6 +39,8 @@ module PropInitializer::Properties
|
|
|
39
39
|
prop_initializer_properties << property
|
|
40
40
|
__define_prop_initializer_methods__(property)
|
|
41
41
|
include(__prop__initializer_extension__)
|
|
42
|
+
|
|
43
|
+
name
|
|
42
44
|
end
|
|
43
45
|
|
|
44
46
|
def prop_initializer_properties
|
|
@@ -67,7 +69,17 @@ module PropInitializer::Properties
|
|
|
67
69
|
if defined?(@__prop__initializer_extension__)
|
|
68
70
|
@__prop__initializer_extension__
|
|
69
71
|
else
|
|
70
|
-
@__prop__initializer_extension__ = Module.new
|
|
72
|
+
@__prop__initializer_extension__ = Module.new do
|
|
73
|
+
set_temporary_name "PropInitializer::Properties(Extension)" if respond_to?(:set_temporary_name)
|
|
74
|
+
|
|
75
|
+
def initialize
|
|
76
|
+
after_initialize if respond_to?(:after_initialize, true)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def to_h
|
|
80
|
+
{}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
71
83
|
end
|
|
72
84
|
end
|
|
73
85
|
|
|
@@ -1,183 +1,187 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class PropInitializer::Property
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
4
|
+
ORDER = { :positional => 0, :* => 1, :keyword => 2, :** => 3, :& => 4 }.freeze
|
|
5
|
+
RUBY_KEYWORDS = %i[alias and begin break case class def do else elsif end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield].to_h { |k| [ k, "__#{k}__" ] }.freeze
|
|
6
|
+
GENERATOR_PROPERTY_LOCAL = "__pi_prop"
|
|
7
|
+
|
|
8
|
+
VISIBILITY_OPTIONS = Set[false, :private, :protected, :public].freeze
|
|
9
|
+
KIND_OPTIONS = Set[:positional, :*, :keyword, :**, :&].freeze
|
|
10
|
+
|
|
11
|
+
include Comparable
|
|
12
|
+
|
|
13
|
+
def initialize(name:, kind:, reader:, writer:, predicate:, default:, coercion:)
|
|
14
|
+
@name = name
|
|
15
|
+
@kind = kind
|
|
16
|
+
@reader = reader
|
|
17
|
+
@writer = writer
|
|
18
|
+
@predicate = predicate
|
|
19
|
+
@default = default
|
|
20
|
+
@coercion = coercion
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :name, :kind, :reader, :writer, :predicate, :default, :coercion
|
|
24
|
+
|
|
25
|
+
def optional?
|
|
26
|
+
default?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def required?
|
|
30
|
+
!optional?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def keyword?
|
|
34
|
+
@kind == :keyword
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def positional?
|
|
38
|
+
@kind == :positional
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def splat?
|
|
42
|
+
@kind == :*
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def double_splat?
|
|
46
|
+
@kind == :**
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def block?
|
|
50
|
+
@kind == :&
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def default?
|
|
54
|
+
nil != @default
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Symbol, Integer, true and false go into the signature as literals, so the initializer never looks the
|
|
58
|
+
# property up. Not for a block parameter, and not for a Symbol the generated UTF-8 source cannot spell.
|
|
59
|
+
def inline_default?
|
|
60
|
+
return false unless positional? || keyword?
|
|
61
|
+
|
|
62
|
+
Integer === @default || true == @default || false == @default ||
|
|
63
|
+
(Symbol === @default && (Encoding::UTF_8 == @default.encoding || Encoding::US_ASCII == @default.encoding))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def lookup?
|
|
67
|
+
(default? && !inline_default?) || !!@coercion
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def param
|
|
71
|
+
case @kind
|
|
72
|
+
when :*
|
|
73
|
+
"*#{escaped_name}"
|
|
74
|
+
when :**
|
|
75
|
+
"**#{escaped_name}"
|
|
76
|
+
when :&
|
|
77
|
+
"&#{escaped_name}"
|
|
78
|
+
when :positional
|
|
79
|
+
escaped_name
|
|
80
|
+
when :keyword
|
|
81
|
+
"#{@name.name}:"
|
|
82
|
+
else
|
|
83
|
+
raise "You should never see this error."
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def <=>(other)
|
|
88
|
+
ORDER[@kind] <=> ORDER[other.kind]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def ruby_keyword?
|
|
92
|
+
!!RUBY_KEYWORDS[@name]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def escaped_name
|
|
96
|
+
RUBY_KEYWORDS[@name] || @name.name
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def generate_reader_method(buffer = +"")
|
|
100
|
+
buffer << @reader.name << " attr_reader :" << @name.name << "\n"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def generate_writer_method(buffer = +"")
|
|
104
|
+
return buffer << @writer.name << " attr_writer :" << @name.name << "\n" unless @coercion
|
|
105
|
+
|
|
106
|
+
# Through self.class at call time, not captured: a subclass may redeclare the prop with another block,
|
|
107
|
+
# or with none, and still inherit this writer.
|
|
108
|
+
buffer <<
|
|
109
|
+
@writer.name << " def " << @name.name << "=(value)\n" \
|
|
110
|
+
" coercion = self.class.prop_initializer_properties[:" << @name.name << "].coercion\n" \
|
|
111
|
+
" @" << @name.name << " = coercion ? instance_exec(value, &coercion) : value\n" \
|
|
112
|
+
"end\n"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def generate_predicate_method(buffer = +"")
|
|
116
|
+
buffer <<
|
|
117
|
+
(@predicate ? @predicate.name : "public") <<
|
|
118
|
+
" def " <<
|
|
119
|
+
@name.name <<
|
|
120
|
+
"?\n" <<
|
|
121
|
+
" !!@" <<
|
|
122
|
+
@name.name <<
|
|
123
|
+
"\n" <<
|
|
124
|
+
"end\n"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def generate_initializer_handle_property(buffer = +"")
|
|
128
|
+
buffer << " # " << @name.name << "\n"
|
|
129
|
+
|
|
130
|
+
if lookup?
|
|
131
|
+
buffer << " #{GENERATOR_PROPERTY_LOCAL} = __pi_properties[:" << @name.name << "]\n"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if @kind == :keyword && ruby_keyword?
|
|
135
|
+
generate_initializer_escape_keyword(buffer)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if default? && !inline_default?
|
|
139
|
+
generate_initializer_assign_default(buffer)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if @coercion
|
|
143
|
+
generate_initializer_coerce_property(buffer)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
generate_initializer_assign_value(buffer)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
private
|
|
150
|
+
|
|
151
|
+
def generate_initializer_escape_keyword(buffer = +"")
|
|
152
|
+
buffer <<
|
|
153
|
+
escaped_name <<
|
|
154
|
+
" = ::Kernel.binding.local_variable_get(:" <<
|
|
155
|
+
@name.name <<
|
|
156
|
+
")\n"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def generate_initializer_coerce_property(buffer = +"")
|
|
160
|
+
buffer <<
|
|
161
|
+
" " <<
|
|
162
|
+
escaped_name <<
|
|
163
|
+
" = instance_exec(" <<
|
|
164
|
+
escaped_name <<
|
|
165
|
+
", &#{GENERATOR_PROPERTY_LOCAL}.coercion)\n"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def generate_initializer_assign_default(buffer = +"")
|
|
169
|
+
buffer <<
|
|
170
|
+
" if " <<
|
|
171
|
+
((@kind == :&) ? "nil" : "PropInitializer::Null") <<
|
|
172
|
+
" == " <<
|
|
173
|
+
escaped_name <<
|
|
174
|
+
"\n " <<
|
|
175
|
+
escaped_name <<
|
|
176
|
+
" = " << (Proc === @default ? "instance_exec(&#{GENERATOR_PROPERTY_LOCAL}.default)" : "#{GENERATOR_PROPERTY_LOCAL}.default") << "\n end\n"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def generate_initializer_assign_value(buffer = +"")
|
|
180
|
+
buffer <<
|
|
181
|
+
" @" <<
|
|
182
|
+
@name.name <<
|
|
183
|
+
" = " <<
|
|
184
|
+
escaped_name <<
|
|
185
|
+
"\n"
|
|
186
|
+
end
|
|
183
187
|
end
|
data/lib/prop_initializer.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: prop_initializer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paul Bob
|
|
@@ -40,9 +40,7 @@ files:
|
|
|
40
40
|
- lib/prop_initializer/properties.rb
|
|
41
41
|
- lib/prop_initializer/properties/schema.rb
|
|
42
42
|
- lib/prop_initializer/property.rb
|
|
43
|
-
- lib/prop_initializer/railtie.rb
|
|
44
43
|
- lib/prop_initializer/version.rb
|
|
45
|
-
- lib/tasks/prop_initializer_tasks.rake
|
|
46
44
|
homepage: https://github.com/avo-hq/prop_initializer
|
|
47
45
|
licenses:
|
|
48
46
|
- MIT
|
|
@@ -55,14 +53,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
55
53
|
requirements:
|
|
56
54
|
- - ">="
|
|
57
55
|
- !ruby/object:Gem::Version
|
|
58
|
-
version:
|
|
56
|
+
version: 3.2.0
|
|
59
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
58
|
requirements:
|
|
61
59
|
- - ">="
|
|
62
60
|
- !ruby/object:Gem::Version
|
|
63
61
|
version: '0'
|
|
64
62
|
requirements: []
|
|
65
|
-
rubygems_version:
|
|
63
|
+
rubygems_version: 4.0.16
|
|
66
64
|
specification_version: 4
|
|
67
65
|
summary: A flexible property initializer for Ruby classes inspired by the Literal
|
|
68
66
|
gem.
|