rmap 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -7,3 +7,5 @@ gem 'mysql2', "~> 0"
7
7
  gem 'json', "~> 1"
8
8
  gem 'ripl', "~> 0"
9
9
  gem 'ripl-multi_line', "~> 0"
10
+ gem 'powerline', "~> 0"
11
+ gem 'gengin', "~> 0"
data/bin/rmap CHANGED
@@ -1,18 +1,5 @@
1
1
 
2
2
  require 'rmap'
3
- require 'ripl'
4
- require 'ripl/multi_line'
5
-
6
- db = Rmap::Database.new
7
-
8
- current = Dir::getwd
9
- while current != '/'
10
- if ::File.file? "#{current}/conf.rmap.rb"
11
- db.run("#{current}/conf.rmap.rb")
12
- break
13
- end
14
- current = ::File.expand_path('../', current)
15
- end
16
-
17
- Ripl.start :binding => db.bindings
3
+ require 'powerline'
18
4
 
5
+ Powerline.new Rmap::Commands
@@ -1,10 +1,20 @@
1
1
 
2
- require 'mysql2'
2
+
3
+ module Rmap
4
+ current = Dir::getwd
5
+ while current != '/'
6
+ if ::File.file? "#{current}/conf.rmap.rb"
7
+ CONF_ROOT = current
8
+ break
9
+ end
10
+ current = ::File.expand_path('../', current)
11
+ end
12
+ end
3
13
 
4
14
  require 'rmap/version'
5
15
  require 'rmap/database'
6
16
  require 'rmap/table'
7
17
  require 'rmap/row'
18
+ require 'rmap/migration'
19
+ require 'rmap/commands'
8
20
 
9
- module Rmap
10
- end
@@ -0,0 +1,169 @@
1
+
2
+ require 'ripl'
3
+ require 'ripl/multi_line'
4
+ require 'gengin'
5
+
6
+ module Rmap
7
+ module Commands
8
+
9
+ def self.console
10
+ db = Rmap::Database.new
11
+
12
+ if Rmap.const_defined? :CONF_ROOT
13
+ db.run("#{Rmap::CONF_ROOT}/conf.rmap.rb")
14
+ end
15
+
16
+ Ripl.start :binding => db.bindings
17
+ end
18
+
19
+ def self.current_migration(options)
20
+ if !db.table? :rmap_vars
21
+ db.create :rmap_vars
22
+ db.rmap_vars.add :key, :string
23
+ db.rmap_vars.add :value, :binary
24
+ end
25
+
26
+ if db.rmap_vars.key_eq(:current_migration).count == 0
27
+ db.rmap_vars.insert(:key => :current_migration, :value => 0)
28
+ current_migration = 0
29
+ else
30
+ current_migration = db.rmap_vars.key_eq(:current_migration).first.value.to_i
31
+ end
32
+
33
+ if options[:echo] != false
34
+ puts current_migration
35
+ end
36
+
37
+ current_migration
38
+ end
39
+
40
+ module Generate
41
+
42
+ def self.conf(database, options={})
43
+ Gengin.new do
44
+ source_root File.expand_path("../generator_templates/", __FILE__)
45
+ @database = database
46
+ copy "conf.rmap.rb", :erb => true
47
+ end
48
+ end
49
+
50
+ def self.migration(name, *columns, options)
51
+ if !Rmap.const_defined? :CONF_ROOT
52
+ raise "Could not find a conf.rmap.rb file in your path."
53
+ end
54
+
55
+ Gengin.new do
56
+ source_root File.expand_path("../generator_templates/", __FILE__)
57
+ destination_root "#{Rmap::CONF_ROOT}/migrations"
58
+ @name = name
59
+ @columns = columns
60
+
61
+ up_code_buf = []
62
+ down_code_buf = []
63
+
64
+ if name.match(/\Aadd_.*_to_(.*?)\Z/)
65
+ table_name = $1
66
+ @columns.each do |column|
67
+ (column_name, type) = column.split(/:/)
68
+ up_code_buf << " #{table_name}.add :#{column_name}, :#{type}"
69
+ down_code_buf << " #{table_name}.remove :#{column_name}"
70
+ end
71
+ end
72
+
73
+ if name.match(/\Aremove_.*_from_(.*?)\Z/)
74
+ table_name = $1
75
+ @columns.each do |column|
76
+ (column_name, type) = column.split(/:/)
77
+ up_code_buf << " #{table_name}.remove :#{column_name}"
78
+ down_code_buf << " #{table_name}.add :#{column_name}, :#{type}"
79
+ end
80
+ end
81
+
82
+ @up_code = up_code_buf.join("\n")
83
+ @down_code = down_code_buf.join("\n")
84
+
85
+ copy "migration.rmap.rb", "#{Time.new.to_i}_#{name.downcase.strip.gsub(/\W+/, "_")}.migration.rmap.rb", :erb => true
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+
94
+ def self.migrate(options = {})
95
+ db = Rmap::Commands::db
96
+
97
+ current_migration = Rmap::Commands::current_migration(:echo => false)
98
+
99
+ migrations = Dir.new("#{Rmap::CONF_ROOT}/migrations/").to_a.find_all{|file| ::File.file? "#{Rmap::CONF_ROOT}/migrations/#{file}" }.map{ |file| Rmap::Migration.new("#{Rmap::CONF_ROOT}/migrations/#{file}") }.sort {|l,r| l.schema_version <=> r.schema_version}
100
+
101
+ if !options[:to].nil?
102
+ to = options[:to].to_i
103
+ found = false
104
+ migrations.each do |migration|
105
+ if migration.schema_version == to
106
+ found = true
107
+ break
108
+ end
109
+ end
110
+
111
+ if !found
112
+ raise "No such migration '#{to}' exists"
113
+ end
114
+
115
+ if to > current_migration
116
+ migrations.each do |migration|
117
+ if migration.schema_version <= current_migration
118
+ next
119
+ end
120
+
121
+ if migration.schema_version <= to
122
+ puts "up: #{migration.schema_version}"
123
+ db.run &migration.up_block
124
+ else
125
+ break
126
+ end
127
+ end
128
+ db.rmap_vars.key_eq(:current_migration).value = to.to_s
129
+ elsif to < current_migration
130
+ migrations.reverse.each do |migration|
131
+ if migration.schema_version > current_migration
132
+ next
133
+ end
134
+ if migration.schema_version > to
135
+ puts "down: #{migration.schema_version}"
136
+ db.run &migration.down_block
137
+ else
138
+ break
139
+ end
140
+ end
141
+ db.rmap_vars.key_eq(:current_migration).value = to
142
+ else
143
+ raise "already at migration #{to}"
144
+ end
145
+
146
+ elsif migrations.count > 0
147
+ migrations.each do |migration|
148
+ if migration.schema_version > current_migration
149
+ puts "up: #{migration.schema_version}"
150
+ db.run &migration.up_block
151
+ end
152
+ end
153
+ db.rmap_vars.key_eq(:current_migration).value = migrations.last.schema_version
154
+ end
155
+
156
+ end
157
+
158
+ private
159
+
160
+ def self.db
161
+ db = Rmap::Database.new
162
+ if Rmap.const_defined? :CONF_ROOT
163
+ db.run("#{Rmap::CONF_ROOT}/conf.rmap.rb")
164
+ end
165
+ db
166
+ end
167
+
168
+ end
169
+ end
@@ -1,43 +1,35 @@
1
1
 
2
+ require 'mysql2'
3
+
2
4
  module Rmap
3
5
  class Database
4
6
 
5
- def initialize(conf={:username => 'root'}, &block)
6
- @conf = conf
7
+ def initialize(connection={}, &block)
8
+ self.connection = connection
7
9
  if !block.nil?
8
10
  instance_eval(&block)
9
11
  end
12
+ @scopes = {}
13
+ end
14
+
15
+ def connection=(connection)
16
+ @connection = {:host => "localhost", :username => "root", :password => ""}.merge connection
17
+ close
18
+ @table_names = nil
10
19
  end
11
20
 
12
21
  def client
13
22
  if @client.nil?
14
- @client = Mysql2::Client.new(@conf)
23
+ @client = Mysql2::Client.new(@connection)
15
24
  end
16
25
  @client
17
26
  end
18
27
 
19
- def host(host)
20
- @client = nil
21
- @table_names = nil
22
- @conf[:host] = host
23
- end
24
-
25
- def username(username)
26
- @client = nil
27
- @table_names = nil
28
- @conf[:username] = username
29
- end
30
-
31
- def password(password)
32
- @client = nil
33
- @table_names = nil
34
- @conf[:password] = password
35
- end
36
-
37
- def database(database)
28
+ def close
29
+ if !@client.nil?
30
+ @client.close
31
+ end
38
32
  @client = nil
39
- @table_names = nil
40
- @conf[:database] = database
41
33
  end
42
34
 
43
35
  def bindings
@@ -58,16 +50,12 @@ module Rmap
58
50
  end
59
51
 
60
52
  def method_missing name, *args
61
- if table_names.include? name.to_s
62
- Table.new(self, name)
63
- else
64
- super(name, *args)
65
- end
53
+ Table.new(self, name)
66
54
  end
67
55
 
68
56
  def create(name)
69
57
  @table_names = nil
70
- client.query("create table `#{name}`(id int unsigned not null auto_increment primary key)")
58
+ client.query("create table `#{name}`(id int unsigned not null auto_increment primary key) engine = InnoDB")
71
59
  end
72
60
 
73
61
  def table_names
@@ -77,5 +65,17 @@ module Rmap
77
65
  @table_names
78
66
  end
79
67
 
68
+ def start_transaction
69
+ client.query("start transaction")
70
+ end
71
+
72
+ def commit_transaction
73
+ client.query("commit")
74
+ end
75
+
76
+ def rollback_transaction
77
+ client.query("rollback")
78
+ end
79
+
80
80
  end
81
81
  end
@@ -0,0 +1,5 @@
1
+
2
+ #host "localhost"
3
+ #username "root"
4
+ #password ""
5
+ database "<%= @database %>"
@@ -0,0 +1,8 @@
1
+
2
+ up do
3
+ <%= @up_code %>
4
+ end
5
+
6
+ down do
7
+ <%= @down_code %>
8
+ end
@@ -0,0 +1,21 @@
1
+
2
+ module Rmap
3
+ class Migration
4
+
5
+ attr_accessor :schema_version, :up_block, :down_block
6
+
7
+ def initialize(file_path)
8
+ @schema_version = file_path.sub(/\A.*?(\d+)[^\/]*\Z/, "\\1").to_i
9
+ instance_eval(::File.open(file_path).read, file_path)
10
+ end
11
+
12
+ def up(&block)
13
+ @up_block = block
14
+ end
15
+
16
+ def down(&block)
17
+ @down_block = block
18
+ end
19
+
20
+ end
21
+ end
@@ -17,7 +17,7 @@ module Rmap
17
17
  end
18
18
 
19
19
  def update(hash)
20
- @database.client.query("update `#{@table_name}` set #{(hash.map{|k,v| "`#{k}`='#{@database.client.escape(v)}'"}).join(', ')} where id = '#{id}'")
20
+ @database.client.query("update `#{@table_name}` set #{(hash.map{|k,v| "`#{k}`='#{@database.client.escape(v.to_s)}'"}).join(', ')} where id = '#{id}'")
21
21
  end
22
22
 
23
23
  def delete
@@ -36,8 +36,12 @@ module Rmap
36
36
  end
37
37
  end
38
38
 
39
+ def to_hash
40
+ @database.client.query("select * from `#{@table_name}` where id = '#{id}'", :as => :hash).first
41
+ end
42
+
39
43
  def to_s
40
- @database.client.query("select * from `#{@table_name}` where id = '#{id}'", :as => :hash).first.to_json
44
+ to_hash.to_json
41
45
  end
42
46
 
43
47
  end
@@ -9,8 +9,8 @@ module Rmap
9
9
  'le' => lambda {|left,right| "#{left} <= #{right}"},
10
10
  'ge' => lambda {|left,right| "#{left} >= #{right}"},
11
11
  'contains' => lambda {|left,right| "#{left} like concat('%', #{right}, '%')"},
12
- 'begins_with' => lambda {|left,right| "#{left} like concat('%', #{right})"},
13
- 'ends_with' => lambda {|left,right| "#{left} like concat(#{right}, '%')"},
12
+ 'ends_with' => lambda {|left,right| "#{left} like concat('%', #{right})"},
13
+ 'begins_with' => lambda {|left,right| "#{left} like concat(#{right}, '%')"},
14
14
  'year_eq' => lambda {|left,right| "year(#{left}) = #{right}"},
15
15
  'year_ne' => lambda {|left,right| "year(#{left}) != #{right}"},
16
16
  'year_lt' => lambda {|left,right| "year(#{left}) < #{right}"},
@@ -82,6 +82,7 @@ module Rmap
82
82
  end
83
83
 
84
84
  def method_missing name, *args
85
+ table = self
85
86
  if @database.table? name
86
87
  Table.new(@database, name).join(self, *args)
87
88
  elsif column? name
@@ -91,6 +92,9 @@ module Rmap
91
92
  elsif name.match /\A(.*?)_(#{BINARY_FILTER_METHODS.keys.join('|')})\Z/
92
93
  @binary_filter_methods_args[$2].push([$1.split(/_or_/),args[0]])
93
94
  self
95
+ elsif @database.instance_eval{!@scopes[table.name].nil? && !@scopes[table.name][name].nil?}
96
+ instance_exec *args, &@database.instance_eval{@scopes[table.name][name]}
97
+ self
94
98
  else
95
99
  super
96
100
  end
@@ -172,7 +176,7 @@ module Rmap
172
176
  end
173
177
  else
174
178
  if table2.column? "#{to_singular(table1.name)}_id"
175
- "#{table1.name}.id = #{to_singular(table2.name)}.#{table1.name}_id"
179
+ "#{table1.name}.id = #{table2.name}.#{to_singular(table1.name)}_id"
176
180
  else
177
181
  "#{table1.name}.#{to_singular(table2.name)}_id = #{table2.name}.id"
178
182
  end
@@ -237,22 +241,38 @@ module Rmap
237
241
  out
238
242
  end
239
243
 
240
- def generate_select_sql(expression_list_sql, limit = nil)
241
- if !limit.nil?
242
- limit_sql = "limit #{limit}"
244
+ def generate_limit_sql
245
+ if !@limit_row_count.nil?
246
+ "limit #{@limit_offset}, #{@limit_row_count}"
243
247
  else
244
- limit_sql = ''
248
+ ""
245
249
  end
246
- "select #{format_sql(expression_list_sql)} #{generate_from_sql} #{generate_where_sql} #{generate_group_by_sql} #{generate_order_by_sql} #{limit_sql}"
247
250
  end
248
251
 
249
- def count(limit = nil)
250
- @database.client.query(generate_select_sql('id', limit)).count
252
+ def generate_select_sql(expression_list_sql, without_limit_sql = false)
253
+ "select #{format_sql(expression_list_sql)} #{generate_from_sql} #{generate_where_sql} #{generate_group_by_sql} #{generate_order_by_sql} #{without_limit_sql ? "" : generate_limit_sql}"
254
+ end
255
+
256
+ def explain
257
+ generate_select_sql('id').strip
258
+ end
259
+
260
+ def count
261
+ @database.client.query(generate_select_sql('id')).count
262
+ end
263
+
264
+ def page_count
265
+ count_without_limit = @database.client.query(generate_select_sql('id', true)).count
266
+ if count_without_limit > 0
267
+ @page_size.nil? ? 1 : (count_with_limit.to_f / @page_size).ceil
268
+ else
269
+ 0
270
+ end
251
271
  end
252
272
 
253
- def all(limit = nil)
273
+ def all
254
274
  out = []
255
- @database.client.query(generate_select_sql('id', limit), :as => :hash).each do |row|
275
+ @database.client.query(generate_select_sql('id'), :as => :hash).each do |row|
256
276
  out.push(Row.new(@database, @name, row['id']))
257
277
  end
258
278
  out
@@ -264,7 +284,7 @@ module Rmap
264
284
  end
265
285
 
266
286
  def first
267
- all(1).first
287
+ all.first
268
288
  end
269
289
 
270
290
  def update(hash)
@@ -277,11 +297,12 @@ module Rmap
277
297
 
278
298
  def insert(hash)
279
299
  @database.client.query("insert into `#{@name}`(#{(hash.map{|k,v| "`#{k}`"}).join(', ')}) values(#{(hash.map{|k,v| quote(v)}).join(', ')})")
300
+ @database.client.last_id
280
301
  end
281
302
 
282
- def sum(sql_expression, limit = nil)
303
+ def sum(sql_expression)
283
304
  out = 0
284
- @database.client.query(generate_select_sql("sum(#{sql_expression})", limit), :as => :array).each{|row| out += row.first}
305
+ @database.client.query(generate_select_sql("sum(#{sql_expression})"), :as => :array).each{|row| out += row.first}
285
306
  out
286
307
  end
287
308
 
@@ -291,6 +312,11 @@ module Rmap
291
312
  end
292
313
 
293
314
  def add(name, type, options = {})
315
+
316
+ if !@database.table? @name
317
+ @database.create @name
318
+ end
319
+
294
320
  case type
295
321
  when :string
296
322
  @database.client.query("alter table `#{@name}` add `#{name}` varchar(255) not null")
@@ -326,6 +352,22 @@ module Rmap
326
352
  all.to_s
327
353
  end
328
354
 
355
+ def define_scope(name, &block)
356
+ table = self
357
+ @database.instance_eval do
358
+ if @scopes[table.name].nil?
359
+ @scopes[table.name] = {}
360
+ end
361
+ @scopes[table.name][name.to_sym] = block
362
+ end
363
+ end
364
+
365
+ def paginate(page, page_size = 10)
366
+ @limit_row_count = page_size
367
+ @limit_offset = (page - 1) * page_size
368
+ self
369
+ end
370
+
329
371
  private
330
372
 
331
373
  def to_singular(value)
@@ -1,3 +1,3 @@
1
1
  module Rmap
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -21,5 +21,7 @@ Gem::Specification.new do |s|
21
21
  s.add_dependency "json", "~> 1"
22
22
  s.add_dependency "ripl", "~> 0"
23
23
  s.add_dependency "ripl-multi_line", "~> 0"
24
+ s.add_dependency "powerline", "~> 0"
25
+ s.add_dependency "gengin", "~> 0"
24
26
 
25
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-14 00:00:00.000000000Z
12
+ date: 2012-08-16 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mysql2
16
- requirement: &82061450 !ruby/object:Gem::Requirement
16
+ requirement: &83687640 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *82061450
24
+ version_requirements: *83687640
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: json
27
- requirement: &82061200 !ruby/object:Gem::Requirement
27
+ requirement: &83684760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '1'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *82061200
35
+ version_requirements: *83684760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ripl
38
- requirement: &82060970 !ruby/object:Gem::Requirement
38
+ requirement: &83684030 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *82060970
46
+ version_requirements: *83684030
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ripl-multi_line
49
- requirement: &82060740 !ruby/object:Gem::Requirement
49
+ requirement: &83683360 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,7 +54,29 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *82060740
57
+ version_requirements: *83683360
58
+ - !ruby/object:Gem::Dependency
59
+ name: powerline
60
+ requirement: &83682550 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *83682550
69
+ - !ruby/object:Gem::Dependency
70
+ name: gengin
71
+ requirement: &83681920 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *83681920
58
80
  description:
59
81
  email:
60
82
  - jody@jodysalt.com
@@ -69,7 +91,11 @@ files:
69
91
  - Rakefile
70
92
  - bin/rmap
71
93
  - lib/rmap.rb
94
+ - lib/rmap/commands.rb
72
95
  - lib/rmap/database.rb
96
+ - lib/rmap/generator_templates/conf.rmap.rb
97
+ - lib/rmap/generator_templates/migration.rmap.rb
98
+ - lib/rmap/migration.rb
73
99
  - lib/rmap/row.rb
74
100
  - lib/rmap/table.rb
75
101
  - lib/rmap/version.rb