mysql2_model 0.1.1
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/.document +7 -0
- data/.gitignore +28 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +30 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +170 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/examples/mtdb.rb +43 -0
- data/examples/repositories.yml +26 -0
- data/examples/subscriber.rb +27 -0
- data/lib/mysql2_model/client.rb +66 -0
- data/lib/mysql2_model/composer.rb +105 -0
- data/lib/mysql2_model/config.rb +15 -0
- data/lib/mysql2_model/container.rb +167 -0
- data/lib/mysql2_model.rb +18 -0
- data/mysql2_model.gemspec +88 -0
- data/spec/mysql2_model/client_spec.rb +84 -0
- data/spec/mysql2_model/composer_spec.rb +123 -0
- data/spec/mysql2_model/config_spec.rb +10 -0
- data/spec/mysql2_model/container_spec.rb +48 -0
- data/spec/mysql2_model_spec.rb +7 -0
- data/spec/repositories.yml.fixture +26 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +43 -0
- metadata +174 -0
@@ -0,0 +1,167 @@
|
|
1
|
+
module Mysql2Model
|
2
|
+
|
3
|
+
# include this module in your class to inherit all of this awsomeness
|
4
|
+
# @example
|
5
|
+
# class MyClass
|
6
|
+
# include Mysql2Model::Container
|
7
|
+
# end
|
8
|
+
module Container
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
base.extend Forwardable
|
12
|
+
base.extend ClassMethods
|
13
|
+
base.extend Mysql2Model::Composer
|
14
|
+
#@TODO Do we need the delegators in the instance? ...not sure.
|
15
|
+
base.def_delegators :default_repository_config, :database, :username, :host, :password
|
16
|
+
base.class_eval do
|
17
|
+
class << self
|
18
|
+
extend Forwardable
|
19
|
+
def_delegators :default_repository_config, :database, :username, :host, :password
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# @raise [ArgumentError] Row must be a Hash
|
25
|
+
# @param [Hash] row Expects a row from a Mysql2 resultset
|
26
|
+
def initialize(row)
|
27
|
+
raise ArgumentError, "must be a hash" unless row.is_a?(Hash)
|
28
|
+
@attributes = row
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_repository_config # @private
|
32
|
+
self.class.default_repository_config
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to?(method) # @private
|
36
|
+
return true if @attributes.key?(method)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
# Delegate the id to the attribute :id insted of the Object_id
|
41
|
+
def id
|
42
|
+
@attributes[:id]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Provide dynamic accessors to the internal attributes only
|
46
|
+
def method_missing(method, *args, &block)
|
47
|
+
if @attributes.key?(method)
|
48
|
+
@attributes[method]
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#member notation convenience method
|
55
|
+
def [](method)
|
56
|
+
@attributes[method]
|
57
|
+
end
|
58
|
+
#member notation convenience method
|
59
|
+
def []=(method,value)
|
60
|
+
@attributes[method] = value
|
61
|
+
end
|
62
|
+
|
63
|
+
#datamapper style resource convenience method
|
64
|
+
def attribute_get(method)
|
65
|
+
@attributes[method]
|
66
|
+
end
|
67
|
+
|
68
|
+
#datamapper style resource convenience method
|
69
|
+
def attribute_set(method,value)
|
70
|
+
@attributes[method]=value
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
|
75
|
+
def default_repository_config # @private
|
76
|
+
OpenStruct.new(Mysql2Model::Client.repositories[default_repository_name][:config])
|
77
|
+
end
|
78
|
+
|
79
|
+
# Define which repository or repositories act as the destination(s) of your model.
|
80
|
+
# @example Single Repository
|
81
|
+
# class MyClass
|
82
|
+
# include Mysql2Model::Container
|
83
|
+
# self.default_repository_name
|
84
|
+
# :infrastructure
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
# @example Multiple Repositories
|
88
|
+
# class MyClass
|
89
|
+
# include Mysql2Model::Container
|
90
|
+
# self.default_repository_name
|
91
|
+
# [:db1,:db2,:db3]
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
# @todo Should probably rename this to just default_repository since Array != Symbol or just "repository"; "default_repository_name" came from Datamapper
|
95
|
+
# @abstract
|
96
|
+
def default_repository_name
|
97
|
+
:default
|
98
|
+
end
|
99
|
+
|
100
|
+
# Your models repository client via the cache
|
101
|
+
def client
|
102
|
+
Mysql2Model::Client[default_repository_name]
|
103
|
+
end
|
104
|
+
|
105
|
+
# @param [String] statement Uncomposed MySQL Statement
|
106
|
+
# @param [Array] args arguements for composure
|
107
|
+
# @yieldparam [String] composed_sql Composed MySQL Statement
|
108
|
+
# @yieldreturn the return of the block
|
109
|
+
def with_composed_sql(statement='',*args)
|
110
|
+
composed_sql = compose_sql(statement,*args).strip
|
111
|
+
log.info("SQL:[#{composed_sql}]")
|
112
|
+
yield composed_sql
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return the sum of adding the first value from each of the rows
|
116
|
+
# primarily useful with count queries running against multiple repos
|
117
|
+
# @todo considering renaming value_sum => value, value => value_for_each, but what happens if value is a String instead of Numeric?
|
118
|
+
# @todo Remove the block pattern, we will need to utilize the block for the evented query pattern
|
119
|
+
def value_sum(statement='',*args)
|
120
|
+
statement = yield if block_given?
|
121
|
+
with_composed_sql(statement,*args) do |sql|
|
122
|
+
client.query(sql).inject(0) { |sum,row|
|
123
|
+
sum += row.first.last
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Useful with queries that only return one result, like a COUNT.
|
129
|
+
# @return [Object] only the first value from the row when there is only one row
|
130
|
+
# @return [Array] that contains the first value from each row if multiple rows are returned; as in a COUNT against multiple repos
|
131
|
+
# @todo Remove the block pattern, we will need to utilize the block for the evented query pattern
|
132
|
+
def value(statement='',*args)
|
133
|
+
statement = yield if block_given?
|
134
|
+
with_composed_sql(statement,*args) do |composed_sql|
|
135
|
+
if (rv = client.query(composed_sql)).count > 1
|
136
|
+
rv.map {|row| row.first.last }
|
137
|
+
else
|
138
|
+
rv.first.first.last
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Flavor the behavior by returning the resultset as instances of self instead of Mysql2::Result
|
144
|
+
def query(statement='',*args)
|
145
|
+
statement = yield if block_given?
|
146
|
+
with_composed_sql(statement,*args) do |composed_sql|
|
147
|
+
response = client.query(composed_sql)
|
148
|
+
if response.respond_to?(:map)
|
149
|
+
response.map do |row|
|
150
|
+
# @todo Patch Mysql2 to support loading the primitives directly into custom class :as => CustomClass, and remove this map
|
151
|
+
# @todo This is defeating Mysql2's lazy loading, but it's good for proof-of-concept
|
152
|
+
self.new(row)
|
153
|
+
end
|
154
|
+
else
|
155
|
+
response
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
alias_method :execute, :query #allow the user to choose whether they want the mysql2 DSL or activerecord DSL
|
160
|
+
|
161
|
+
def log # @private
|
162
|
+
Mysql2Model::LOGGER
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
data/lib/mysql2_model.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'active_support/core_ext/time'
|
4
|
+
require 'active_support/core_ext/date_time'
|
5
|
+
require 'mysql2'
|
6
|
+
require 'forwardable'
|
7
|
+
require 'logging'
|
8
|
+
|
9
|
+
module Mysql2Model
|
10
|
+
VERSION = File.read(File.expand_path(File.dirname(__FILE__) + '/../VERSION')).strip
|
11
|
+
LOGGER = Logging.logger(STDOUT)
|
12
|
+
LOGGER.level = :info
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'mysql2_model/config'
|
16
|
+
require 'mysql2_model/client'
|
17
|
+
require 'mysql2_model/container'
|
18
|
+
require 'mysql2_model/composer'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{mysql2_model}
|
8
|
+
s.version = "0.1.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["donnoman"]
|
12
|
+
s.date = %q{2010-09-03}
|
13
|
+
s.description = %q{Provides a class suitable to be used as a model, that includes connection management, variable interpolation, object coercion and helper methods to support using direct MySQL statements for database interaction.}
|
14
|
+
s.email = %q{donnoman@donovanbray.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
".yardopts",
|
22
|
+
"CHANGELOG.md",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"MIT-LICENSE",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"examples/mtdb.rb",
|
30
|
+
"examples/repositories.yml",
|
31
|
+
"examples/subscriber.rb",
|
32
|
+
"lib/mysql2_model.rb",
|
33
|
+
"lib/mysql2_model/client.rb",
|
34
|
+
"lib/mysql2_model/composer.rb",
|
35
|
+
"lib/mysql2_model/config.rb",
|
36
|
+
"lib/mysql2_model/container.rb",
|
37
|
+
"mysql2_model.gemspec",
|
38
|
+
"spec/mysql2_model/client_spec.rb",
|
39
|
+
"spec/mysql2_model/composer_spec.rb",
|
40
|
+
"spec/mysql2_model/config_spec.rb",
|
41
|
+
"spec/mysql2_model/container_spec.rb",
|
42
|
+
"spec/mysql2_model_spec.rb",
|
43
|
+
"spec/repositories.yml.fixture",
|
44
|
+
"spec/spec.opts",
|
45
|
+
"spec/spec_helper.rb"
|
46
|
+
]
|
47
|
+
s.homepage = %q{http://github.com/donnoman/mysql2_model}
|
48
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
49
|
+
s.require_paths = ["lib"]
|
50
|
+
s.rubygems_version = %q{1.3.7}
|
51
|
+
s.summary = %q{Mysql2Model provides a container for creating model code based on MySQL Statements utilizing the Mysql2 client}
|
52
|
+
s.test_files = [
|
53
|
+
"spec/mysql2_model/client_spec.rb",
|
54
|
+
"spec/mysql2_model/container_spec.rb",
|
55
|
+
"spec/mysql2_model/config_spec.rb",
|
56
|
+
"spec/mysql2_model/composer_spec.rb",
|
57
|
+
"spec/mysql2_model_spec.rb",
|
58
|
+
"spec/spec_helper.rb",
|
59
|
+
"examples/mtdb.rb",
|
60
|
+
"examples/subscriber.rb"
|
61
|
+
]
|
62
|
+
|
63
|
+
if s.respond_to? :specification_version then
|
64
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
65
|
+
s.specification_version = 3
|
66
|
+
|
67
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
68
|
+
s.add_runtime_dependency(%q<mysql2>, ["~> 0.2"])
|
69
|
+
s.add_runtime_dependency(%q<activesupport>, ["~> 2.3"])
|
70
|
+
s.add_runtime_dependency(%q<builder>, ["~> 2.1.2"])
|
71
|
+
s.add_runtime_dependency(%q<logging>, ["~> 1"])
|
72
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.3"])
|
73
|
+
else
|
74
|
+
s.add_dependency(%q<mysql2>, ["~> 0.2"])
|
75
|
+
s.add_dependency(%q<activesupport>, ["~> 2.3"])
|
76
|
+
s.add_dependency(%q<builder>, ["~> 2.1.2"])
|
77
|
+
s.add_dependency(%q<logging>, ["~> 1"])
|
78
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
79
|
+
end
|
80
|
+
else
|
81
|
+
s.add_dependency(%q<mysql2>, ["~> 0.2"])
|
82
|
+
s.add_dependency(%q<activesupport>, ["~> 2.3"])
|
83
|
+
s.add_dependency(%q<builder>, ["~> 2.1.2"])
|
84
|
+
s.add_dependency(%q<logging>, ["~> 1"])
|
85
|
+
s.add_dependency(%q<rspec>, ["~> 1.3"])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Mysql2Model::Client do
|
4
|
+
describe "repositories" do
|
5
|
+
it "should have repositories" do
|
6
|
+
Mysql2Model::Client.repositories[:default].should_not be_nil
|
7
|
+
end
|
8
|
+
end
|
9
|
+
describe "getting repositories" do
|
10
|
+
it "should have a :default repository that is a 'Mysql2::Client'" do
|
11
|
+
Mysql2Model::Client[:default].class.name.should eql("Mysql2::Client")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
describe "setting repositories" do
|
15
|
+
it "should add the :mtdb1 repository" do
|
16
|
+
Mysql2Model::Client[:mtdb1] = YAML.load(File.read(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml')))[:repositories][:default]
|
17
|
+
Mysql2Model::Client[:mtdb1].class.name.should eql("Mysql2::Client")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
describe "load_repos" do
|
21
|
+
context "forced" do
|
22
|
+
it "should load_repos subsequent times" do
|
23
|
+
rv = YAML.load(File.new(Mysql2Model::Config.repository_path, 'r'))
|
24
|
+
YAML.should_receive(:load).twice.and_return(rv)
|
25
|
+
2.times do
|
26
|
+
Mysql2Model::Client.load_repos(true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
context "not forced" do
|
31
|
+
it "should not load_repos again" do
|
32
|
+
YAML.should_not_receive(:load)
|
33
|
+
Mysql2Model::Client.load_repos
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class M2MClient
|
40
|
+
include Mysql2Model::Container
|
41
|
+
def self.all
|
42
|
+
query("SELECT * FROM mysql2_model_test")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe M2MClient do
|
47
|
+
describe "default_repository_name" do
|
48
|
+
before :each do
|
49
|
+
Mysql2Model::Config.should_receive(:repository_path).any_number_of_times.and_return(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml'))
|
50
|
+
Mysql2Model::Client.load_repos(true)
|
51
|
+
end
|
52
|
+
describe "with multiple repositories" do
|
53
|
+
before :each do
|
54
|
+
Mysql2Model::Client[:default2] = YAML.load(File.read(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml')))[:repositories][:default]
|
55
|
+
Mysql2Model::Client[:default3] = YAML.load(File.read(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml')))[:repositories][:default]
|
56
|
+
M2MClient.stub!(:default_repository_name).and_return([:default,:default2,:default3])
|
57
|
+
end
|
58
|
+
it "should return single resultset of merged rows" do
|
59
|
+
M2MClient.all.size.should eql(6)
|
60
|
+
end
|
61
|
+
it "should add the values returned" do
|
62
|
+
M2MClient.value_sum("SELECT COUNT(*) from mysql2_model_test").should eql(6)
|
63
|
+
end
|
64
|
+
it "should return an array of values" do
|
65
|
+
M2MClient.value("SELECT COUNT(*) from mysql2_model_test").should eql([2,2,2])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
describe "with single repository" do
|
69
|
+
before :each do
|
70
|
+
M2MClient.stub!(:default_repository_name).and_return(:default)
|
71
|
+
end
|
72
|
+
it "should return single resultset" do
|
73
|
+
M2MClient.all.size.should eql(2)
|
74
|
+
end
|
75
|
+
it "should add the values returned" do
|
76
|
+
M2MClient.value_sum("SELECT COUNT(*) from mysql2_model_test").should eql(2)
|
77
|
+
end
|
78
|
+
it "should return the value" do
|
79
|
+
M2MClient.value("SELECT COUNT(*) from mysql2_model_test").should eql(2)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class M2MComposer
|
4
|
+
include Mysql2Model::Container
|
5
|
+
end
|
6
|
+
|
7
|
+
describe M2MComposer do
|
8
|
+
describe "compose_sql" do
|
9
|
+
context "string" do
|
10
|
+
it "should return the string" do
|
11
|
+
M2MComposer.compose_sql("one two three 4").should eql("one two three 4")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
context "array" do
|
15
|
+
it "should assemble use multiple arguments as the array" do
|
16
|
+
M2MComposer.compose_sql("%s %s %s %d",'one','two','three',4).should eql("one two three 4")
|
17
|
+
end
|
18
|
+
it "should support passing in an array" do
|
19
|
+
M2MComposer.compose_sql(["one two three 4",'one','two','three',4]).should eql("one two three 4")
|
20
|
+
end
|
21
|
+
it "should support passing in an array and single string" do
|
22
|
+
#or should this raise?
|
23
|
+
M2MComposer.compose_sql(["one two three 4"]).should eql("one two three 4")
|
24
|
+
end
|
25
|
+
it "should support printf style substitution" do
|
26
|
+
M2MComposer.compose_sql("%s %s %s %d",'one','two','three',4).should eql("one two three 4")
|
27
|
+
end
|
28
|
+
it "should support ? placeholders" do
|
29
|
+
M2MComposer.compose_sql("? ? ? ?",'one','two','three',4).should eql("one two three 4")
|
30
|
+
end
|
31
|
+
it "should support named bind variables" do
|
32
|
+
M2MComposer.compose_sql(":uno :dos :tres :cuatro :uno :dos :tres :cuatro",:uno => 'one', :dos => 'two',:tres => 'three', :cuatro => 4).should eql("one two three 4 one two three 4")
|
33
|
+
end
|
34
|
+
it "should raise an error with mismatched number of replacements" do
|
35
|
+
lambda { M2MComposer.compose_sql("? ? ? ?",'one','two','three') }.should raise_error(Mysql2Model::PreparedStatementInvalid)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
describe M2MComposer do
|
40
|
+
|
41
|
+
before :each do
|
42
|
+
@client = Mysql2Model::Client[:default]
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "query" do
|
46
|
+
it "should be composed with a string" do
|
47
|
+
@client.should_receive(:query).with("SELECT 1").and_return([])
|
48
|
+
M2MComposer.query("SELECT 1")
|
49
|
+
end
|
50
|
+
it "should be composed with multiple arguments" do
|
51
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
52
|
+
M2MComposer.query("%s %s %s %d",'one','two','three',4)
|
53
|
+
end
|
54
|
+
it "should be composed with an array" do
|
55
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
56
|
+
M2MComposer.query(["%s %s %s %d",'one','two','three',4])
|
57
|
+
end
|
58
|
+
context "with a block" do
|
59
|
+
it "should be composed when in an array" do
|
60
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
61
|
+
M2MComposer.query do
|
62
|
+
["%s %s %s %d",'one','two','three',4]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
it "should be composed when a string" do
|
66
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
67
|
+
M2MComposer.query do
|
68
|
+
"one two three 4"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "value" do
|
76
|
+
it "should be composed with a string" do
|
77
|
+
@client.should_receive(:query).with("SELECT 1").and_return([])
|
78
|
+
M2MComposer.query("SELECT 1")
|
79
|
+
end
|
80
|
+
it "should be composed with multiple arguments" do
|
81
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
82
|
+
M2MComposer.query("%s %s %s %d",'one','two','three',4)
|
83
|
+
end
|
84
|
+
it "should be composed with an array" do
|
85
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
86
|
+
M2MComposer.query(["%s %s %s %d",'one','two','three',4])
|
87
|
+
end
|
88
|
+
context "with a block" do
|
89
|
+
it "should be composed when in an array" do
|
90
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
91
|
+
M2MComposer.query do
|
92
|
+
["%s %s %s %d",'one','two','three',4]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
it "should be composed when a string" do
|
96
|
+
@client.should_receive(:query).with("one two three 4").and_return([])
|
97
|
+
M2MComposer.query do
|
98
|
+
"one two three 4"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "convert" do
|
105
|
+
context "time" do
|
106
|
+
it "should convert a time" do
|
107
|
+
M2MComposer.convert(Time.utc(2000,1,2,20,15,1)).should eql("2000-01-02 20:15:01")
|
108
|
+
end
|
109
|
+
it "should convert a date" do
|
110
|
+
M2MComposer.convert(Date.new(2000,1,2)).should eql("2000-01-02")
|
111
|
+
end
|
112
|
+
it "should convert a datetime" do
|
113
|
+
M2MComposer.convert(DateTime.new(2000,1,2,20,15,1)).should eql("2000-01-02 20:15:01")
|
114
|
+
end
|
115
|
+
it "should convert a time via query" do
|
116
|
+
M2MComposer.query("UPDATE mysql2_model_test SET created_at = '?' WHERE id = 1",Time.utc(2000,1,2,20,15,1))
|
117
|
+
M2MComposer.value("SELECT created_at FROM mysql2_model_test WHERE id = 1").should eql(Time.utc(2000,1,2,20,15,1))
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Mysql2Model::Config do
|
4
|
+
describe "repository_path" do
|
5
|
+
it "should be muteable" do
|
6
|
+
Mysql2Model::Config.repository_path = 'databases.yml'
|
7
|
+
Mysql2Model::Config.repository_path.should eql('databases.yml')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
class M2MContainer
|
4
|
+
include Mysql2Model::Container
|
5
|
+
|
6
|
+
def self.default_repository_array
|
7
|
+
[database,username,password,host]
|
8
|
+
end
|
9
|
+
|
10
|
+
def default_repository_array
|
11
|
+
[database,username,password,host]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe M2MContainer do
|
16
|
+
before :each do
|
17
|
+
Mysql2Model::Config.should_receive(:repository_path).any_number_of_times.and_return(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml.fixture'))
|
18
|
+
Mysql2Model::Client.load_repos(true)
|
19
|
+
end
|
20
|
+
describe "class" do
|
21
|
+
it "should have direct access to the default_repository hash members" do
|
22
|
+
M2MContainer.default_repository_array.should eql(['mysql2_model_test','root','gibberish','localhost'])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
describe "instance" do
|
26
|
+
it "should have direct access to the default_repository hash members" do
|
27
|
+
M2MContainer.new({}).default_repository_array.should eql(['mysql2_model_test','root','gibberish','localhost'])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe M2MContainer, "mysql2 methods" do
|
33
|
+
before :each do
|
34
|
+
Mysql2Model::Config.should_receive(:repository_path).any_number_of_times.and_return(File.expand_path(File.dirname(__FILE__) + '/../repositories.yml'))
|
35
|
+
Mysql2Model::Client.load_repos(true) #fooling with the class repository path, need to make sure we don't use the fixture
|
36
|
+
end
|
37
|
+
describe "query" do
|
38
|
+
it "should return an array with a member named 'test'" do
|
39
|
+
M2MContainer.query("SELECT * FROM mysql2_model_test").first.name.should eql('test')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "value" do
|
44
|
+
it "should return only the first value of the first row" do
|
45
|
+
M2MContainer.value("SELECT COUNT(*) FROM mysql2_model_test").should eql(2)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Mysql2Model" do
|
4
|
+
it "should report the same version as in the VERSION file" do
|
5
|
+
Mysql2Model::VERSION.to_s.should == IO.read(File.expand_path(File.dirname(__FILE__) + "/../VERSION")).strip
|
6
|
+
end
|
7
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
:repositories:
|
2
|
+
:default:
|
3
|
+
:database: mysql2_model_test
|
4
|
+
:username: root
|
5
|
+
:password: gibberish
|
6
|
+
:host: localhost
|
7
|
+
:secondary:
|
8
|
+
:database: mysql2_model_test
|
9
|
+
:username: root
|
10
|
+
:password: gibberish
|
11
|
+
:host: localhost
|
12
|
+
:m1:
|
13
|
+
:database: mysql2_model_test
|
14
|
+
:username: root
|
15
|
+
:password: gibberish
|
16
|
+
:host: localhost
|
17
|
+
:m2:
|
18
|
+
:database: mysql2_model_test
|
19
|
+
:username: root
|
20
|
+
:password: gibberish
|
21
|
+
:host: localhost
|
22
|
+
:m3:
|
23
|
+
:database: mysql2_model_test
|
24
|
+
:username: root
|
25
|
+
:password: gibberish
|
26
|
+
:host: localhost
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'mysql2_model'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'ruby-debug'
|
7
|
+
|
8
|
+
Spec::Runner.configure do |config|
|
9
|
+
config.before(:all) do
|
10
|
+
Mysql2Model::Config.repository_path = File.join(File.dirname(__FILE__), 'repositories.yml')
|
11
|
+
Mysql2Model::LOGGER.level = :fatal
|
12
|
+
client = Mysql2::Client.new(YAML.load(File.read(Mysql2Model::Config.repository_path))[:repositories][:default])
|
13
|
+
client.query %[ DROP TABLE IF EXISTS mysql2_model_test ]
|
14
|
+
client.query %[
|
15
|
+
CREATE TABLE IF NOT EXISTS mysql2_model_test (
|
16
|
+
id MEDIUMINT NOT NULL AUTO_INCREMENT,
|
17
|
+
name VARCHAR(40),
|
18
|
+
value VARCHAR(40),
|
19
|
+
created_at DATETIME,
|
20
|
+
updated_at DATETIME,
|
21
|
+
PRIMARY KEY (id)
|
22
|
+
)
|
23
|
+
]
|
24
|
+
client.query %[
|
25
|
+
INSERT INTO mysql2_model_test (
|
26
|
+
name, value, updated_at, created_at
|
27
|
+
)
|
28
|
+
|
29
|
+
VALUES (
|
30
|
+
'test', 'garbage', NOW(), NOW()
|
31
|
+
)
|
32
|
+
]
|
33
|
+
client.query %[
|
34
|
+
INSERT INTO mysql2_model_test (
|
35
|
+
name, value, updated_at, created_at
|
36
|
+
)
|
37
|
+
|
38
|
+
VALUES (
|
39
|
+
'test2', 'garbage2', NOW(), NOW()
|
40
|
+
)
|
41
|
+
]
|
42
|
+
end
|
43
|
+
end
|