jrubyfx 1.1.0-java → 2.0.0-java
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/README.md +21 -10
- data/lib/jrubyfx/application.rb +3 -3
- data/lib/jrubyfx/compiler_app.rb +2 -0
- data/lib/jrubyfx/controller.rb +91 -34
- data/lib/jrubyfx/core_ext/exts.yml +9 -1
- data/lib/jrubyfx/core_ext/observable_value.rb +20 -2
- data/lib/jrubyfx/core_ext/precompiled.rb +1865 -742
- data/lib/jrubyfx/core_ext/stage.rb +1 -1
- data/lib/jrubyfx/dsl.rb +14 -4
- data/lib/jrubyfx/dsl_control.rb +28 -0
- data/lib/jrubyfx/dsl_map.rb +487 -9
- data/lib/jrubyfx/fxml_helper.rb +134 -0
- data/lib/jrubyfx/imports.rb +503 -26
- data/lib/jrubyfx/module.rb +31 -0
- data/lib/jrubyfx/part_imports.rb +67 -52
- data/lib/jrubyfx/utils/common_converters.rb +3 -0
- data/lib/jrubyfx/utils/string_utils.rb +48 -0
- data/lib/jrubyfx/utils.rb +29 -3
- data/lib/jrubyfx/version.rb +1 -1
- data/lib/jrubyfx.rb +7 -5
- data/lib/jrubyfx_tasks.rb +7 -3
- metadata +54 -80
- data/lib/jrubyfx/java_fx_impl.rb +0 -143
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2663b39ced8255fd70b6666efcf58ad87133d4a385f5f01dc8fd6d9797ebf298
|
4
|
+
data.tar.gz: ec875fdd53ca592f9023004b83595d902d8dd74a680a2b3830df71a744369b4c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dee292568c4247cff866bccffab39a1f2ee1928c95c776649540a459a3edb5f3d4b90ae49a17b50906f38e96a24f4ca0d0ecf3235d3d6c1ce702c606fefb2170
|
7
|
+
data.tar.gz: f3e259057d479843db42ed9e9582a2e3acbd64fa214221a639dbc6d965fa86f456e3e4b96e0e734971a1c4989829d335600457ec9be61b7dd373675535d61c6b
|
data/README.md
CHANGED
@@ -1,24 +1,34 @@
|
|
1
1
|
JRubyFX
|
2
2
|
=======
|
3
|
-
JRubyFX is a pure ruby wrapper for JavaFX 2.2+ with FXML support
|
3
|
+
JRubyFX is a pure ruby wrapper for JavaFX 2.2+ with FXML support. Currently supported: Java 8+, JRuby 9.3+.
|
4
4
|
|
5
5
|
Status
|
6
6
|
------
|
7
|
-
JRubyFX master should be usable in its current form and able to run
|
8
|
-
|
7
|
+
JRubyFX master should be usable in its current form and able to run most FXML apps.
|
8
|
+
As of JRubyFX 2.0, the Java FXML Loader is used. This requires JRuby 9.3+.
|
9
|
+
Please see the [JRubyFX github wiki](https://github.com/jruby/jrubyfx/wiki/) for upgrading from 1.x.
|
9
10
|
|
10
11
|
Install
|
11
12
|
-----
|
13
|
+
|
14
|
+
For JRuby 9.3.4+:
|
15
|
+
|
12
16
|
```text
|
13
17
|
gem install jrubyfx
|
14
18
|
```
|
19
|
+
For older JRuby versions:
|
20
|
+
|
21
|
+
```text
|
22
|
+
gem install jrubyfx -v 1.2
|
23
|
+
```
|
24
|
+
|
25
|
+
If you are using Java 9+, additionally append the contents of `module-opens.txt` to `bin/.jruby.java_opts` in your jruby install. If you fail to do this, you may get inscruitable "method X not found, did you mean X?" errors.
|
15
26
|
|
16
27
|
Manual Build and Install
|
17
28
|
-----
|
18
|
-
Build is done using rake/gem/bundler/rdoc. You need JRuby
|
29
|
+
Build is done using rake/gem/bundler/rdoc. You need JRuby >= 9.3.4.0, Java >= 8 with JavaFX 11 modules installed (only required for `reflect` task). Building native application packages requires JDK 8+.
|
19
30
|
|
20
31
|
```text
|
21
|
-
gem install jrubyfx-fxmlloader
|
22
32
|
rake install
|
23
33
|
```
|
24
34
|
Once the gem is installed, just run a ruby file that uses it normally.
|
@@ -26,7 +36,11 @@ Once the gem is installed, just run a ruby file that uses it normally.
|
|
26
36
|
**NOTE:** If you don't have JRuby installed as the `ruby` command, use `jruby -S rake` instead of `rake`. If
|
27
37
|
you are using RVM, this does not apply to you (though make sure you `rvm use jruby`).
|
28
38
|
|
29
|
-
**If you are reporting bugs or encountering fxml issues:** please
|
39
|
+
**If you are reporting bugs or encountering fxml issues:** please ensure you are using JRubyFX 2.0. Prior version relied on a ported fxml parser and had many known issues.
|
40
|
+
|
41
|
+
Updating the Imports
|
42
|
+
--------------
|
43
|
+
JRubyFX currently uses the 11-based classes for the default imports (part_imports.rb). In the future, this list may change. See `gen_tree.rb` for a script to help automate finding the classes to import.
|
30
44
|
|
31
45
|
Creating a Jar
|
32
46
|
--------------
|
@@ -94,16 +108,13 @@ If you want rdoc, run `rake rdoc`. Please note that there are lots of generated
|
|
94
108
|
|
95
109
|
Issues
|
96
110
|
------
|
97
|
-
* Use JRubyFX-FxmlLoader's FxmlLoader instead of javafx.fxml.FXMLLoader for maximum Ruby support.
|
98
|
-
* FXML support in master for very complex documents is untested. Report bugs against JRubyFX-FxmlLoader with the FXML file if it fails.
|
99
|
-
* You must use the provided JavaFXImpl::Launcher to launch the app (aka: call _yourFXApplicationClass_.launch())
|
100
111
|
* Errors loading JavaFX are bugs. Please report if you encounter this issue, tell us your platform, OS, and version of JRuby
|
101
112
|
* Jarify command needs the `jar` executable in your path.
|
102
113
|
* Any other difficulties are bugs. Please report them
|
103
114
|
|
104
115
|
Contact
|
105
116
|
-------
|
106
|
-
Find us in #jruby on
|
117
|
+
Find us in #jruby on matrix.
|
107
118
|
|
108
119
|
License
|
109
120
|
-------
|
data/lib/jrubyfx/application.rb
CHANGED
@@ -27,7 +27,7 @@ class JRubyFX::Application < Java.javafx.application.Application
|
|
27
27
|
# and, if jruby changes, false negatives. If you are using this, it might be a
|
28
28
|
# very bad idea... (though it is handy)
|
29
29
|
def self.in_jar?()
|
30
|
-
$LOAD_PATH.inject(false) { |res,i| res || i.include?("
|
30
|
+
$LOAD_PATH.inject(false) { |res,i| res || i.include?("/META-INF/jruby.home/lib/ruby/")}
|
31
31
|
end
|
32
32
|
|
33
33
|
##
|
@@ -36,7 +36,7 @@ class JRubyFX::Application < Java.javafx.application.Application
|
|
36
36
|
#
|
37
37
|
# When called on a subclass, this is effectively our main method.
|
38
38
|
def self.launch(*args)
|
39
|
-
#
|
40
|
-
|
39
|
+
# Note: object args are no longer allowed
|
40
|
+
Java.javafx.application.Application.launch(self.become_java!, args.map(&:to_s).to_java(:string))
|
41
41
|
end
|
42
42
|
end
|
data/lib/jrubyfx/compiler_app.rb
CHANGED
data/lib/jrubyfx/controller.rb
CHANGED
@@ -15,28 +15,39 @@ See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
16
16
|
=end
|
17
17
|
|
18
|
-
require 'jrubyfx
|
18
|
+
require 'jrubyfx/utils/string_utils'
|
19
|
+
require 'jrubyfx/fxml_helper'
|
20
|
+
require 'jruby/core_ext'
|
19
21
|
|
20
22
|
# Special methods for fxml loading
|
21
23
|
module Kernel
|
22
24
|
@@jrubyfx_res_dir = {}
|
23
|
-
|
25
|
+
@@jrubyfx_fxml_res_cl = nil
|
26
|
+
def fxml_root(value=nil, jar_value=nil, get_resources: nil, fxml_class_loader: nil)
|
27
|
+
@@jrubyfx_fxml_res_cl = get_resources if get_resources
|
28
|
+
@@jrubyfx_fxml_main_cl = fxml_class_loader if fxml_class_loader
|
24
29
|
if value or jar_value
|
25
|
-
@@jrubyfx_fxml_dir = JRubyFX::Application.in_jar? ? jar_value : File.expand_path(value)
|
30
|
+
@@jrubyfx_fxml_dir = (JRubyFX::Application.in_jar? and jar_value) ? jar_value : File.expand_path(value)
|
26
31
|
else
|
27
32
|
@@jrubyfx_fxml_dir
|
28
33
|
end
|
29
34
|
end
|
30
35
|
def resource_root(res_name, value=nil, jar_value=nil)
|
31
36
|
if value or jar_value
|
32
|
-
@@jrubyfx_res_dir[res_name.to_sym] = JRubyFX::Application.in_jar? ? jar_value : File.expand_path(value)
|
37
|
+
@@jrubyfx_res_dir[res_name.to_sym] = (JRubyFX::Application.in_jar? and jar_value) ? jar_value : File.expand_path(value)
|
33
38
|
else
|
34
39
|
@@jrubyfx_res_dir[res_name.to_sym]
|
35
40
|
end
|
36
41
|
end
|
42
|
+
def get_fxml_resource_class_loader
|
43
|
+
@@jrubyfx_fxml_res_cl || JRuby.runtime.jruby_class_loader.method("get_resource")
|
44
|
+
end
|
45
|
+
def get_fxml_classes_class_loader
|
46
|
+
@@jrubyfx_fxml_main_cl ||= JRubyFX::PolyglotClassLoader.new
|
47
|
+
end
|
37
48
|
def resource_url(type, relative_path)
|
38
49
|
if JRubyFX::Application.in_jar?
|
39
|
-
|
50
|
+
get_fxml_resource_class_loader.call("#{resource_root(type)}/#{relative_path}")
|
40
51
|
else
|
41
52
|
java.net.URL.new("file:" + File.join(resource_root(type), relative_path))
|
42
53
|
end
|
@@ -64,8 +75,12 @@ module JRubyFX::Controller
|
|
64
75
|
|
65
76
|
def self.included(base)
|
66
77
|
base.extend(ClassMethods)
|
67
|
-
base.extend(JRubyFX::FXMLClassUtils)
|
78
|
+
base.extend(JRubyFX::FXMLClassUtils) if defined? JRubyFX::FXMLClassUtils
|
68
79
|
base.extend(JRubyFX::FXImports)
|
80
|
+
base.configure_java_class ctor_name: "java_ctor" do
|
81
|
+
dispatch :initialize, :fx_initialize # we want to load our code before calling user code
|
82
|
+
# un-exclude "initialize"
|
83
|
+
end
|
69
84
|
# register ourselves as a control. overridable with custom_fxml_control
|
70
85
|
register_type base if base.is_a? Class
|
71
86
|
end
|
@@ -102,10 +117,20 @@ module JRubyFX::Controller
|
|
102
117
|
def load_into(stage, settings={})
|
103
118
|
# Inherit from default settings
|
104
119
|
settings = DEFAULT_SETTINGS.merge({root_dir: (self.instance_variable_get("@fxml_root_dir") || fxml_root),
|
120
|
+
get_resources: get_fxml_resource_class_loader,
|
121
|
+
fxml_class_loader: get_fxml_classes_class_loader,
|
105
122
|
filename: self.instance_variable_get("@filename")}).merge settings
|
106
|
-
|
107
|
-
|
108
|
-
|
123
|
+
|
124
|
+
raise "JRubyFX 1.x style class loader argument passed into 'load_into'. Replace 'class_loader' with either 'get_resources' (likely) or 'fxml_class_loader' (less likely)" if settings.has_key? :class_loader
|
125
|
+
|
126
|
+
unless @built
|
127
|
+
## Use the temporary loader to reformat AController
|
128
|
+
JRubyFX::FxmlHelper.transform self, Controller.get_fxml_location(settings[:root_dir], settings[:filename], settings[:get_resources])
|
129
|
+
|
130
|
+
# Custom controls don't always need to be pure java, but oh well...
|
131
|
+
become_java!
|
132
|
+
@built = true
|
133
|
+
end
|
109
134
|
|
110
135
|
# like new, without initialize
|
111
136
|
ctrl = allocate
|
@@ -114,7 +139,7 @@ module JRubyFX::Controller
|
|
114
139
|
ctrl.stage = stage
|
115
140
|
|
116
141
|
# load the FXML file
|
117
|
-
root = Controller.get_fxml_loader(settings[:filename], ctrl, settings[:root_dir]).load
|
142
|
+
root = Controller.get_fxml_loader(settings[:filename], ctrl, settings[:root_dir], settings[:get_resources], settings[:fxml_class_loader]).load
|
118
143
|
|
119
144
|
# Unless the FXML root node is a scene, wrap that node in a scene
|
120
145
|
if root.is_a? Scene
|
@@ -136,14 +161,24 @@ module JRubyFX::Controller
|
|
136
161
|
if @preparsed && @preparsed.length > 0
|
137
162
|
return @preparsed.pop.finish_initialization(*args, &block)
|
138
163
|
end
|
164
|
+
|
165
|
+
settings = DEFAULT_SETTINGS.merge({root_dir: @fxml_root_dir || fxml_root, get_resources: get_fxml_resource_class_loader,
|
166
|
+
fxml_class_loader: get_fxml_classes_class_loader, filename: @filename})
|
167
|
+
|
139
168
|
# Custom controls don't always need to be pure java, but oh well...
|
140
|
-
|
169
|
+
if @filename && !@built
|
170
|
+
@built = true # TODO: move later if no new :bake call
|
171
|
+
## Use the temporary loader to reformat AController
|
172
|
+
JRubyFX::FxmlHelper.transform self, Controller.get_fxml_location(settings[:root_dir], settings[:filename], settings[:get_resources])
|
173
|
+
|
174
|
+
# Custom controls don't always need to be pure java, but oh well...
|
175
|
+
become_java!
|
176
|
+
end
|
141
177
|
|
142
178
|
# like new, without initialize
|
143
179
|
ctrl = allocate
|
144
180
|
|
145
|
-
ctrl.initialize_controller(
|
146
|
-
filename: @filename}),
|
181
|
+
ctrl.initialize_controller(settings,
|
147
182
|
*args, &block) if @filename
|
148
183
|
|
149
184
|
# return the controller
|
@@ -220,17 +255,22 @@ module JRubyFX::Controller
|
|
220
255
|
end
|
221
256
|
end
|
222
257
|
end
|
258
|
+
|
259
|
+
# java initialize is redirected to here
|
260
|
+
def fx_initialize()
|
261
|
+
# Do nothing, as we already control initialization
|
262
|
+
end
|
223
263
|
|
224
264
|
#default java ctor, override for arguments
|
225
|
-
def java_ctor(
|
226
|
-
|
265
|
+
def java_ctor(*initialize_arguments)
|
266
|
+
super()
|
227
267
|
end
|
228
268
|
|
229
269
|
# Initialize all controllers
|
230
270
|
def initialize_controller(options={}, *args, &block)
|
231
|
-
|
271
|
+
|
232
272
|
# JRuby complains loudly (probably broken behavior) if we don't call the ctor
|
233
|
-
|
273
|
+
__jallocate!() # TODO: args? TODO: non-java controllers?*args) # TODO: remove
|
234
274
|
|
235
275
|
# load the FXML file with the current control as the root
|
236
276
|
load_fxml options[:filename], options[:root_dir]
|
@@ -242,14 +282,14 @@ module JRubyFX::Controller
|
|
242
282
|
def pre_initialize_controller(options={})
|
243
283
|
|
244
284
|
# JRuby complains loudly (probably broken behavior) if we don't call the ctor
|
245
|
-
java_ctor self.class.
|
285
|
+
java_ctor self.class.instance_method(:__jallocate!).bind(self), [] #TODO: do we need to call this now with []?
|
246
286
|
|
247
287
|
# load the FXML file with the current control as the root
|
248
288
|
load_fxml options[:filename], options[:root_dir]
|
249
289
|
end
|
250
290
|
|
251
291
|
def load_fxml(filename, root_dir=nil)
|
252
|
-
fx = Controller.get_fxml_loader(filename, self, root_dir || @fxml_root_dir || fxml_root)
|
292
|
+
fx = Controller.get_fxml_loader(filename, self, root_dir || @fxml_root_dir || fxml_root, get_fxml_resource_class_loader, get_fxml_classes_class_loader)
|
253
293
|
fx.root = self
|
254
294
|
fx.load
|
255
295
|
end
|
@@ -261,7 +301,7 @@ module JRubyFX::Controller
|
|
261
301
|
self.scene = self unless @scene
|
262
302
|
|
263
303
|
# Everything is ready, call initialize
|
264
|
-
if private_methods.include? :initialize
|
304
|
+
if private_methods.include? :initialize or methods.include? :initialize
|
265
305
|
self.send :initialize, *args, &block
|
266
306
|
end
|
267
307
|
|
@@ -294,10 +334,14 @@ module JRubyFX::Controller
|
|
294
334
|
def self.load_fxml_only(filename, stage, settings={})
|
295
335
|
# Inherit from default settings
|
296
336
|
settings = DEFAULT_SETTINGS.merge({root_dir: fxml_root,
|
337
|
+
get_resources: get_fxml_resource_class_loader,
|
338
|
+
fxml_class_loader: get_fxml_classes_class_loader,
|
297
339
|
filename: filename}).merge settings
|
298
|
-
|
340
|
+
|
341
|
+
raise "JRubyFX 1.x style class loader argument passed into 'load_fxml_only'. Replace 'class_loader' with either 'get_resources' (likely) or 'fxml_class_loader' (less likely)" if settings.has_key? :class_loader
|
342
|
+
|
299
343
|
# load the FXML file
|
300
|
-
root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir]).load
|
344
|
+
root = Controller.get_fxml_loader(settings[:filename], nil, settings[:root_dir], settings[:get_resources], settings[:fxml_class_loader]).load
|
301
345
|
|
302
346
|
# TODO: de-duplicate this code
|
303
347
|
|
@@ -330,20 +374,33 @@ module JRubyFX::Controller
|
|
330
374
|
# === Equivalent Java
|
331
375
|
# Parent root = FXMLLoader.load(getClass().getResource("Demo.fxml"));
|
332
376
|
#
|
333
|
-
def self.get_fxml_loader(filename, controller = nil, root_dir = nil)
|
334
|
-
fx =
|
335
|
-
|
336
|
-
if JRubyFX::Application.in_jar?
|
337
|
-
# If we are in a jar file, use the class loader to get the file from the jar (like java)
|
338
|
-
# TODO: should just be able to use URLs
|
339
|
-
JRuby.runtime.jruby_class_loader.get_resource File.join(root_dir, filename)
|
340
|
-
else
|
341
|
-
root_dir ||= fxml_root
|
342
|
-
# If we are in the normal filesystem, create a file url path relative to relative_to or this file
|
343
|
-
URL.new "file:#{File.join root_dir, filename}"
|
344
|
-
end
|
377
|
+
def self.get_fxml_loader(filename, controller = nil, root_dir = nil, get_resources = JRuby.runtime.jruby_class_loader.method("get_resource"), fxml_class_loader=nil)
|
378
|
+
fx = javafx.fxml.FXMLLoader.new(get_fxml_location(root_dir, filename, get_resources))
|
379
|
+
fx.class_loader = fxml_class_loader unless fxml_class_loader.nil?
|
345
380
|
# we must set this here for JFX to call our events
|
346
381
|
fx.controller = controller
|
347
382
|
fx
|
348
383
|
end
|
384
|
+
|
385
|
+
def self.get_fxml_location(root_dir, filename, get_resources)
|
386
|
+
if JRubyFX::Application.in_jar? and filename.match(/^[^.\/]/)
|
387
|
+
# If we are in a jar file, use the class loader to get the file from the jar (like java)
|
388
|
+
# TODO: should just be able to use URLs
|
389
|
+
|
390
|
+
# According to how class loader works, the correct path for a file inside a jar is NOT "/folder/file.fxml"
|
391
|
+
# but "folder/file.fxml" (without starting "/" or ".", which would both make the path to be seen as a filesystem
|
392
|
+
# reference) so we assume that if root_dir is set to "" or to any other path not starting with "." or "/" then
|
393
|
+
# we want to point to a folder inside the jar, otherwise to a filesystem's one. According to this we format and
|
394
|
+
# feed the right path to the class loader.
|
395
|
+
|
396
|
+
location = get_resources.call(File.join(root_dir, filename))
|
397
|
+
|
398
|
+
# fall back if not found
|
399
|
+
return location if location
|
400
|
+
end
|
401
|
+
|
402
|
+
root_dir ||= fxml_root
|
403
|
+
# If we are in the normal filesystem, create a file url path relative to relative_to or this file
|
404
|
+
URL.new "file:#{File.join root_dir, filename}"
|
405
|
+
end
|
349
406
|
end
|
@@ -16,6 +16,9 @@
|
|
16
16
|
"Java::JavafxSceneControl::TreeItem":
|
17
17
|
method_missing: "Java::JavafxSceneControl::TreeItem"
|
18
18
|
add: get_children
|
19
|
+
"Java::JavafxSceneControl::TreeTableView":
|
20
|
+
method_missing: "Java::JavafxSceneControl::TreeItem"
|
21
|
+
add: get_children
|
19
22
|
"Java::JavafxSceneControl::TableView":
|
20
23
|
method_missing: "Java::JavafxSceneControl::TableColumn"
|
21
24
|
add: get_columns
|
@@ -39,6 +42,8 @@
|
|
39
42
|
"Java::JavafxAnimation::Timeline":
|
40
43
|
method_missing: "Java::JavafxAnimation::KeyFrame"
|
41
44
|
add: key_frames
|
45
|
+
"Java::JavafxSceneLayout::BackgroundFill":
|
46
|
+
new_converter: [[color, none, none]]
|
42
47
|
"Java::JavafxSceneShape::Path":
|
43
48
|
add: elements
|
44
49
|
rotate: []
|
@@ -51,7 +56,10 @@
|
|
51
56
|
logical_children: panes
|
52
57
|
"Java::JavafxSceneShape::Circle":
|
53
58
|
new_converter: [[], [none], [none, color], [none, none, none], [none, none, none, color]]
|
59
|
+
"Java::JavafxSceneShape::Rectangle":
|
60
|
+
new_converter: [[], [none, none], [none, none, none, none], [none, none, color]]
|
54
61
|
"Java::JavafxScenePaint::Stop":
|
55
62
|
new_converter: [[none, color]]
|
56
63
|
"Java::JavafxSceneShape::Shape":
|
57
|
-
getter_setter: fill
|
64
|
+
getter_setter: fill
|
65
|
+
|
@@ -131,6 +131,24 @@ module Java::javafx::collections::ObservableMap
|
|
131
131
|
# stores the listeners.
|
132
132
|
end
|
133
133
|
|
134
|
+
module Java::javafx::beans::binding::NumberExpression
|
135
|
+
def - x
|
136
|
+
subtract x
|
137
|
+
end
|
138
|
+
def / x
|
139
|
+
divide x
|
140
|
+
end
|
141
|
+
def * x
|
142
|
+
multiply x
|
143
|
+
end
|
144
|
+
def + x
|
145
|
+
add x
|
146
|
+
end
|
147
|
+
def -@ x
|
148
|
+
negate x
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
134
152
|
class Class
|
135
153
|
def property_writer(*symbol_names)
|
136
154
|
symbol_names.each do |symbol_name|
|
@@ -147,8 +165,8 @@ class Class
|
|
147
165
|
end
|
148
166
|
end
|
149
167
|
def property_accessor(*symbol_names)
|
150
|
-
property_reader
|
151
|
-
property_writer
|
168
|
+
property_reader(*symbol_names)
|
169
|
+
property_writer(*symbol_names)
|
152
170
|
symbol_names.each do |symbol_name|
|
153
171
|
send(:define_method, symbol_name.id2name + "_property") do
|
154
172
|
instance_variable_get("@#{symbol_name}")
|