skiima 0.1.000 → 0.2.2
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 +15 -0
- data/.gitignore +9 -0
- data/.travis.yml +11 -3
- data/Gemfile +12 -6
- data/Guardfile +13 -11
- data/LICENSE +20 -0
- data/Procfile.example +2 -0
- data/README.md +170 -23
- data/Rakefile +26 -22
- data/lib/skiima.rb +61 -240
- data/lib/skiima/config.rb +60 -0
- data/lib/skiima/config/struct.rb +87 -0
- data/lib/skiima/db/connector.rb +195 -0
- data/lib/skiima/db/connector/active_record.rb +11 -0
- data/lib/skiima/db/connector/active_record/base_connector.rb +34 -0
- data/lib/skiima/db/connector/active_record/mysql2_connector.rb +147 -0
- data/lib/skiima/db/connector/active_record/mysql_connector.rb +177 -0
- data/lib/skiima/db/connector/active_record/postgresql_connector.rb +39 -0
- data/lib/skiima/db/helpers/mysql.rb +230 -0
- data/lib/skiima/db/helpers/postgresql.rb +221 -0
- data/lib/skiima/db/resolver.rb +62 -0
- data/lib/skiima/dependency/reader.rb +55 -0
- data/lib/skiima/dependency/script.rb +63 -0
- data/lib/skiima/i18n.rb +24 -0
- data/lib/skiima/loader.rb +108 -0
- data/lib/skiima/locales/en.yml +2 -2
- data/lib/skiima/logger.rb +54 -0
- data/lib/skiima/railtie.rb +10 -0
- data/lib/skiima/railties/skiima.rake +31 -0
- data/lib/skiima/version.rb +2 -2
- data/skiima.gemspec +5 -5
- data/spec/config/{database.yml → database.yml.example} +16 -0
- data/spec/config/database.yml.travis +69 -0
- data/spec/db/skiima/{depends.yml → dependencies.yml} +7 -2
- data/spec/db/skiima/{empty_depends.yml → empty_dependencies.yml} +0 -0
- data/spec/db/skiima/init_test_db/database.skiima_test.mysql.current.sql +7 -0
- data/spec/db/skiima/init_test_db/database.skiima_test.postgresql.current.sql +7 -0
- data/spec/mysql2_spec.rb +61 -12
- data/spec/mysql_spec.rb +66 -27
- data/spec/postgresql_spec.rb +55 -34
- data/spec/shared_examples/config_shared_example.rb +40 -0
- data/spec/skiima/config/struct_spec.rb +78 -0
- data/spec/skiima/config_spec.rb +6 -0
- data/spec/skiima/db/connector/active_record/base_connector_spec.rb +0 -0
- data/spec/skiima/db/connector/active_record/mysql2_connector_spec.rb +3 -0
- data/spec/skiima/db/connector/active_record/mysql_connector_spec.rb +3 -0
- data/spec/skiima/db/connector/active_record/postgresql_connector_spec.rb +7 -0
- data/spec/skiima/db/connector_spec.rb +6 -0
- data/spec/skiima/db/resolver_spec.rb +54 -0
- data/spec/skiima/dependency/reader_spec.rb +52 -0
- data/spec/skiima/{dependency_spec.rb → dependency/script_spec.rb} +3 -41
- data/spec/skiima/i18n_spec.rb +29 -0
- data/spec/skiima/loader_spec.rb +102 -0
- data/spec/skiima/logger_spec.rb +0 -0
- data/spec/skiima_spec.rb +43 -64
- data/spec/spec_helper.rb +38 -4
- metadata +144 -100
- data/lib/skiima/db_adapters.rb +0 -187
- data/lib/skiima/db_adapters/base_mysql_adapter.rb +0 -308
- data/lib/skiima/db_adapters/mysql2_adapter.rb +0 -114
- data/lib/skiima/db_adapters/mysql_adapter.rb +0 -287
- data/lib/skiima/db_adapters/postgresql_adapter.rb +0 -509
- data/lib/skiima/dependency.rb +0 -84
- data/lib/skiima_helpers.rb +0 -49
- data/spec/skiima/db_adapters/mysql_adapter_spec.rb +0 -38
- data/spec/skiima/db_adapters/postgresql_adapter_spec.rb +0 -20
- data/spec/skiima/db_adapters_spec.rb +0 -31
data/lib/skiima.rb
CHANGED
@@ -5,266 +5,87 @@ require 'yaml'
|
|
5
5
|
require 'logger'
|
6
6
|
require 'fast_gettext'
|
7
7
|
require 'erubis'
|
8
|
+
require 'ostruct'
|
9
|
+
require 'forwardable'
|
10
|
+
|
11
|
+
require 'skiima/config'
|
12
|
+
require 'skiima/config/struct'
|
13
|
+
require 'skiima/i18n'
|
14
|
+
require 'skiima/logger'
|
15
|
+
require 'skiima/loader'
|
16
|
+
require 'skiima/db/resolver'
|
17
|
+
require 'skiima/db/connector'
|
18
|
+
require 'skiima/dependency/script'
|
19
|
+
require 'skiima/dependency/reader'
|
8
20
|
|
9
|
-
require 'skiima_helpers'
|
10
|
-
|
11
|
-
# include FastGettext unless it already is
|
12
21
|
include FastGettext unless ::Object.included_modules.include?(FastGettext)
|
13
22
|
|
14
23
|
module Skiima
|
15
24
|
include FastGettext::Translation
|
16
|
-
extend
|
17
|
-
extend
|
18
|
-
|
19
|
-
# require 'skiima/base'
|
20
|
-
autoload :Dependency, 'skiima/dependency'
|
21
|
-
autoload :DbAdapters, 'skiima/db_adapters'
|
22
|
-
|
23
|
-
set_defaults(:config, {
|
24
|
-
:root_path => 'specify/in/config/block',
|
25
|
-
:config_path => 'config',
|
26
|
-
:database_yaml => 'database.yml',
|
27
|
-
:scripts_path => 'db/skiima',
|
28
|
-
:depends_yaml => 'depends.yml',
|
29
|
-
:interpolator => '&',
|
30
|
-
:locale => 'en',
|
31
|
-
:logging_out => 'STDOUT',
|
32
|
-
:logging_level => '3' })
|
33
|
-
#should time zone be added to configs?
|
25
|
+
extend Skiima::Config
|
26
|
+
extend Skiima::I18n
|
27
|
+
extend Skiima::LoggerHelpers
|
34
28
|
|
35
29
|
class << self
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def new(env, opts = {})
|
42
|
-
Skiima::Loader.new(env, opts)
|
43
|
-
end
|
44
|
-
|
45
|
-
def up(*args)
|
46
|
-
opts = args.last.is_a?(Hash) ? args.pop : {}
|
47
|
-
ski = Skiima.new(env, opts).up(*args)
|
48
|
-
ensure
|
49
|
-
ski.connection.close
|
50
|
-
end
|
51
|
-
|
52
|
-
def down(*args)
|
53
|
-
opts = args.last.is_a?(Hash) ? args.pop : {}
|
54
|
-
Skiima.new(env, opts).down(*args)
|
55
|
-
ensure
|
56
|
-
ski.connection.close
|
57
|
-
end
|
58
|
-
|
59
|
-
def msg(*args)
|
60
|
-
locale = args.last.is_a?(Symbol) ? args.pop : default_locale
|
61
|
-
lookup = args.join('.')
|
62
|
-
Skiima._(lookup)
|
63
|
-
end
|
64
|
-
|
65
|
-
def log_message(logger, msg)
|
66
|
-
logger.debug msg
|
67
|
-
end
|
68
|
-
|
69
|
-
def default_locale
|
70
|
-
::Skiima.locale
|
71
|
-
end
|
72
|
-
|
73
|
-
def set_translation_repository
|
74
|
-
FastGettext.add_text_domain('skiima', :path => File.join(File.dirname(__FILE__), 'skiima', 'locales'), :type => :yaml)
|
75
|
-
Skiima.text_domain = 'skiima'
|
76
|
-
Skiima.locale = locale.to_s
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.exe_with_connection(db, &block)
|
80
|
-
resolver = Skiima::DbAdapters::Resolver.new db
|
81
|
-
connection = nil
|
82
|
-
|
83
|
-
begin
|
84
|
-
connection = self.send(resolver.adapter_method, db)
|
85
|
-
yield connection
|
86
|
-
rescue => ex
|
87
|
-
puts "Oh Noes!!"
|
88
|
-
ensure
|
89
|
-
connection.close
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def interpolate_sql(char, sql, vars = {})
|
94
|
-
vars.inject(sql) do |memo, (k,v)|
|
95
|
-
memo = memo.gsub("#{char}#{k.to_s}", v)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
def full_scripts_path(root = self.root_path, config = self.scripts_path)
|
100
|
-
File.join(root, config)
|
101
|
-
end
|
102
|
-
|
103
|
-
def full_database_path(root = self.root_path, config = self.config_path, db = self.database_yaml)
|
104
|
-
File.join(root, config, db)
|
105
|
-
end
|
106
|
-
|
107
|
-
def full_depends_path(root = self.root_path, config = self.scripts_path, depends = self.depends_yaml)
|
108
|
-
File.join(root, config, depends)
|
109
|
-
end
|
110
|
-
|
111
|
-
def read_db_yaml(file)
|
112
|
-
Skiima.symbolize_keys(self.read_yaml_or_throw(file, MissingFileException, "#{Skiima.msg('errors.open_db_yaml')} #{file}"))
|
113
|
-
end
|
114
|
-
|
115
|
-
def read_depends_yaml(file)
|
116
|
-
Skiima.symbolize_keys(self.read_yaml_or_throw(file, MissingFileException, "#{Skiima.msg('errors.open_depends_yaml')} #{file}"))
|
117
|
-
end
|
30
|
+
extend Forwardable
|
31
|
+
delegate new: Skiima::Loader
|
32
|
+
end
|
118
33
|
|
119
|
-
|
120
|
-
|
121
|
-
|
34
|
+
def self.setup
|
35
|
+
yield config
|
36
|
+
set_translation_repository
|
37
|
+
end
|
122
38
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
39
|
+
require 'skiima/railtie' if defined?(Rails) && Rails::VERSION::MAJOR >= 3
|
40
|
+
|
41
|
+
def self.defaults
|
42
|
+
{ root_path: 'specify/in/config/block',
|
43
|
+
config_path: 'config',
|
44
|
+
database_yml: 'database.yml',
|
45
|
+
scripts_path: 'db/skiima',
|
46
|
+
dependencies_yml: 'dependencies.yml',
|
47
|
+
interpolator: '&',
|
48
|
+
locale: 'en',
|
49
|
+
logging_out: 'STDOUT',
|
50
|
+
logging_level: '3' }
|
51
|
+
end
|
131
52
|
|
132
|
-
|
133
|
-
|
53
|
+
def self.up(env, *args)
|
54
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
55
|
+
ski = Skiima::Loader.new(env, opts).up(*args, opts)
|
56
|
+
ensure
|
57
|
+
ski.connector.disconnect! if ski && ski.connector
|
58
|
+
end
|
134
59
|
|
135
|
-
|
136
|
-
|
60
|
+
def self.down(env, *args)
|
61
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
62
|
+
ski = Skiima::Loader.new(env, opts).down(*args, opts)
|
63
|
+
ensure
|
64
|
+
ski.connector.disconnect! if ski && ski.connector
|
65
|
+
end
|
137
66
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
end
|
67
|
+
def self.exe_with_connection(db, &block)
|
68
|
+
resolver = Skiima::Db::Resolver.new db
|
69
|
+
connection = nil
|
142
70
|
|
143
|
-
|
71
|
+
begin
|
72
|
+
connection = self.send(resolver.adapter_method, db)
|
73
|
+
yield connection
|
74
|
+
rescue => ex
|
75
|
+
puts "Oh Noes!!"
|
76
|
+
ensure
|
77
|
+
connection.close
|
144
78
|
end
|
145
79
|
end
|
146
80
|
|
147
|
-
|
81
|
+
end
|
82
|
+
|
83
|
+
module Skiima
|
148
84
|
class BaseException < ::StandardError; end
|
149
85
|
class MissingFileException < BaseException; end
|
150
86
|
class SqlGroupNotFound < BaseException; end
|
151
87
|
class SqlScriptNotFound < BaseException; end
|
152
|
-
|
153
|
-
#DbAdapterExceptions
|
154
88
|
class AdapterNotSpecified < BaseException; end
|
155
89
|
class LoadError < BaseException; end
|
156
90
|
class StatementInvalid < BaseException; end
|
157
|
-
|
158
|
-
class Loader
|
159
|
-
attr_accessor :config, :logger
|
160
|
-
attr_accessor :db, :connection
|
161
|
-
attr_accessor :scripts
|
162
|
-
|
163
|
-
def initialize(env, opts = {})
|
164
|
-
db_config = Skiima.symbolize_keys(opts[:db] || {})
|
165
|
-
|
166
|
-
self.config = Skiima.config.merge(opts)
|
167
|
-
create_logger
|
168
|
-
@db = Skiima.symbolize_keys(Skiima.read_db_yaml(full_database_path)[env].merge(db_config))
|
169
|
-
make_connection
|
170
|
-
@depends = Skiima.read_depends_yaml(full_depends_path)
|
171
|
-
end
|
172
|
-
|
173
|
-
def up(*args)
|
174
|
-
opts = args.last.is_a?(Hash) ? args.pop : {}
|
175
|
-
reader = Skiima::Dependency::Reader.new(@depends, @db[:adapter], opts)
|
176
|
-
scripts = reader.get_load_order(*args)
|
177
|
-
scripts.each do |s|
|
178
|
-
s.read_content(:up, full_scripts_path)
|
179
|
-
s.interpolate_sql(interpolator, interpolation_vars)
|
180
|
-
end
|
181
|
-
scripts.each {|s| connection.execute(s.sql)}
|
182
|
-
end
|
183
|
-
|
184
|
-
def down(*args)
|
185
|
-
opts = args.last.is_a?(Hash) ? args.pop : {}
|
186
|
-
reader = Skiima::Dependency::Reader.new(@depends, @db[:adapter], opts)
|
187
|
-
scripts = reader.get_load_order(*args).reverse
|
188
|
-
scripts.each do |s|
|
189
|
-
s.read_content(:down, full_scripts_path)
|
190
|
-
s.content ||= connection.drop(s.type, s.name, {:attr => s.attr}.merge(opts))
|
191
|
-
s.interpolate_sql(interpolator, interpolation_vars)
|
192
|
-
end
|
193
|
-
scripts.each {|s| connection.execute(s.sql)}
|
194
|
-
end
|
195
|
-
|
196
|
-
def make_connection
|
197
|
-
resolver = Skiima::DbAdapters::Resolver.new(@db)
|
198
|
-
@connection = Skiima.send(resolver.adapter_method, logger, @db)
|
199
|
-
end
|
200
|
-
|
201
|
-
def log_action(msg, &block)
|
202
|
-
begin
|
203
|
-
logger.debug "[#{Time.now}] Started: #{msg}"
|
204
|
-
results = yield
|
205
|
-
logger.debug "[#{Time.now}] Finished: #{msg}"
|
206
|
-
results
|
207
|
-
rescue
|
208
|
-
logger.error "[#{Time.now}] Error: #{msg}"
|
209
|
-
raise
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def log_message(msg)
|
214
|
-
Skiima.log_message(logger, msg)
|
215
|
-
end
|
216
|
-
|
217
|
-
def interpolation_vars(vars = {})
|
218
|
-
{ :database => db[:database] }.merge(vars)
|
219
|
-
end
|
220
|
-
|
221
|
-
def method_missing(method, *args, &block)
|
222
|
-
setter = method.to_s.gsub(/=$/, '').to_sym if method.to_s =~ /=$/
|
223
|
-
|
224
|
-
val = case
|
225
|
-
when (@config.keys.include?(method)) then @config[method]
|
226
|
-
when (setter and @config.keys.include?(setter)) then @config[setter] = args
|
227
|
-
end
|
228
|
-
|
229
|
-
val || super
|
230
|
-
end
|
231
|
-
|
232
|
-
private
|
233
|
-
|
234
|
-
def full_database_path
|
235
|
-
Skiima.full_database_path(self.root_path, self.config_path, self.database_yaml)
|
236
|
-
end
|
237
|
-
|
238
|
-
def full_depends_path
|
239
|
-
Skiima.full_depends_path(self.root_path, self.scripts_path, self.depends_yaml)
|
240
|
-
end
|
241
|
-
|
242
|
-
def full_scripts_path
|
243
|
-
Skiima.full_scripts_path(self.root_path, self.scripts_path)
|
244
|
-
end
|
245
|
-
|
246
|
-
def get_logger_out(str)
|
247
|
-
case str
|
248
|
-
when /STDOUT/i then ::STDOUT
|
249
|
-
when /STDERR/i then ::STDERR
|
250
|
-
else File.join(root_path, str)
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
def get_logger_level(str)
|
255
|
-
case str
|
256
|
-
when '4', /fatal/i then ::Logger::FATAL
|
257
|
-
when '3', /error/i then ::Logger::ERROR
|
258
|
-
when '2', /warn/i then ::Logger::WARN
|
259
|
-
when '1', /info/i then ::Logger::INFO
|
260
|
-
when '0', /debug/i then ::Logger::DEBUG
|
261
|
-
else ::Logger::ERROR
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
def create_logger
|
266
|
-
self.logger = ::Logger.new(get_logger_out(@config[:logging_out]))
|
267
|
-
self.logger.level = get_logger_level(@config[:logging_level])
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
91
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Skiima
|
3
|
+
module Config
|
4
|
+
|
5
|
+
def config
|
6
|
+
@config ||= (Skiima::Config::Struct.new(defaults.to_hash))
|
7
|
+
end
|
8
|
+
|
9
|
+
def config=(struct)
|
10
|
+
@config = struct
|
11
|
+
end
|
12
|
+
|
13
|
+
def full_scripts_path(root = self.root_path, config = self.scripts_path)
|
14
|
+
File.join(root, config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def full_database_path(root = self.root_path, config = self.config_path, db = self.database_yml)
|
18
|
+
File.join(root, config, db)
|
19
|
+
end
|
20
|
+
|
21
|
+
def full_dependencies_path(root = self.root_path, config = self.scripts_path, dependencies = self.dependencies_yml)
|
22
|
+
File.join(root, config, dependencies)
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_sql_file(folder, file)
|
26
|
+
File.open(File.join(Skiima.full_scripts_path, folder, file)).read
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_db_yml(file)
|
30
|
+
symbolize_keys(read_yml_or_throw(file, MissingFileException, "#{Skiima.msg('errors.open_db_yml')} #{file}"))
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_dependencies_yml(file)
|
34
|
+
symbolize_keys(read_yml_or_throw(file, MissingFileException, "#{Skiima.msg('errors.open_dependencies_yml')} #{file}"))
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_yml_or_throw(file, errclass, errmsg)
|
38
|
+
input = File.read(file)
|
39
|
+
eruby = Erubis::Eruby.new(input)
|
40
|
+
symbolize_keys(YAML::load(eruby.result(binding()))) || {}
|
41
|
+
rescue => ex
|
42
|
+
raise errclass, errmsg
|
43
|
+
end
|
44
|
+
|
45
|
+
def symbolize_keys(hash)
|
46
|
+
hash.inject({}) do |options, (key, value)|
|
47
|
+
options[(key.to_sym rescue key) || key] = value
|
48
|
+
options
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def interpolate_sql(char, sql, vars = {})
|
53
|
+
vars.inject(sql) { |m,(k,v)| m.gsub("#{char}#{k.to_s}", v) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def method_missing(method, *args, &block)
|
57
|
+
config.respond_to?(method) ? config.send(method, *args) : super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Skiima
|
2
|
+
module Config
|
3
|
+
|
4
|
+
class Struct < OpenStruct
|
5
|
+
def initialize(opts = {})
|
6
|
+
@table = Skiima.symbolize_keys(opts)
|
7
|
+
@table.each_key { |k,v| new_ostruct_member(k) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def new_ostruct_member(name)
|
11
|
+
name = convert_key(name)
|
12
|
+
unless self.respond_to?(name)
|
13
|
+
self.instance_eval <<EOS
|
14
|
+
def #{name.to_s}
|
15
|
+
v = @table[:#{name.to_s}]
|
16
|
+
if v.is_a?(Hash)
|
17
|
+
self.class.new(v)
|
18
|
+
else
|
19
|
+
v
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def #{name.to_s}=(x)
|
24
|
+
modifiable[:#{name.to_s}] = x
|
25
|
+
end
|
26
|
+
EOS
|
27
|
+
end
|
28
|
+
name
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(mid, *args, &block)
|
32
|
+
mname, len = mid.id2name, args.length
|
33
|
+
|
34
|
+
case
|
35
|
+
when (mname.chomp!('=') && (mid != :[]=))
|
36
|
+
raise_argument_error(len, caller(1)) if len != 1
|
37
|
+
modifiable[new_ostruct_member(mname)] = args[0]
|
38
|
+
when (len == 0 && (mid != :[]) && block_given?)
|
39
|
+
cs = self.class.new(Hash.new).ostruct_eval(&block)
|
40
|
+
modifiable[new_ostruct_member(mname)] = cs
|
41
|
+
when (len == 0 && mid != :[])
|
42
|
+
@table[mid]
|
43
|
+
when (len == 1 && mid != :[])
|
44
|
+
modifiable[new_ostruct_member(mname)] = args[0]
|
45
|
+
else raise_no_method_error(mid, caller(1))
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def [](key)
|
51
|
+
@table[key]
|
52
|
+
end
|
53
|
+
|
54
|
+
def []=(key,val)
|
55
|
+
modifiable[key] = val
|
56
|
+
end
|
57
|
+
|
58
|
+
def slice(*keys)
|
59
|
+
keys.inject(Hash.new) { |m,k| m[k] = @table[k] if @table.key?(k); m }
|
60
|
+
end
|
61
|
+
|
62
|
+
def merge(hash)
|
63
|
+
hash.each { |k,v| self[k] = v; new_ostruct_member(k) unless self.respond_to? k }
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_hash
|
68
|
+
@table
|
69
|
+
end
|
70
|
+
|
71
|
+
def convert_key(key)
|
72
|
+
key.kind_of?(Symbol) ? key : (key.to_sym rescue key)
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def raise_argument_error(len, caller)
|
78
|
+
raise ArgumentError, "wrong number of arguments (#{len} for 1)", caller
|
79
|
+
end
|
80
|
+
|
81
|
+
def raise_no_method_error(mid, caller)
|
82
|
+
raise NoMethodError, "undefined method `#{mid}' for #{self}", caller
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|