atomics_resource 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ ## production gems
4
+ gem "nokogiri"
5
+
6
+ ## dev gems
7
+ group :development do
8
+ gem "shoulda", ">= 0"
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+ gem "rcov", ">= 0"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,22 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.4)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ nokogiri (1.5.0)
10
+ rake (0.9.2)
11
+ rcov (0.9.10)
12
+ shoulda (2.11.3)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ bundler (~> 1.0.0)
19
+ jeweler (~> 1.6.4)
20
+ nokogiri
21
+ rcov
22
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Richard Lister
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,92 @@
1
+ = Atomics Resource
2
+
3
+ Ruby and/or Rails interface for Atomics queries. Atomics is MySQL over
4
+ HTTP, originally developed at CNET and has similar intent to DBSlayer.
5
+
6
+ == Philosophy
7
+
8
+ This module use a different approach from
9
+ e.g. activerecord-dbslayer-adapter, which subclasses the MySQL adapter
10
+ in order to use ActiveRecord. Rather, AtomicsResource is a lightweight
11
+ re-implementation of some ActiveRecord-style methods, which means the
12
+ module can be used in non-Rails apps, or mixed with non-MySQL
13
+ connections in a Rails app.
14
+
15
+ == Overview
16
+
17
+ Classes representing resources in atomics are created by subclassing
18
+ AtomicsResource::Base. Class find methods are mapped to HTTP GET
19
+ requests. XML responses are parsed and mapped to an instance of the
20
+ class.
21
+
22
+ === Configuration
23
+
24
+ To use an instance, you will need to create a yaml file with atomics
25
+ configs, e.g. config/atomics.yml:
26
+
27
+ hr:
28
+ host: hr-atomics.newco.com
29
+ port: 8080
30
+ path: /jAtomics/select/?version=1
31
+
32
+ then load the file into a hash called ATOMICS_CONFIG; in Rails this is
33
+ best done from an initializer, e.g. config/initializers/atomics_config.rb:
34
+
35
+ ATOMICS_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/atomics.yml")
36
+
37
+ === Usage
38
+
39
+ Your model will look like this:
40
+
41
+ class Employee < AtomicsResource::Base
42
+ set_atomics_type :hr #section of config file to read
43
+ set_table_name :employee_display #default table for requests
44
+ set_primary_key :id #default key for find() methods
45
+
46
+ ## default columns to SELECT, if none-given default will be '*'
47
+ column :first_name
48
+ column :last_name
49
+ column :title
50
+ column :team_id
51
+ end
52
+
53
+ and a simple controller:
54
+
55
+ class EmployeesController < ApplicationController
56
+ def index
57
+ @employees = Employee.all(:conditions => [ "team_id = ?", params[:team] ]
58
+ :order => [ :last_name, :first_name ])
59
+ end
60
+
61
+ def show
62
+ @employee = Employee.find(params[:id])
63
+ end
64
+ end
65
+
66
+ Conditions may be given as follows:
67
+
68
+ :conditions => "team_id = 156 AND title = 'Manager'"
69
+ :conditions => [ "team_id = ? AND title = ?", 156, 'Manager' ]
70
+ :conditions => [ "team_id = %d AND title = %s", 156 , 'Manager' ]
71
+ :conditions => { :team_id => 156, :title => :Manager }
72
+
73
+ Columns: in general you don't want to do "SELECT *" from Atomics
74
+ tables, which are frequently huge, denormalized beasts which will put
75
+ a lot of extra data on the wire that you don't want. Instead, list in
76
+ the model the columns you normally want, using 'column'. These will be
77
+ used to create the default 'SELECT' statement in find(). This can be
78
+ overridden using something like find(:all, :select=>'*').
79
+
80
+ Convenience functions:
81
+
82
+ Employee.all(99) ## equivalent to Employee.find(:all, :conditions => {:id = 99})
83
+ Employee.first(99) ## equivalent to Employee.find(:first, :conditions => {:id = 99})
84
+ Employee.last(99) ## equivalent to Employee.find(:last, :conditions => {:id = 99})
85
+
86
+ == Contributing to atomics_resource
87
+
88
+ The project is available for forking at github.
89
+
90
+ == Copyright
91
+
92
+ Copyright (c) 2011 Richard Lister. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "atomics_resource"
17
+ gem.homepage = "http://github.com/rlister/atomics_resource"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Active Model for Atomics MySQL lookups}
20
+ gem.description = %Q{Model Atomics (MySQL over HTTP) records for ruby and rails projects}
21
+ gem.email = "rlister@github"
22
+ gem.authors = ["Richard Lister"]
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ require 'rake/testtask'
27
+ Rake::TestTask.new(:test) do |test|
28
+ test.libs << 'lib' << 'test'
29
+ test.pattern = 'test/**/test_*.rb'
30
+ test.verbose = true
31
+ end
32
+
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/test_*.rb'
37
+ test.verbose = true
38
+ test.rcov_opts << '--exclude "gems/*"'
39
+ end
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "atomics_resource #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ## this does not run, but will show you how to configure against your local Atomics instance
4
+
5
+ require 'rubygems'
6
+ require 'atomics_resource'
7
+
8
+ ATOMICS_CONFIG = {
9
+ 'hr' => {
10
+ 'host' => 'hr-atomics.newco.com',
11
+ 'port' => '8080',
12
+ 'path' => '/jAtomics/select/?version=1',
13
+ },
14
+ 'other' => {
15
+ 'host' => 'other-atomics.for.illustration.com',
16
+ 'port' => '80',
17
+ 'path' => '/atomics/raw',
18
+ },
19
+ }
20
+
21
+ class Employee < AtomicsResource::Base
22
+ set_atomics_type :hr
23
+ set_table_name :employee_display
24
+ set_primary_key :id
25
+
26
+ column :first_name
27
+ column :last_name
28
+ column :title
29
+ column :team_id
30
+ end
31
+
32
+ employees = Employee.all(:conditions => {:team_id => 1},
33
+ :order => [:last_name, :first_name])
34
+
35
+ employees.each do |e|
36
+ puts "#{e.last_name},#{e.first_name}: #{e.title}"
37
+ end
@@ -0,0 +1,30 @@
1
+ #--
2
+ # Copyright (c) 2011 Richard Lister
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ ## ActiveModel-style interface for Atomics queries.
25
+
26
+ require 'atomics_resource/base.rb'
27
+
28
+ module AtomicsResource
29
+ ## noop
30
+ end
@@ -0,0 +1,246 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'net/http'
4
+
5
+ module AtomicsResource
6
+
7
+ class Base
8
+
9
+ ## class instance variables
10
+ class << self
11
+ attr_accessor :atomics_type, :table_name, :primary_key
12
+ alias_method :set_atomics_type, :atomics_type=
13
+ alias_method :set_table_name, :table_name=
14
+ alias_method :set_primary_key, :primary_key=
15
+ end
16
+
17
+ ## Get method for array of columns (attr_accessor will break for arrays on inheritance).
18
+ def self.columns
19
+ @columns ||= []
20
+ end
21
+
22
+ ## Add a column.
23
+ def self.column(value)
24
+ columns << value
25
+ end
26
+
27
+ ## Quote value for Atomics in SQL statment; numeric arguments returned unquoted,
28
+ ## strings in single quotes.
29
+ def self.quote_value(value)
30
+ value.match(/^\d+$/) ? value : "'#{value}'"
31
+ end
32
+
33
+ ## Build a SQL query string from hash of options passed to find.
34
+ def self.construct_sql(options)
35
+ sql = []
36
+ sql << "SELECT " + construct_sql_for_params(options[:select])
37
+ sql << "FROM " + construct_sql_for_params(options[:from])
38
+ sql << "WHERE " + construct_sql_for_conditions(options[:conditions]) if options[:conditions]
39
+ sql << "ORDER BY " + construct_sql_for_params(options[:order]) if options[:order]
40
+ sql << "LIMIT " + options[:limit].to_s if options[:limit]
41
+ sql << "OFFSET " + options[:offset].to_s if options[:offset]
42
+ sql.join(' ')
43
+ end
44
+
45
+ ## Return string for SQL conditions from values params as string, array, or hash.
46
+ def self.construct_sql_for_params(parms)
47
+ case parms
48
+ when Array; parms.map(&:to_s).join(',')
49
+ when Hash; parms.keys.map(&:to_s).join(',')
50
+ else parms.to_s
51
+ end
52
+ end
53
+
54
+ ## Return string for SQL conditions from options params as string, array, or hash.
55
+ def self.construct_sql_for_conditions(option)
56
+ case option
57
+ when Array; construct_sql_for_array(option)
58
+ when Hash; construct_sql_for_hash (option) ## :TODO: implement this
59
+ else option
60
+ end
61
+ end
62
+
63
+ ## Construct string of conditions from an array of format plus values to substitute.
64
+ ## Examples:
65
+ ## [ 'foo = ? AND bar = ?', 'hello', 99 ]
66
+ ## [ 'foo = %s AND bar = %d", 'hello', 99 ]
67
+ def self.construct_sql_for_array(a)
68
+ format, *values = a
69
+ if format.include?("\?")
70
+ raise ArgumentError unless format.count('\?') == values.size # sanity check right number args
71
+ format.gsub(/\?/) { quote_value(values.shift.to_s) } # replace all ? with args
72
+ elsif format.blank?
73
+ format
74
+ else # replace sprintf escapes
75
+ format % values.collect { |value| quote_value(value.to_s) }
76
+ end
77
+ end
78
+
79
+ ## Construct string of conditions from a hash of format plus values to substitute.
80
+ ## Allows conditions as hash of key/value pairs to be ANDed together.
81
+ ## Examples:
82
+ ## { :foo => :hello, :bar => 99 }
83
+ def self.construct_sql_for_hash(h)
84
+ h.map{|k,v| "#{k}=#{quote_value(v.to_s)}"}.join(' AND ')
85
+ end
86
+
87
+ ## Calls find and returns array of all matches.
88
+ def self.all(*args)
89
+ find(:all, *args)
90
+ end
91
+
92
+ ## Calls find and returns first matching object.
93
+ def self.first(*args)
94
+ find(:first, *args)
95
+ end
96
+
97
+ ## Calls find and returns last matching object.
98
+ def self.last(*args)
99
+ find(:last, *args)
100
+ end
101
+
102
+ ## Find takes a list of conditions as a hash, and returns array of matching objects.
103
+ ## If single argument is numeric, return first object to match by primary key.
104
+ def self.find(*arguments)
105
+ scope = arguments.slice!(0)
106
+ options = arguments.slice!(0) || {}
107
+
108
+ case scope
109
+ when :all then find_every(options) # Employee.find(:all, :conditions => 'team_id = 156')
110
+ when :first then find_every(options).first # Employee.find(:first, :conditions => 'team_id = 156')
111
+ when :last then find_every(options).last # Employee.find(:last, :conditions => 'team_id = 156')
112
+ else find_single(scope, options) # Employee.find(7923113)
113
+ end
114
+ end
115
+
116
+ ## Return array of columns to use for SELECT statements, ensuring we get primary_key, or single
117
+ ## string '*' if no columns set.
118
+ def self.columns_or_default
119
+ columns.empty? ? '*' : ([primary_key]+columns).uniq
120
+ end
121
+
122
+ ## Find array of all matching records.
123
+ def self.find_every(options)
124
+ defaults = { :select => columns_or_default, :from => table_name }
125
+ sql = construct_sql(defaults.merge(options))
126
+ find_by_sql(sql)
127
+ end
128
+
129
+ ## Find a single record with given primary key.
130
+ def self.find_single(scope, options)
131
+ defaults = { :select => columns_or_default, :from => table_name, :conditions => {primary_key => scope} }
132
+ sql = construct_sql(defaults)
133
+ find_by_sql(sql).first
134
+ end
135
+
136
+ ## Return string with whole URL for request, adding given SQL string as query.
137
+ def self.construct_url_for_sql(sql)
138
+ (host, port, path) = ATOMICS_CONFIG[atomics_type.to_s].values_at('host', 'port', 'path')
139
+ "http://#{host}:#{port}#{path}&q=#{URI.escape(sql)}"
140
+ end
141
+
142
+ ## Find matches using raw SQL statement given as a string.
143
+ ## args:: string containing SQL statement.
144
+ ## returns:: array of objects.
145
+ def self.find_by_sql(sql)
146
+ url = construct_url_for_sql(sql)
147
+
148
+ ## get the xml doc as a nokogiri object
149
+ doc = Nokogiri::XML(open(url))
150
+
151
+
152
+ ## array of records
153
+ records = doc.xpath('//record').to_a.map do |record|
154
+
155
+ ## convert record into a hash with name => value
156
+ hash = record.xpath('./field').inject({}) do |hash, field|
157
+ hash[field.xpath('./name')[0].content] = field.xpath('./value')[0].content
158
+ hash
159
+ end
160
+
161
+ ## instantiate record object
162
+ new(hash)
163
+ end
164
+
165
+ end
166
+
167
+ ## What uses this?
168
+ def self.to_model
169
+ self
170
+ end
171
+
172
+ ## instance variables
173
+ attr_accessor :attributes
174
+
175
+ ## Constructor allows hash as arg to set attributes.
176
+ def initialize(attributes = {})
177
+ hsh = {}
178
+ @attributes = hsh.respond_to?(:with_indifferent_access) ? hsh.with_indifferent_access : hsh
179
+ load(attributes)
180
+ end
181
+
182
+ ## Set attributes for an existing instance of this object.
183
+ def load(attributes)
184
+ raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
185
+ attributes.each do |key, value|
186
+ @attributes[key.to_s] = value.dup rescue value
187
+ end
188
+ self
189
+ end
190
+
191
+ ## Return formatted inspection string for record with attributes listed.
192
+ def inspect
193
+ attributes_string = @attributes.map{|k,v| "#{k}: #{value_for_inspect(v)}"}.join(', ')
194
+ "#<#{self.class} #{attributes_string}>"
195
+ end
196
+
197
+ ## Returns inspect for a value, with strings shortened to 50 chars, for use in Object.inspect.
198
+ def value_for_inspect(value)
199
+ if value.is_a?(String) && value.length > 50
200
+ "#{value[0..50]}...".inspect
201
+ else
202
+ value.inspect
203
+ end
204
+ end
205
+
206
+ ## Get attributes as methods, like active_model.
207
+ def method_missing(method_symbol, *arguments)
208
+ method_name = method_symbol.to_s
209
+ if method_name =~ /=$/
210
+ attributes[$`] = arguments.first
211
+ elsif method_name =~ /\?$/
212
+ attributes[$`]
213
+ else
214
+ return attributes[method_name] if attributes.include?(method_name)
215
+ super
216
+ end
217
+ end
218
+
219
+ ## Get attributes using hash syntax.
220
+ def [](attr)
221
+ attributes[attr]
222
+ end
223
+
224
+ ## Value of primary key.
225
+ def id
226
+ attributes[self.class.primary_key].to_i
227
+ end
228
+
229
+ ## What uses this?
230
+ def to_key
231
+ [id]
232
+ end
233
+
234
+ ## Return primary_key as param for object, for polymorphic route generation to work from object in view.
235
+ def to_param
236
+ attributes[self.class.primary_key]
237
+ end
238
+
239
+ end
240
+
241
+ ## Do some mix-ins to get various bits of rails coolness, skip these for non-rails.
242
+ if defined? RAILS_ROOT
243
+ extend ActiveModel::Naming # need this for model_name and variants, used to get paths from objects
244
+ end
245
+
246
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'rubygems'
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+
7
+ require 'atomics_resource'
@@ -0,0 +1,52 @@
1
+ require File.dirname(__FILE__) + '/helper.rb'
2
+
3
+ # ATOMICS_CONFIG = YAML.load_file("atomics.yml")
4
+
5
+ ATOMICS_CONFIG = {
6
+ 'my_type' => {
7
+ 'host' => 'orb-atomics.ops.aol.com',
8
+ 'port' => '8080',
9
+ 'path' => '/jAtomics/select/?version=1'
10
+ }
11
+ }
12
+
13
+ module AtomicsResource
14
+ describe Base do
15
+ before :each do
16
+ class MyTest < AtomicsResource::Base
17
+ set_atomics_type :my_type
18
+ set_table_name :my_table
19
+ set_primary_key :my_pk
20
+ end
21
+ end
22
+
23
+ context "class variables" do
24
+ it "should have class settings" do
25
+ MyTest.atomics_type.should == :my_type
26
+ MyTest.table_name.should == :my_table
27
+ MyTest.primary_key.should == :my_pk
28
+ end
29
+ end
30
+
31
+ context "atomics config" do
32
+ require 'uri'
33
+ it "should create a valid base URL" do
34
+ sql = "select * from foo where bar = 'wibble'"
35
+ URI.parse(MyTest.construct_url_for_sql(sql)).class.should == URI::HTTP
36
+ end
37
+ end
38
+
39
+ context "sql construction" do
40
+ it "should construct sql from array conditions" do
41
+ a = MyTest.construct_sql_for_conditions(["foo = \? AND bar = \?", :hello, :world])
42
+ a.should == "foo = 'hello' AND bar = 'world'"
43
+ end
44
+ it "should contruct sql from hash conditions" do
45
+ b = MyTest.construct_sql_for_conditions({:foo => :hello, :bar => :world})
46
+ b.should == "foo='hello' AND bar='world'"
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestAtomicsResource < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: atomics_resource
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Richard Lister
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-08-15 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: shoulda
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.0.0
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: jeweler
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.6.4
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rcov
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *id005
70
+ description: Model Atomics (MySQL over HTTP) records for ruby and rails projects
71
+ email: rlister@github
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files:
77
+ - LICENSE.txt
78
+ - README.rdoc
79
+ files:
80
+ - .document
81
+ - Gemfile
82
+ - Gemfile.lock
83
+ - LICENSE.txt
84
+ - README.rdoc
85
+ - Rakefile
86
+ - VERSION
87
+ - examples/employees.rb
88
+ - lib/atomics_resource.rb
89
+ - lib/atomics_resource/base.rb
90
+ - test/helper.rb
91
+ - test/spec_atomics_resource.rb
92
+ - test/test_atomics_resource.rb
93
+ homepage: http://github.com/rlister/atomics_resource
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 1985330703577403544
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: "0"
116
+ requirements: []
117
+
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.5
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Active Model for Atomics MySQL lookups
123
+ test_files: []
124
+