rmap 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rmap.gemspec
4
+ gemspec
5
+
6
+ gem 'mysql2'
7
+ gem 'json'
8
+ gem 'ripl'
9
+ gem 'ripl-multi_line'
10
+
data/README.markdown ADDED
@@ -0,0 +1,124 @@
1
+
2
+ # Rmap - a simple yet powerfull object relational mapper
3
+
4
+ ##Installation
5
+
6
+ ```
7
+ gem install rmap
8
+ ```
9
+ or add the following to your gem file:
10
+
11
+ ```
12
+ gem 'rmap'
13
+ ```
14
+ and then run bundle install from your shell.
15
+
16
+ ##Basic configuration
17
+
18
+ ```ruby
19
+ require 'rmap'
20
+
21
+ db = Rmap::Database.new :database => 'rmap', :username => 'root'
22
+ ```
23
+ You can get more configuration options by going to the mysql2 gem documentation, as rmap wraps the mysql2 gem and simply passes through the conf hash to it:
24
+
25
+ * https://github.com/brianmario/mysql2
26
+
27
+ For instance a more advanced configuration might be:
28
+
29
+ ```ruby
30
+ require 'rmap'
31
+
32
+ db = Rmap::Database.new :database => 'rmap', :host => 'localhost', :username => 'root', :password => "secret"
33
+ ```
34
+
35
+ ## How to use
36
+
37
+ The following will return a representation of the 'posts' table:
38
+
39
+ ```ruby
40
+ db.posts
41
+ ```
42
+ ### Creating
43
+
44
+ You can insert rows into the posts table by doing the following:
45
+
46
+ ```ruby
47
+ db.posts.insert(:title => "Hello World", :body => "This is a test")
48
+ ```
49
+
50
+ ### Retrieval
51
+
52
+ You can list all the posts by doing the following:
53
+
54
+ ```ruby
55
+ db.posts.all.each do |post|
56
+ puts "title #{post.title}"
57
+ end
58
+ ```
59
+
60
+ You can list all the posts that contain the word apple by doing the following:
61
+
62
+ ```ruby
63
+ db.posts.contains(:body, "apple").all.each do |post|
64
+ puts "title #{post.title}"
65
+ end
66
+ ```
67
+
68
+ You can list all the posts that contain the word apple or pear by doing the following:
69
+
70
+ ```ruby
71
+ db.posts.contains(:body, ["apple", "pear"]).all.each do |post|
72
+ puts "title #{post.title}"
73
+ end
74
+ ```
75
+
76
+ You can retrieve a particular post (row) by doing the following:
77
+
78
+ ```ruby
79
+ db.posts.eq(:id, 7).first
80
+ ```
81
+
82
+ and then you can print the title to the screen:
83
+
84
+ ```ruby
85
+ puts db.posts.eq(:id, 7).first.title
86
+ ```
87
+
88
+ ### Joins
89
+
90
+ Joins are really easy. To retrieve all the posts by gmail users, you can do the following:
91
+
92
+ ```ruby
93
+ db.users.contains(:email, "@gmail.com").posts.all
94
+ ```
95
+
96
+ ### Deleting
97
+
98
+ You can delete all the posts by gmail users by doing the following:
99
+
100
+ ```ruby
101
+ db.users.contains(:email, "@gmail.com").posts.delete
102
+ ```
103
+
104
+ ### Updating
105
+
106
+ You can update all the posts by gmail users by doing the following:
107
+
108
+ ```ruby
109
+ db.users.contains(:email, "@gmail.com").posts.update(:published => true, :last_published => Time.now)
110
+ ```
111
+
112
+ or if you just want to update a column:
113
+
114
+ ```ruby
115
+ db.users.contains(:email, "@gmail.com").posts.published = true
116
+ ```
117
+
118
+ more coming soon....
119
+
120
+ ## License
121
+
122
+ Rmap is released under the MIT license:
123
+
124
+ * http://www.opensource.org/licenses/MIT
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/rmap ADDED
@@ -0,0 +1,18 @@
1
+
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
18
+
@@ -0,0 +1,61 @@
1
+
2
+ module Rmap
3
+ class Database
4
+
5
+ def initialize(conf={:username => 'root'})
6
+ @conf = conf
7
+ end
8
+
9
+ def client
10
+ if @client.nil?
11
+ @client = Mysql2::Client.new(@conf)
12
+ end
13
+ @client
14
+ end
15
+
16
+ def host(host)
17
+ @conf[:host] = host
18
+ end
19
+
20
+ def username(username)
21
+ @conf[:username] = username
22
+ end
23
+
24
+ def database(database)
25
+ @conf[:database] = database
26
+ end
27
+
28
+ def bindings
29
+ binding
30
+ end
31
+
32
+ def run(file_path)
33
+ instance_eval(::File.open(file_path).read, file_path)
34
+ end
35
+
36
+ def table?(name)
37
+ table_names.include?(name.to_s)
38
+ end
39
+
40
+ def method_missing name, *args
41
+ if table_names.include? name.to_s
42
+ Table.new(self, name)
43
+ else
44
+ super(name, *args)
45
+ end
46
+ end
47
+
48
+ def create(name)
49
+ @table_names = nil
50
+ client.query("create table `#{name}`(id int unsigned not null auto_increment primary key)")
51
+ end
52
+
53
+ def table_names
54
+ if @table_names.nil?
55
+ @table_names = client.query("show tables", :as => :array).map{|a| a[0]}
56
+ end
57
+ @table_names
58
+ end
59
+
60
+ end
61
+ end
data/lib/rmap/row.rb ADDED
@@ -0,0 +1,44 @@
1
+
2
+ require 'json'
3
+
4
+ module Rmap
5
+ class Row
6
+
7
+ attr_accessor :id
8
+
9
+ def initialize(database, table_name, id)
10
+ @database = database
11
+ @table_name = table_name
12
+ @id = id
13
+ end
14
+
15
+ def fetch(*args)
16
+ @database.client.query("select #{(args.map { |field| "`#{@database.client.escape(field.to_s)}`"}).join(', ')} from `#{@table_name}` where id = '#{id}'", :as => :array).first
17
+ end
18
+
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}'")
21
+ end
22
+
23
+ def delete
24
+ @database.client.query("delete from `#{@table_name}` where id = '#{id}'")
25
+ end
26
+
27
+ def method_missing name, *args
28
+ if @database.table? name
29
+ Table.new(@database, name).join(Table.new(@database, @table_name).eq(:id, @id), *args)
30
+ elsif name.match(/\A.*=\Z/) && @database.method_missing(@table_name).column?(name.to_s.sub(/=\Z/, ""))
31
+ update(name[/\A(.*)=\Z/, 1] => args[0])
32
+ elsif @database.method_missing(@table_name).column? name
33
+ fetch(name).first
34
+ else
35
+ super
36
+ end
37
+ end
38
+
39
+ def to_s
40
+ @database.client.query("select * from `#{@table_name}` where id = '#{id}'", :as => :hash).first.to_json
41
+ end
42
+
43
+ end
44
+ end
data/lib/rmap/table.rb ADDED
@@ -0,0 +1,328 @@
1
+
2
+ module Rmap
3
+ class Table
4
+ BINARY_FILTER_METHODS = {
5
+ 'eq' => lambda {|left,right| "#{left} = #{right}"},
6
+ 'ne' => lambda {|left,right| "#{left} != #{right}"},
7
+ 'lt' => lambda {|left,right| "#{left} < #{right}"},
8
+ 'gt' => lambda {|left,right| "#{left} > #{right}"},
9
+ 'le' => lambda {|left,right| "#{left} <= #{right}"},
10
+ 'ge' => lambda {|left,right| "#{left} >= #{right}"},
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}, '%')"},
14
+ 'year_eq' => lambda {|left,right| "year(#{left}) = #{right}"},
15
+ 'year_ne' => lambda {|left,right| "year(#{left}) != #{right}"},
16
+ 'year_lt' => lambda {|left,right| "year(#{left}) < #{right}"},
17
+ 'year_gt' => lambda {|left,right| "year(#{left}) > #{right}"},
18
+ 'year_le' => lambda {|left,right| "year(#{left}) <= #{right}"},
19
+ 'year_ge' => lambda {|left,right| "year(#{left}) >= #{right}"},
20
+ 'month_eq' => lambda {|left,right| "month(#{left}) = #{right}"},
21
+ 'month_ne' => lambda {|left,right| "month(#{left}) != #{right}"},
22
+ 'month_lt' => lambda {|left,right| "month(#{left}) < #{right}"},
23
+ 'month_gt' => lambda {|left,right| "month(#{left}) > #{right}"},
24
+ 'month_le' => lambda {|left,right| "month(#{left}) <= #{right}"},
25
+ 'month_ge' => lambda {|left,right| "month(#{left}) >= #{right}"},
26
+ 'day_eq' => lambda {|left,right| "day(#{left}) = #{right}"},
27
+ 'day_ne' => lambda {|left,right| "day(#{left}) != #{right}"},
28
+ 'day_lt' => lambda {|left,right| "day(#{left}) < #{right}"},
29
+ 'day_gt' => lambda {|left,right| "day(#{left}) > #{right}"},
30
+ 'day_le' => lambda {|left,right| "day(#{left}) <= #{right}"},
31
+ 'day_ge' => lambda {|left,right| "day(#{left}) >= #{right}"},
32
+ 'hour_eq' => lambda {|left,right| "hour(#{left}) = #{right}"},
33
+ 'hour_ne' => lambda {|left,right| "hour(#{left}) != #{right}"},
34
+ 'hour_lt' => lambda {|left,right| "hour(#{left}) < #{right}"},
35
+ 'hour_gt' => lambda {|left,right| "hour(#{left}) > #{right}"},
36
+ 'hour_le' => lambda {|left,right| "hour(#{left}) <= #{right}"},
37
+ 'hour_ge' => lambda {|left,right| "hour(#{left}) >= #{right}"},
38
+ 'minute_eq' => lambda {|left,right| "minute(#{left}) = #{right}"},
39
+ 'minute_ne' => lambda {|left,right| "minute(#{left}) != #{right}"},
40
+ 'minute_lt' => lambda {|left,right| "minute(#{left}) < #{right}"},
41
+ 'minute_gt' => lambda {|left,right| "minute(#{left}) > #{right}"},
42
+ 'minute_le' => lambda {|left,right| "minute(#{left}) <= #{right}"},
43
+ 'minute_ge' => lambda {|left,right| "minute(#{left}) >= #{right}"},
44
+ 'second_eq' => lambda {|left,right| "second(#{left}) = #{right}"},
45
+ 'second_ne' => lambda {|left,right| "second(#{left}) != #{right}"},
46
+ 'second_lt' => lambda {|left,right| "second(#{left}) < #{right}"},
47
+ 'second_gt' => lambda {|left,right| "second(#{left}) > #{right}"},
48
+ 'second_le' => lambda {|left,right| "second(#{left}) <= #{right}"},
49
+ 'second_ge' => lambda {|left,right| "second(#{left}) >= #{right}"},
50
+ }
51
+
52
+ attr_accessor :name
53
+
54
+ def initialize(database, name)
55
+ @database = database
56
+ @name = name
57
+ @binary_filter_methods_args = {}
58
+ Table::BINARY_FILTER_METHODS.each {|name, block| @binary_filter_methods_args[name] = []}
59
+ @join_list = []
60
+ @order_by_list = []
61
+ end
62
+
63
+ Table::BINARY_FILTER_METHODS.each do |name,block|
64
+ define_method name do |left, right|
65
+ @binary_filter_methods_args[name].push([left,right])
66
+ self
67
+ end
68
+ end
69
+
70
+ def join(table, options = {})
71
+ @join_list.push({:table => table, :options => options});
72
+ self
73
+ end
74
+
75
+ def order_by(sql_exression, desc = false)
76
+ @order_by_list.push([sql_exression, desc])
77
+ self
78
+ end
79
+
80
+ def column?(name)
81
+ @database.client.query("describe #{@name} `#{name}`").count > 0
82
+ end
83
+
84
+ def method_missing name, *args
85
+ if @database.table? name
86
+ Table.new(@database, name).join(self, *args)
87
+ elsif column? name
88
+ all.map{|row| row.fetch(name).first}
89
+ elsif column?(name.to_s.sub(/=\Z/, "")) && name.match(/\A(.*)=\Z/)
90
+ all.each{|row| row.update($1 => args[0])}
91
+ else
92
+ super
93
+ end
94
+ end
95
+
96
+ def format_sql(sql)
97
+ out_buffer = []
98
+ sql = sql.to_s
99
+ while sql.length > 0
100
+ if sql.match(/\A(\s+|\d+\.\d+|\d+|\w+\()(.*)/)
101
+ out_buffer.push($1)
102
+ sql = $2
103
+ elsif sql.match(/\A(\w+)\.(\w+)(.*)/)
104
+ out_buffer.push("`#{$1}`.`#{$2}`")
105
+ sql = $3
106
+ elsif sql.match(/\A(\w+)(.*)/)
107
+ out_buffer.push("`#{@name}`.`#{$1}`")
108
+ sql = $2
109
+ else
110
+ sql.match(/\A(.)(.*)/)
111
+ out_buffer.push($1)
112
+ sql = $2
113
+ end
114
+ end
115
+ out_buffer.join
116
+ end
117
+
118
+ def quote(data)
119
+ "'" + @database.client.escape(data.to_s) + "'"
120
+ end
121
+
122
+ def generate_filter_conditions_sql
123
+ and_sql = []
124
+ Table::BINARY_FILTER_METHODS.each do |name, block|
125
+ @binary_filter_methods_args[name].each do |args|
126
+ or_sql = []
127
+ if args[0].class.name == 'Array'
128
+ args[0].each do |left|
129
+ or_sql.push(block.call(format_sql(left.to_s), quote(args[1])))
130
+ end
131
+ elsif args[1].class.name == 'Array'
132
+ args[1].each do |right|
133
+ or_sql.push(block.call(format_sql(args[0].to_s), quote(right)))
134
+ end
135
+ else
136
+ or_sql.push(block.call(format_sql(args[0].to_s), quote(args[1])))
137
+ end
138
+ and_sql.push("(" + or_sql.join(' or ') + ")")
139
+ end
140
+ end
141
+ @join_list.each do |join|
142
+ and_sql.push(join[:table].generate_filter_conditions_sql)
143
+ end
144
+ and_sql.join(' and ')
145
+ end
146
+
147
+ def generate_table_list_sql
148
+ out = []
149
+ out.push(name)
150
+ @join_list.each do |join|
151
+ table_list_sql = join[:table].generate_table_list_sql
152
+ if table_list_sql != ''
153
+ out.push(table_list_sql)
154
+ end
155
+ end
156
+ out.join(', ')
157
+ end
158
+
159
+ def generate_from_sql
160
+ "from " + generate_table_list_sql
161
+ end
162
+
163
+ def generate_join_condition_sql(table1, table2, foreign_key)
164
+ if !foreign_key.nil?
165
+ if table2.column? foreign_key
166
+ "#{table1.name}.id = #{table2.name}.#{foreign_key}"
167
+ else
168
+ "#{table1.name}.#{foreign_key} = #{table2.name}.id"
169
+ end
170
+ else
171
+ if table2.column? "#{table1.name}_id"
172
+ "#{table1.name}.id = #{table2.name}.#{table1.name}_id"
173
+ else
174
+ "#{table1.name}.#{table2.name}_id = #{table2.name}.id"
175
+ end
176
+ end
177
+ end
178
+
179
+ def generate_inner_join_conditions_sql
180
+ out = []
181
+ @join_list.each do |join|
182
+ out.push(generate_join_condition_sql(self, join[:table], join[:options][:using]))
183
+ inner_join_conditions_sql = join[:table].generate_inner_join_conditions_sql
184
+ if inner_join_conditions_sql != ''
185
+ out.push(inner_join_conditions_sql)
186
+ end
187
+ end
188
+ out.join(" and ")
189
+ end
190
+
191
+ def generate_where_sql
192
+ out = []
193
+ inner_join_conditions_sql = generate_inner_join_conditions_sql
194
+ if inner_join_conditions_sql != ''
195
+ out.push inner_join_conditions_sql
196
+ end
197
+ filter_conditions_sql = generate_filter_conditions_sql
198
+ if filter_conditions_sql != ''
199
+ out.push filter_conditions_sql
200
+ end
201
+ out = out.join(' and ')
202
+ if out != ''
203
+ out = "where #{out}"
204
+ end
205
+ out
206
+ end
207
+
208
+ def generate_group_by_sql
209
+ if @join_list.count > 0
210
+ "group by #{name}.id"
211
+ end
212
+ end
213
+
214
+ def generate_order_by_sql
215
+ out = []
216
+ @order_by_list.each do |order_by|
217
+ (sql_expression, desc) = order_by
218
+ if desc
219
+ out.push "#{format_sql(sql_expression)} desc"
220
+ else
221
+ out.push "#{format_sql(sql_expression)} asc"
222
+ end
223
+ end
224
+ @join_list.each do |join|
225
+ order_by_sql = join[:table].generate_order_by_sql
226
+ if order_by_sql != ''
227
+ out.push(order_by_sql)
228
+ end
229
+ end
230
+ out = out.join(', ')
231
+ if out != ''
232
+ out = "order by #{out}"
233
+ end
234
+ out
235
+ end
236
+
237
+ def generate_select_sql(expression_list_sql, limit = nil)
238
+ if !limit.nil?
239
+ limit_sql = "limit #{limit}"
240
+ else
241
+ limit_sql = ''
242
+ end
243
+ "select #{format_sql(expression_list_sql)} #{generate_from_sql} #{generate_where_sql} #{generate_group_by_sql} #{generate_order_by_sql} #{limit_sql}"
244
+ end
245
+
246
+ def count(limit = nil)
247
+ @database.client.query(generate_select_sql('id', limit)).count
248
+ end
249
+
250
+ def all(limit = nil)
251
+ out = []
252
+ @database.client.query(generate_select_sql('id', limit), :as => :hash).each do |row|
253
+ out.push(Row.new(@database, @name, row['id']))
254
+ end
255
+ out
256
+ end
257
+
258
+ def each &block
259
+ all.each &block
260
+ nil
261
+ end
262
+
263
+ def first
264
+ all(1).first
265
+ end
266
+
267
+ def update(hash)
268
+ all.each {|row| row.update(hash)}
269
+ end
270
+
271
+ def delete
272
+ each {|row| row.delete}
273
+ end
274
+
275
+ def insert(hash)
276
+ @database.client.query("insert into `#{@name}`(#{(hash.map{|k,v| "`#{k}`"}).join(', ')}) values(#{(hash.map{|k,v| quote(v)}).join(', ')})")
277
+ end
278
+
279
+ def sum(sql_expression, limit = nil)
280
+ out = 0
281
+ @database.client.query(generate_select_sql("sum(#{sql_expression})", limit), :as => :array).each{|row| out += row.first}
282
+ out
283
+ end
284
+
285
+ def drop
286
+ eval("@table_names = nil", @database.bindings)
287
+ @database.client.query("drop table `#{@name}`")
288
+ end
289
+
290
+ def add(name, type, options = {})
291
+ case type
292
+ when :string
293
+ @database.client.query("alter table `#{@name}` add `#{name}` varchar(255) not null")
294
+ when :text
295
+ @database.client.query("alter table `#{@name}` add `#{name}` longtext not null")
296
+ when :binary
297
+ @database.client.query("alter table `#{@name}` add `#{name}` longblob not null")
298
+ when :integer
299
+ @database.client.query("alter table `#{@name}` add `#{name}` int signed not null")
300
+ when :foreign_key
301
+ @database.client.query("alter table `#{@name}` add `#{name}` int unsigned not null")
302
+ @database.client.query("alter table `#{@name}` add index(`#{name}`)")
303
+ when :date
304
+ @database.client.query("alter table `#{@name}` add `#{name}` date not null")
305
+ when :datetime
306
+ @database.client.query("alter table `#{@name}` add `#{name}` datetime not null")
307
+ when :boolean
308
+ @database.client.query("alter table `#{@name}` add `#{name}` enum('true', 'false') not null")
309
+ when :decimal
310
+ @database.client.query("alter table `#{@name}` add `#{name}` decimal not null")
311
+ end
312
+ end
313
+
314
+ def remove(name)
315
+ @database.client.query("alter table `#{@name}` drop `#{name}`")
316
+ end
317
+
318
+
319
+ def column_names
320
+ @database.client.query("describe `#{@name}`", :as => :hash).map {|row| row['Field']}
321
+ end
322
+
323
+ def to_s
324
+ all.to_s
325
+ end
326
+
327
+ end
328
+ end
@@ -0,0 +1,3 @@
1
+ module Rmap
2
+ VERSION = "0.1.0"
3
+ end
data/lib/rmap.rb ADDED
@@ -0,0 +1,10 @@
1
+
2
+ require 'mysql2'
3
+
4
+ require 'rmap/version'
5
+ require 'rmap/database'
6
+ require 'rmap/table'
7
+ require 'rmap/row'
8
+
9
+ module Rmap
10
+ end
data/rmap.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rmap/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rmap"
7
+ s.version = Rmap::VERSION
8
+ s.authors = ["Jody Salt"]
9
+ s.email = ["jody@jodysalt.com"]
10
+ s.homepage = "https://github.com/jodysalt/rmap"
11
+ s.summary = "A simple yet powerful object relational mapper (ORM)."
12
+
13
+ s.rubyforge_project = "rmap"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # specify any dependencies here; for example:
21
+ # s.add_development_dependency "rspec"
22
+ # s.add_runtime_dependency "rest-client"
23
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jody Salt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-10 00:00:00.000000000Z
13
+ dependencies: []
14
+ description:
15
+ email:
16
+ - jody@jodysalt.com
17
+ executables:
18
+ - rmap
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - README.markdown
25
+ - Rakefile
26
+ - bin/rmap
27
+ - lib/rmap.rb
28
+ - lib/rmap/database.rb
29
+ - lib/rmap/row.rb
30
+ - lib/rmap/table.rb
31
+ - lib/rmap/version.rb
32
+ - rmap.gemspec
33
+ homepage: https://github.com/jodysalt/rmap
34
+ licenses: []
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project: rmap
53
+ rubygems_version: 1.8.10
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: A simple yet powerful object relational mapper (ORM).
57
+ test_files: []