rmap 0.1.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.
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: []