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.
Files changed (67) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +11 -3
  4. data/Gemfile +12 -6
  5. data/Guardfile +13 -11
  6. data/LICENSE +20 -0
  7. data/Procfile.example +2 -0
  8. data/README.md +170 -23
  9. data/Rakefile +26 -22
  10. data/lib/skiima.rb +61 -240
  11. data/lib/skiima/config.rb +60 -0
  12. data/lib/skiima/config/struct.rb +87 -0
  13. data/lib/skiima/db/connector.rb +195 -0
  14. data/lib/skiima/db/connector/active_record.rb +11 -0
  15. data/lib/skiima/db/connector/active_record/base_connector.rb +34 -0
  16. data/lib/skiima/db/connector/active_record/mysql2_connector.rb +147 -0
  17. data/lib/skiima/db/connector/active_record/mysql_connector.rb +177 -0
  18. data/lib/skiima/db/connector/active_record/postgresql_connector.rb +39 -0
  19. data/lib/skiima/db/helpers/mysql.rb +230 -0
  20. data/lib/skiima/db/helpers/postgresql.rb +221 -0
  21. data/lib/skiima/db/resolver.rb +62 -0
  22. data/lib/skiima/dependency/reader.rb +55 -0
  23. data/lib/skiima/dependency/script.rb +63 -0
  24. data/lib/skiima/i18n.rb +24 -0
  25. data/lib/skiima/loader.rb +108 -0
  26. data/lib/skiima/locales/en.yml +2 -2
  27. data/lib/skiima/logger.rb +54 -0
  28. data/lib/skiima/railtie.rb +10 -0
  29. data/lib/skiima/railties/skiima.rake +31 -0
  30. data/lib/skiima/version.rb +2 -2
  31. data/skiima.gemspec +5 -5
  32. data/spec/config/{database.yml → database.yml.example} +16 -0
  33. data/spec/config/database.yml.travis +69 -0
  34. data/spec/db/skiima/{depends.yml → dependencies.yml} +7 -2
  35. data/spec/db/skiima/{empty_depends.yml → empty_dependencies.yml} +0 -0
  36. data/spec/db/skiima/init_test_db/database.skiima_test.mysql.current.sql +7 -0
  37. data/spec/db/skiima/init_test_db/database.skiima_test.postgresql.current.sql +7 -0
  38. data/spec/mysql2_spec.rb +61 -12
  39. data/spec/mysql_spec.rb +66 -27
  40. data/spec/postgresql_spec.rb +55 -34
  41. data/spec/shared_examples/config_shared_example.rb +40 -0
  42. data/spec/skiima/config/struct_spec.rb +78 -0
  43. data/spec/skiima/config_spec.rb +6 -0
  44. data/spec/skiima/db/connector/active_record/base_connector_spec.rb +0 -0
  45. data/spec/skiima/db/connector/active_record/mysql2_connector_spec.rb +3 -0
  46. data/spec/skiima/db/connector/active_record/mysql_connector_spec.rb +3 -0
  47. data/spec/skiima/db/connector/active_record/postgresql_connector_spec.rb +7 -0
  48. data/spec/skiima/db/connector_spec.rb +6 -0
  49. data/spec/skiima/db/resolver_spec.rb +54 -0
  50. data/spec/skiima/dependency/reader_spec.rb +52 -0
  51. data/spec/skiima/{dependency_spec.rb → dependency/script_spec.rb} +3 -41
  52. data/spec/skiima/i18n_spec.rb +29 -0
  53. data/spec/skiima/loader_spec.rb +102 -0
  54. data/spec/skiima/logger_spec.rb +0 -0
  55. data/spec/skiima_spec.rb +43 -64
  56. data/spec/spec_helper.rb +38 -4
  57. metadata +144 -100
  58. data/lib/skiima/db_adapters.rb +0 -187
  59. data/lib/skiima/db_adapters/base_mysql_adapter.rb +0 -308
  60. data/lib/skiima/db_adapters/mysql2_adapter.rb +0 -114
  61. data/lib/skiima/db_adapters/mysql_adapter.rb +0 -287
  62. data/lib/skiima/db_adapters/postgresql_adapter.rb +0 -509
  63. data/lib/skiima/dependency.rb +0 -84
  64. data/lib/skiima_helpers.rb +0 -49
  65. data/spec/skiima/db_adapters/mysql_adapter_spec.rb +0 -38
  66. data/spec/skiima/db_adapters/postgresql_adapter_spec.rb +0 -20
  67. data/spec/skiima/db_adapters_spec.rb +0 -31
@@ -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 SkiimaHelpers
17
- extend ModuleHelpers
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
- def setup
37
- yield self
38
- set_translation_repository
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
- def read_sql_file(folder, file)
120
- File.open(File.join(Skiima.full_scripts_path, folder, file)).read
121
- end
34
+ def self.setup
35
+ yield config
36
+ set_translation_repository
37
+ end
122
38
 
123
- def read_yaml_or_throw(file, errclass, errmsg)
124
- yaml = begin
125
- input = File.read(file)
126
- eruby = Erubis::Eruby.new(input)
127
- YAML::load(eruby.result(binding())) || {}
128
- rescue => ex
129
- raise errclass, errmsg
130
- end
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
- Skiima.symbolize_keys(yaml)
133
- end
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
- def method_missing(method, *args, &block)
136
- setter = method.to_s.gsub(/=$/, '').to_sym if method.to_s =~ /=$/
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
- val = case
139
- when (@@config.keys.include?(method)) then @@config[method]
140
- when (setter and @@config.keys.include?(setter)) then @@config[setter] = args.first
141
- end
67
+ def self.exe_with_connection(db, &block)
68
+ resolver = Skiima::Db::Resolver.new db
69
+ connection = nil
142
70
 
143
- val || super
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
- #BaseExceptions
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