drain 0.1.0 → 0.2.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 +5 -5
- data/.gitignore +6 -2
- data/.travis.yml +10 -0
- data/.yardopts +6 -1
- data/Gemfile +7 -0
- data/LICENSE.txt +1 -1
- data/README.md +11 -5
- data/Rakefile +7 -12
- data/drain.gemspec +15 -5
- data/gemspec.yml +4 -3
- data/lib/dr.rb +1 -0
- data/lib/{drain → dr}/base.rb +0 -0
- data/lib/{drain → dr}/base/bool.rb +0 -0
- data/lib/dr/base/converter.rb +33 -0
- data/lib/{drain → dr}/base/encoding.rb +0 -0
- data/lib/dr/base/eruby.rb +284 -0
- data/lib/{drain → dr}/base/functional.rb +2 -2
- data/lib/dr/base/graph.rb +378 -0
- data/lib/dr/base/utils.rb +28 -0
- data/lib/dr/parse.rb +1 -0
- data/lib/dr/parse/simple_parser.rb +70 -0
- data/lib/{drain → dr}/parse/time_parse.rb +0 -0
- data/lib/dr/ruby_ext.rb +1 -0
- data/lib/dr/ruby_ext/core_ext.rb +7 -0
- data/lib/{drain/ruby_ext/core_ext.rb → dr/ruby_ext/core_modules.rb} +67 -27
- data/lib/{drain → dr}/ruby_ext/meta_ext.rb +57 -30
- data/lib/dr/tools.rb +1 -0
- data/lib/{drain → dr}/tools/gtk.rb +0 -0
- data/lib/dr/version.rb +4 -0
- data/lib/drain.rb +2 -1
- data/test/helper.rb +12 -1
- data/test/test_converter.rb +42 -0
- data/test/test_core_ext.rb +116 -0
- data/test/test_graph.rb +126 -0
- data/test/test_meta.rb +65 -0
- data/test/test_simple_parser.rb +41 -0
- metadata +45 -21
- data/.document +0 -3
- data/lib/drain/base/eruby.rb +0 -28
- data/lib/drain/base/graph.rb +0 -213
- data/lib/drain/parse.rb +0 -5
- data/lib/drain/parse/simple_parser.rb +0 -61
- data/lib/drain/ruby_ext.rb +0 -5
- data/lib/drain/tools.rb +0 -5
- data/lib/drain/tools/git.rb +0 -116
- data/lib/drain/version.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2a6165b74687b54296ee9b273eac4465746de73b9774eb5466fd550031897cba
|
4
|
+
data.tar.gz: 915728a74d0050b45fec8167e51e2b08c3657defb5fc3187b25b4aca2ff18fb4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f1c013bdb8158298fec2a204063d142a328840e9f3bea214036932ddc59f696aca94549190df72b95b3110dbea295f7a2e240bd69dbb3ed7264911a201517297
|
7
|
+
data.tar.gz: 4cdffbe87293046d6752bd64a0e7e17224b16786d39cb5ff4f4537a5ed3da6722060acf44475774c4bc788f4b09abbb66cf85833e8027cc990fb79fc862f001c
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/.yardopts
CHANGED
data/Gemfile
ADDED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,25 +1,31 @@
|
|
1
1
|
# drain
|
2
2
|
|
3
3
|
* [Homepage](https://github.com/DamienRobert/drain#readme)
|
4
|
-
* [Gems]("https://rubygems.org/gems/drain)
|
5
4
|
* [Issues](https://github.com/DamienRobert/drain/issues)
|
6
|
-
* [Documentation](http://rubydoc.info/gems/drain
|
5
|
+
* [Documentation](http://rubydoc.info/gems/drain)
|
7
6
|
* [Email](mailto:Damien.Olivier.Robert+gems at gmail.com)
|
8
7
|
|
8
|
+
[](https://rubygems.org/gems/drain)
|
9
|
+
[](https://travis-ci.org/DamienRobert/drain)
|
10
|
+
|
9
11
|
## Description
|
10
12
|
|
11
13
|
Drain is a small set of libraries that I use in my other gems.
|
12
14
|
The Api is far from stable yet, so use at your own risk!
|
13
15
|
|
16
|
+
## Warning
|
17
|
+
|
18
|
+
For now the API is experimental and some parts are not ready to use!
|
19
|
+
|
14
20
|
## Install
|
15
21
|
|
16
22
|
$ gem install drain
|
17
23
|
|
18
24
|
## Copyright
|
19
25
|
|
20
|
-
Copyright
|
26
|
+
Copyright © 2015–2017 Damien Robert
|
21
27
|
|
22
|
-
MIT License. See
|
28
|
+
MIT License. See [LICENSE.txt](./LICENSE.txt) for details.
|
23
29
|
|
24
30
|
Some of the code is inspired by other project, in general I give proper
|
25
|
-
|
31
|
+
acknowledgement in the corresponding file.
|
data/Rakefile
CHANGED
@@ -1,20 +1,16 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
1
|
require 'rake'
|
5
2
|
|
6
3
|
begin
|
7
|
-
gem 'rubygems-tasks', '~> 0.2'
|
8
4
|
require 'rubygems/tasks'
|
9
|
-
|
10
|
-
|
5
|
+
Gem::Tasks.new(sign: {checksum: true, pgp: true},
|
6
|
+
scm: {status: true}) do |tasks|
|
7
|
+
tasks.console.command = 'pry'
|
8
|
+
end
|
11
9
|
rescue LoadError => e
|
12
10
|
warn e.message
|
13
|
-
warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
|
14
11
|
end
|
15
12
|
|
16
13
|
require 'rake/testtask'
|
17
|
-
|
18
14
|
Rake::TestTask.new do |test|
|
19
15
|
test.libs << 'test'
|
20
16
|
test.pattern = 'test/**/test_*.rb'
|
@@ -22,13 +18,12 @@ Rake::TestTask.new do |test|
|
|
22
18
|
end
|
23
19
|
|
24
20
|
begin
|
25
|
-
gem 'yard', '~> 0.8'
|
26
21
|
require 'yard'
|
27
|
-
|
28
|
-
YARD::Rake::YardocTask.new
|
22
|
+
YARD::Rake::YardocTask.new
|
29
23
|
rescue LoadError => e
|
30
24
|
task :yard do
|
31
|
-
|
25
|
+
warn e.message
|
32
26
|
end
|
33
27
|
end
|
34
28
|
task :doc => :yard
|
29
|
+
|
data/drain.gemspec
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
require 'yaml'
|
4
2
|
|
5
3
|
Gem::Specification.new do |gem|
|
@@ -10,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
10
8
|
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
9
|
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
10
|
|
13
|
-
require '
|
14
|
-
|
11
|
+
require 'dr/version'
|
12
|
+
DR::VERSION
|
15
13
|
end
|
16
14
|
|
17
15
|
gem.summary = gemspec['summary']
|
@@ -24,6 +22,16 @@ Gem::Specification.new do |gem|
|
|
24
22
|
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
25
23
|
|
26
24
|
gem.files = `git ls-files`.split($/)
|
25
|
+
|
26
|
+
`git submodule --quiet foreach --recursive pwd`.split($/).each do |submodule|
|
27
|
+
submodule.sub!("#{Dir.pwd}/",'')
|
28
|
+
|
29
|
+
Dir.chdir(submodule) do
|
30
|
+
`git ls-files`.split($/).map do |subpath|
|
31
|
+
gem.files << File.join(submodule,subpath)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
27
35
|
gem.files = glob[gemspec['files']] if gemspec['files']
|
28
36
|
|
29
37
|
gem.executables = gemspec.fetch('executables') do
|
@@ -38,7 +46,7 @@ Gem::Specification.new do |gem|
|
|
38
46
|
%w[ext lib].select { |dir| File.directory?(dir) }
|
39
47
|
})
|
40
48
|
|
41
|
-
gem.requirements = gemspec['requirements']
|
49
|
+
gem.requirements = Array(gemspec['requirements'])
|
42
50
|
gem.required_ruby_version = gemspec['required_ruby_version']
|
43
51
|
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
44
52
|
gem.post_install_message = gemspec['post_install_message']
|
@@ -56,4 +64,6 @@ Gem::Specification.new do |gem|
|
|
56
64
|
gem.add_development_dependency(name,split[versions])
|
57
65
|
end
|
58
66
|
end
|
67
|
+
|
68
|
+
gem.metadata['yard.run']='yri'
|
59
69
|
end
|
data/gemspec.yml
CHANGED
@@ -8,6 +8,7 @@ email: Damien.Olivier.Robert+gems@gmail.com
|
|
8
8
|
homepage: https://github.com/DamienRobert/drain#readme
|
9
9
|
|
10
10
|
development_dependencies:
|
11
|
-
minitest: ~> 5.0
|
12
|
-
|
13
|
-
|
11
|
+
minitest: "~> 5.0"
|
12
|
+
rake: "~> 10"
|
13
|
+
rubygems-tasks: "~> 0.2"
|
14
|
+
yard: "~> 0.8"
|
data/lib/dr.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'dr/version'
|
data/lib/{drain → dr}/base.rb
RENAMED
File without changes
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DR
|
2
|
+
module Converter
|
3
|
+
extend self
|
4
|
+
#convert an obj to hash, using 'methods' for the methods attributes
|
5
|
+
def to_hash(obj=nil, methods:[], recursive: false, check: false, compact: false)
|
6
|
+
return {} if obj.nil?
|
7
|
+
obj||=self
|
8
|
+
stack=[*obj]
|
9
|
+
processed=[]
|
10
|
+
klass=stack.first.class
|
11
|
+
h={}
|
12
|
+
while !stack.empty?
|
13
|
+
obj=stack.shift
|
14
|
+
next if processed.include?(obj)
|
15
|
+
processed << obj
|
16
|
+
attributes={}
|
17
|
+
methods.each do |m|
|
18
|
+
next if check and !obj.respond_to? m
|
19
|
+
v=obj.public_send(m)
|
20
|
+
attributes[m]=v
|
21
|
+
if recursive
|
22
|
+
vals=v.kind_of?(Enumerable) ? v.to_a.flatten : [v]
|
23
|
+
vals.select! {|v| v.kind_of?(klass)}
|
24
|
+
stack.concat(vals)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
attributes=attributes.values.first if compact and attributes.keys.length == 1
|
28
|
+
h[obj]=attributes
|
29
|
+
end
|
30
|
+
h
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
@@ -0,0 +1,284 @@
|
|
1
|
+
module DR
|
2
|
+
class Eruby
|
3
|
+
module BindingHelper
|
4
|
+
extend self
|
5
|
+
#complement TOPLEVEL_BINDING
|
6
|
+
def empty_binding
|
7
|
+
#wraps into anonymous module so that 'def foo' do not pollute namespace
|
8
|
+
Module.new do
|
9
|
+
#regenerate a new binding
|
10
|
+
return binding
|
11
|
+
end
|
12
|
+
end
|
13
|
+
#empty binding (at first) that stays the same and can be shared
|
14
|
+
EMPTY_BINDING = empty_binding
|
15
|
+
BLANK_OBJECT=Object.new
|
16
|
+
|
17
|
+
# add variables values to a binding; variables is a Hash
|
18
|
+
def add_variables(variables, _binding=empty_binding)
|
19
|
+
eval variables.collect{|k,v| "#{k} = variables[#{k.inspect}]; "}.join, _binding
|
20
|
+
_binding
|
21
|
+
end
|
22
|
+
|
23
|
+
#From Tilt/template.rb
|
24
|
+
#return a string extracting local_keys from a hash named _context
|
25
|
+
def local_extraction(local_keys, context_name: '_context')
|
26
|
+
local_keys.map do |k|
|
27
|
+
if k.to_s =~ /\A[a-z_][a-zA-Z_0-9]*\z/
|
28
|
+
"#{k} = #{context_name}[#{k.inspect}]"
|
29
|
+
else
|
30
|
+
raise "invalid locals key: #{k.inspect} (keys must be variable names)"
|
31
|
+
end
|
32
|
+
end.join("\n")+"\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
module EngineHelper
|
38
|
+
### Stolen from erubis
|
39
|
+
## eval(@src) with binding object
|
40
|
+
def result(_binding_or_hash=BindingHelper.empty_binding)
|
41
|
+
_arg = _binding_or_hash
|
42
|
+
if _arg.is_a?(Hash)
|
43
|
+
_b=BindingHelper.add_variables(_arg, BindingHelper.empty_binding)
|
44
|
+
elsif _arg.is_a?(Binding)
|
45
|
+
_b = _arg
|
46
|
+
elsif _arg.nil?
|
47
|
+
_b = binding
|
48
|
+
else
|
49
|
+
raise ArgumentError.new("#{self.class.name}#result(): argument should be Binding or Hash but passed #{_arg.class.name} object.")
|
50
|
+
end
|
51
|
+
return eval(@src, _b, (@filename || '(eruby'))
|
52
|
+
#erb.rb:
|
53
|
+
# if @safe_level
|
54
|
+
# proc {
|
55
|
+
# $SAFE = @safe_level
|
56
|
+
# eval(@src, b, (@filename || '(erb)'), @lineno)
|
57
|
+
# }.call
|
58
|
+
end
|
59
|
+
|
60
|
+
#Note that when the result is not used afterwards via "instance_eval"
|
61
|
+
#then the Klass of binding is important when src has 'def foo...'
|
62
|
+
#If set, locals should be an array of variable names
|
63
|
+
def compile(wrap: :proc, bind: BindingHelper.empty_binding, locals: nil, pre: nil, post: nil, context_name: '_context')
|
64
|
+
src=@src
|
65
|
+
src=BindingHelper.local_extraction(locals, context_name: context_name)+src if locals
|
66
|
+
src=pre+"\n"+src if pre
|
67
|
+
src<< post+"\n" if post
|
68
|
+
to_eval=case wrap
|
69
|
+
when :eval; @src
|
70
|
+
when :lambda; "lambda { |#{context_name}| #{src} }"
|
71
|
+
when :proc; "Proc.new { |#{context_name}| #{src} }"
|
72
|
+
when :module; "Module.new { |#{context_name}| #{src} }"
|
73
|
+
when :unbound
|
74
|
+
#wrapping in a method allows us to pass a block to a code
|
75
|
+
#calling yield
|
76
|
+
require 'dr/ruby_ext/meta_ext'
|
77
|
+
return Meta.get_unbound_evalmethod('eruby', src, args: context_name)
|
78
|
+
when :unbound_instance
|
79
|
+
#here we wrap in a method that the calls instance_eval
|
80
|
+
require 'dr/ruby_ext/meta_ext'
|
81
|
+
return Meta.get_unbound_evalmethod('eruby', <<-RUBY, args: context_name)
|
82
|
+
self.instance_eval do
|
83
|
+
#{src}
|
84
|
+
end
|
85
|
+
RUBY
|
86
|
+
when :string
|
87
|
+
src.to_s
|
88
|
+
else
|
89
|
+
warn "wrap meth #{warn} not understood, defaulting to String"
|
90
|
+
src
|
91
|
+
end
|
92
|
+
return eval(to_eval, bind, "(wrap #{@filename})")
|
93
|
+
end
|
94
|
+
|
95
|
+
## by default invoke context.instance_eval(@src)
|
96
|
+
def evaluate(_context=Context.new, compile: {}, **opts, &b)
|
97
|
+
#I prefer to pass context as a keyword, but we allow to pass it as
|
98
|
+
#an argument to respect erubis's api
|
99
|
+
_context=opts[:context] if opts.key?(:context)
|
100
|
+
_context = Context.new(_context) if _context.is_a?(Hash)
|
101
|
+
vars=opts[:vars]
|
102
|
+
compile[:locals]||=vars.keys if vars
|
103
|
+
#to pass a block we need to wrap in a method
|
104
|
+
compile[:wrap]||=:unbound_instance if b
|
105
|
+
_proc=compile(**compile)
|
106
|
+
Eruby.evaluate(_proc, context: _context, **opts, &b)
|
107
|
+
end
|
108
|
+
|
109
|
+
## if object is an Class or Module then define instance method to it,
|
110
|
+
## else define singleton method to it.
|
111
|
+
def def_method(object, method_name, filename=nil)
|
112
|
+
m = object.is_a?(Module) ? :module_eval : :instance_eval
|
113
|
+
object.__send__(m, "def #{method_name}; #{@src}; end", filename || @filename || '(eruby)')
|
114
|
+
#erb.rb: src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n" #This pattern insert the 'def' after lines with leading comments
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class Template
|
119
|
+
include EngineHelper
|
120
|
+
|
121
|
+
def initialize(src, filename: nil)
|
122
|
+
if src.respond_to?(:read)
|
123
|
+
filename=src unless filename
|
124
|
+
src=src.read
|
125
|
+
end
|
126
|
+
@filename=filename || self.class.inspect
|
127
|
+
@src=src
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
module ClassHelpers
|
133
|
+
def process_eruby(eruby_src, **opts, &b)
|
134
|
+
src=Eruby::Engine.new(eruby_src).src
|
135
|
+
process_ruby(src, **opts, &b)
|
136
|
+
end
|
137
|
+
|
138
|
+
def process_ruby(src, src_info: nil, **opts, &b)
|
139
|
+
Template.new(src, filename: src_info).evaluate(**opts, &b)
|
140
|
+
end
|
141
|
+
|
142
|
+
def evaluate(_proc, context: Context.new, vars: nil, &b)
|
143
|
+
#we can only pass the block b when we get an UnboundMethod
|
144
|
+
if _proc.is_a?(UnboundMethod)
|
145
|
+
vars={} if _proc.arity > 0 and vars.nil?
|
146
|
+
if !vars.nil?
|
147
|
+
_proc.bind(context).call(vars,&b)
|
148
|
+
else
|
149
|
+
_proc.bind(context).call(&b)
|
150
|
+
end
|
151
|
+
elsif _proc.is_a?(String)
|
152
|
+
#in this case we cannot pass vars
|
153
|
+
warn "Cannot pass variables when _proc is a String" unless vars.nil?
|
154
|
+
context.instance_eval(_proc)
|
155
|
+
else
|
156
|
+
if context.nil?
|
157
|
+
if !vars.nil?
|
158
|
+
_proc.to_proc.call(vars,&b)
|
159
|
+
else
|
160
|
+
_proc.to_proc(&b)
|
161
|
+
end
|
162
|
+
else
|
163
|
+
warn "Cannot pass block in context.instance_eval" unless b.nil?
|
164
|
+
if !vars.nil?
|
165
|
+
context.instance_exec(vars,&_proc)
|
166
|
+
else
|
167
|
+
context.instance_eval(&_proc)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def include(template, **opts)
|
174
|
+
file=File.expand_path(template)
|
175
|
+
Dir.chdir(File.dirname(file)) do |cwd|
|
176
|
+
erb = Engine.new(File.read(file))
|
177
|
+
#if context is not empty, then we probably want to evaluate
|
178
|
+
if opts[:evaluate] or opts[:context]
|
179
|
+
r=erb.evaluate(opts[:context])
|
180
|
+
else
|
181
|
+
bind=opts[:bind]||binding
|
182
|
+
r=erb.result(bind)
|
183
|
+
end
|
184
|
+
#if using erubis, it is better to invoke the template in <%= =%> than
|
185
|
+
#to use chomp=true
|
186
|
+
r=r.chomp if opts[:chomp]
|
187
|
+
return r
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
extend ClassHelpers
|
193
|
+
|
194
|
+
begin
|
195
|
+
require 'erubi'
|
196
|
+
Engine=::Erubi::Engine
|
197
|
+
rescue LoadError
|
198
|
+
require 'erubis'
|
199
|
+
Engine=::Erubis::Eruby
|
200
|
+
rescue LoadError
|
201
|
+
require 'erb'
|
202
|
+
Engine=::ERB
|
203
|
+
end
|
204
|
+
#prepend so that we have the same implementation
|
205
|
+
Engine.__send__(:prepend, EngineHelper)
|
206
|
+
|
207
|
+
## Copy/Pasted from erubis context.rb
|
208
|
+
## # context object for Engine#evaluate
|
209
|
+
##
|
210
|
+
## ex.
|
211
|
+
## template = <<'END'
|
212
|
+
## Hello <%= @user %>!
|
213
|
+
## <% for item in @list %>
|
214
|
+
## - <%= item %>
|
215
|
+
## <% end %>
|
216
|
+
## END
|
217
|
+
##
|
218
|
+
## context = Erubis::Context.new(:user=>'World', :list=>['a','b','c'])
|
219
|
+
## # or
|
220
|
+
## # context = Erubis::Context.new
|
221
|
+
## # context[:user] = 'World'
|
222
|
+
## # context[:list] = ['a', 'b', 'c']
|
223
|
+
##
|
224
|
+
## eruby = Erubis::Eruby.new(template)
|
225
|
+
## print eruby.evaluate(context)
|
226
|
+
##
|
227
|
+
class Context
|
228
|
+
include Enumerable
|
229
|
+
|
230
|
+
def initialize(hash=nil)
|
231
|
+
hash.each do |name, value|
|
232
|
+
self[name] = value
|
233
|
+
end if hash
|
234
|
+
end
|
235
|
+
|
236
|
+
def [](key)
|
237
|
+
return instance_variable_get("@#{key}")
|
238
|
+
end
|
239
|
+
|
240
|
+
def []=(key, value)
|
241
|
+
return instance_variable_set("@#{key}", value)
|
242
|
+
end
|
243
|
+
|
244
|
+
def keys
|
245
|
+
return instance_variables.collect { |name| name[1..-1] }
|
246
|
+
end
|
247
|
+
|
248
|
+
def each
|
249
|
+
instance_variables.each do |name|
|
250
|
+
key = name[1..-1]
|
251
|
+
value = instance_variable_get(name)
|
252
|
+
yield(key, value)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Was to_hash, but changed to 'to_h' in commit 25d0e1e4b1a4ada40fd64945eb79823ea074d030
|
257
|
+
# Indeed otherwise passing it to 'evaluate' it get interpreted as the options rather than as a context
|
258
|
+
# cf https://bugs.ruby-lang.org/issues/12884
|
259
|
+
# corrected in ruby 2.4.1?
|
260
|
+
def to_h
|
261
|
+
hash = {}
|
262
|
+
self.keys.each { |key| hash[key] = self[key] }
|
263
|
+
return hash
|
264
|
+
end
|
265
|
+
|
266
|
+
def update(context_or_hash)
|
267
|
+
arg = context_or_hash
|
268
|
+
if arg.is_a?(Hash)
|
269
|
+
arg.each do |key, val|
|
270
|
+
self[key] = val
|
271
|
+
end
|
272
|
+
else
|
273
|
+
arg.instance_variables.each do |varname|
|
274
|
+
key = varname[1..-1]
|
275
|
+
val = arg.instance_variable_get(varname)
|
276
|
+
self[key] = val
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
end
|