peacekeeper 0.0.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +119 -0
- data/Rakefile +12 -1
- data/lib/peacekeeper.rb +4 -5
- data/lib/peacekeeper/loader.rb +112 -0
- data/lib/peacekeeper/model.rb +122 -0
- data/lib/peacekeeper/model_delegation.rb +68 -0
- data/lib/peacekeeper/version.rb +1 -1
- data/test/fixtures/data/active_record/after_ar.rb +2 -0
- data/test/fixtures/data/active_record/after_setting_ar.rb +1 -0
- data/test/fixtures/data/active_record/before_ar.rb +2 -0
- data/test/fixtures/data/active_record/before_setting_ar.rb +1 -0
- data/test/fixtures/data/active_record/my_subtest_ar.rb +3 -0
- data/test/fixtures/data/active_record/my_test_ar.rb +5 -0
- data/test/fixtures/data/sequel/after.rb +2 -0
- data/test/fixtures/data/sequel/after_setting.rb +1 -0
- data/test/fixtures/data/sequel/before.rb +2 -0
- data/test/fixtures/data/sequel/before_setting.rb +1 -0
- data/test/fixtures/data/sequel/my_subtest.rb +3 -0
- data/test/fixtures/data/sequel/my_test.rb +5 -0
- data/test/peacekeeper/test_loader.rb +137 -0
- data/test/peacekeeper/test_model.rb +224 -0
- data/test/peacekeeper/test_orm_model.rb +115 -0
- data/test/test_helper.rb +32 -0
- metadata +177 -20
- data/.gitignore +0 -4
- data/Gemfile +0 -4
- data/peacekeeper.gemspec +0 -24
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1fa3eff5db180174619150ac1f8004706e6cfa9e
|
4
|
+
data.tar.gz: 9668cfd0a54b84b6825338f9dda8c5b8d4c11e7f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 73461cb3360790b227ddd4504858b112cd2db729d59af6c21893a9b702c5b0c3f04824f7a16250864464495c8923342f8110898cf545d5509f8ab94c1f51d7e9
|
7
|
+
data.tar.gz: fa72f99fef480695f45d4116c6b7226981ec95f21b25af8406058170eb09d946b3bf205ddd0224c911f0338f3eaf6cd6957494a96b1b0efb3005c11fef2233bf
|
data/README.md
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
## What is Peacekeeper?
|
2
|
+
|
3
|
+
Peacekeeper is a simple delegation library that allows the creation of business objects (Peacekeeper models) that hide the data objects they pull from. This allows a clean separation of business logic and data logic, without any kind of imposition on how the data is stored. Business objects (Peacekeeper models) can pull from an API resource or database resource, or this can be changed at runtime.
|
4
|
+
|
5
|
+
Peacekeeper delegates any unknown methods from your business objects directly to their respective data object.
|
6
|
+
|
7
|
+
examples usages for each DB type:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# API resource using Nasreddin
|
11
|
+
# lib/models/car_model.rb
|
12
|
+
class CarModel < Peacekeeper::Model
|
13
|
+
self.data_source = :api
|
14
|
+
# application specific business logic
|
15
|
+
end
|
16
|
+
|
17
|
+
# lib/data/api/car.rb
|
18
|
+
class Car < Nasreddin::Resource('cars')
|
19
|
+
# data retrieval logic
|
20
|
+
end
|
21
|
+
|
22
|
+
# Database resource using Sequel
|
23
|
+
# lib/models/car_model.rb
|
24
|
+
class CarModel < Peacekeeper::Model
|
25
|
+
self.data_source = :sequel # Can also use :active_record
|
26
|
+
# application specific business logic
|
27
|
+
end
|
28
|
+
|
29
|
+
# lib/data/sequel/car.rb
|
30
|
+
class Car < Sequel::Model
|
31
|
+
# data retrieval logic
|
32
|
+
end
|
33
|
+
|
34
|
+
# lib/data/active_record/car.rb
|
35
|
+
class Car < ActiveRecord::Base
|
36
|
+
# data retrieval logic
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
# Setting up Peacekeeper
|
41
|
+
Peacekeeper requires that your data source be configured. This can be done in a
|
42
|
+
yaml file:
|
43
|
+
|
44
|
+
```yaml
|
45
|
+
default: &default
|
46
|
+
adapter: <%= defined?(JRUBY_VERSION) ? 'jdbc:mysql':'mysql2' %>
|
47
|
+
username: root
|
48
|
+
password:
|
49
|
+
host: localhost
|
50
|
+
xa: false
|
51
|
+
|
52
|
+
development:
|
53
|
+
<<: *default
|
54
|
+
database: dev
|
55
|
+
test:
|
56
|
+
<<: *default
|
57
|
+
database: test
|
58
|
+
build:
|
59
|
+
<<: *default
|
60
|
+
database: build
|
61
|
+
staging:
|
62
|
+
<<: *default
|
63
|
+
database: staging
|
64
|
+
production:
|
65
|
+
<<: *default
|
66
|
+
database: production
|
67
|
+
```
|
68
|
+
|
69
|
+
# Sinatra
|
70
|
+
If you are using Sinatra, you can setup Peacekeeper with something like this in
|
71
|
+
your lib dir.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# lib/database.rb
|
75
|
+
dbcfg = File.read(File.expand_path('config/database.yml', APP_ROOT))
|
76
|
+
dbcfg = ERB.new(dbcfg).result(binding)
|
77
|
+
Peacekeeper::Model.config = YAML.load(dbcfg)[ENV['RACK_ENV']]
|
78
|
+
Sequel.default_timezone = :utc
|
79
|
+
```
|
80
|
+
|
81
|
+
# Rails
|
82
|
+
If you are using Rails, you can setup Peacekeeper with something like this in
|
83
|
+
your application.rb.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
# config/application.rb
|
87
|
+
class Application < Rails::Application
|
88
|
+
dbcfg = File.read(File.expand_path('config/database.yml', config.root))
|
89
|
+
dbcfg = ERB.new(dbcfg).result(binding)
|
90
|
+
Peacekeeper::Model.config = YAML.load(dbcfg)[Rails.env]
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
# Testing with Peacekeeper
|
95
|
+
Peacekeeper also makes testing easy with the :mock ORM type, this can be set in your test code which sets Peacekeeper to return mock objects from any delegated methods.
|
96
|
+
You will need a mocking library installed that responds to mock(). If you are using rspec, add this to your spec_helper.rb file:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
RSpec.configure do |config|
|
100
|
+
config.before(:all) do
|
101
|
+
Peacekeeper::Model.config[:mock_library] = 'mocha'
|
102
|
+
Peacekeeper::Model.data_source = :mock
|
103
|
+
end
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
example usage:
|
108
|
+
```ruby
|
109
|
+
describe 'CarModel' do
|
110
|
+
CarModel.data_source = :mock
|
111
|
+
# test business logic
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
# License
|
116
|
+
|
117
|
+
Copyright (C) 2012-2013 Burnside Digital
|
118
|
+
|
119
|
+
Licensed under the BSD 2-Clause License. See COPYING for license details.
|
data/Rakefile
CHANGED
@@ -1 +1,12 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'yard'
|
3
|
+
|
4
|
+
desc 'Run all the tests'
|
5
|
+
task :test do
|
6
|
+
sh 'bacon -a'
|
7
|
+
end
|
8
|
+
|
9
|
+
YARD::Rake::YardocTask.new do |t|
|
10
|
+
t.name = 'doc'
|
11
|
+
t.files = Dir["#{File.dirname(__FILE__)}/lib/**/*"]
|
12
|
+
end
|
data/lib/peacekeeper.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
1
|
+
require 'peacekeeper/version'
|
2
|
+
require 'peacekeeper/loader'
|
3
|
+
require 'peacekeeper/model_delegation'
|
4
|
+
require 'peacekeeper/model'
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Peacekeeper
|
2
|
+
class Loader
|
3
|
+
attr_reader :source, :config
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
@source = config[:source]
|
8
|
+
end
|
9
|
+
|
10
|
+
def load_source
|
11
|
+
case source
|
12
|
+
when :sequel
|
13
|
+
require 'sequel'
|
14
|
+
Sequel::Model.db = Sequel::DATABASES.find { |db| db.uri == sequel_db_uri } || Sequel.connect(sequel_db_uri)
|
15
|
+
when :active_record
|
16
|
+
require 'active_record'
|
17
|
+
ActiveRecord::Base.establish_connection(active_record_config)
|
18
|
+
when :api
|
19
|
+
require 'nasreddin'
|
20
|
+
when :mock
|
21
|
+
require config[:mock_library] if config[:mock_library]
|
22
|
+
#data_class # Trigger mock data_class creation
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# Construct uri to connect to database
|
28
|
+
# Sequel: http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html
|
29
|
+
def sequel_db_uri
|
30
|
+
# Set the protocol (DB engine; i.e. mysql, sqlite3, postgres, etc.)
|
31
|
+
protocol = config['protocol'] || config['adapter'] || 'sqlite'
|
32
|
+
if RUBY_ENGINE == 'jruby'
|
33
|
+
protocol = "jdbc:#{protocol}" unless protocol.start_with? "jdbc:"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Set the path (hostname & database name)
|
37
|
+
path = "#{config['host'] || config['path']}/#{config['database']}"
|
38
|
+
path = '' if path == '/' # Clear path if 'host', 'path', and 'database' are all unset
|
39
|
+
|
40
|
+
# Set the user and password
|
41
|
+
if RUBY_ENGINE == 'jruby' && protocol == 'jdbc:mysql'
|
42
|
+
# Special case for JRuby and MySQL
|
43
|
+
user_pass = "?user=#{config['username']}&password=#{config['password']}"
|
44
|
+
server_path = "#{path}#{user_pass}"
|
45
|
+
else
|
46
|
+
user_pass = "#{config['username']}:#{config['password']}@"
|
47
|
+
user_pass = '' if user_pass == ':@' # Clear user_pass if both 'username' and 'password' are unset
|
48
|
+
server_path = "#{user_pass}#{path}"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Finally, put the protocol and path components together
|
52
|
+
server_path = "/#{server_path}" unless server_path.empty?
|
53
|
+
uri = "#{protocol}:/#{server_path}"
|
54
|
+
uri = 'jdbc:sqlite::memory:' if uri == 'jdbc:sqlite:/' && RUBY_ENGINE == 'jruby'
|
55
|
+
if config['options']
|
56
|
+
if uri =~ /\?/
|
57
|
+
uri += "&#{paramize(config['options'])}"
|
58
|
+
else
|
59
|
+
uri += "?#{paramize(config['options'])}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
uri
|
63
|
+
end
|
64
|
+
|
65
|
+
def active_record_config
|
66
|
+
protocol = config['protocol'] || config['adapter'] || 'sqlite3'
|
67
|
+
# Set the adapter (DB engine; i.e. mysql, sqlite3, postgres, etc.)
|
68
|
+
|
69
|
+
database = config['database']
|
70
|
+
ar_config = {
|
71
|
+
adapter: protocol,
|
72
|
+
database: database
|
73
|
+
}
|
74
|
+
ar_config['host'] = config['host'] if config['host']
|
75
|
+
ar_config['username'] = config['username'] if config['username']
|
76
|
+
ar_config['password'] = config['password'] if config['password']
|
77
|
+
ar_config['driver'] = config['driver'] if config['driver']
|
78
|
+
ar_config
|
79
|
+
end
|
80
|
+
|
81
|
+
def paramize(options)
|
82
|
+
params = options.map { |k, v| "#{k}=#{v}" }
|
83
|
+
"#{params.join('&')}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
module DataLoader
|
88
|
+
def self.data_class(config)
|
89
|
+
source = config[:source]
|
90
|
+
data_lib_name = config[:data_lib_name]
|
91
|
+
data_name = config[:data_name]
|
92
|
+
if source.nil?
|
93
|
+
nil
|
94
|
+
elsif source == :mock
|
95
|
+
Kernel.const_set(data_name, Class.new do
|
96
|
+
def self.new(opts = {})
|
97
|
+
mock(self.name.gsub(/^.*:/, ''), opts)
|
98
|
+
end
|
99
|
+
def self.method_missing(*)
|
100
|
+
self.new
|
101
|
+
end
|
102
|
+
def self.respond_to?(*)
|
103
|
+
true
|
104
|
+
end
|
105
|
+
end)
|
106
|
+
else
|
107
|
+
require "data/#{source}/#{data_lib_name}"
|
108
|
+
Kernel.const_get(data_name)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Peacekeeper
|
2
|
+
class Model
|
3
|
+
kernel = ::Kernel.dup
|
4
|
+
kernel.class_eval do
|
5
|
+
[:to_s, :inspect, :=~, :!~, :===, :<=>, :eql?, :hash].each do |m|
|
6
|
+
undef_method m
|
7
|
+
end
|
8
|
+
end
|
9
|
+
include kernel
|
10
|
+
|
11
|
+
class<<self
|
12
|
+
include ModelDelegation
|
13
|
+
|
14
|
+
def new(*)
|
15
|
+
raise RuntimeError, "ModelObject cannot be instantiated directly. Please subclass first!" if self == Model
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def subclasses; (@subclasses ||= []); end
|
20
|
+
|
21
|
+
def config; (@config ||= {}); end
|
22
|
+
|
23
|
+
def config=(new_config)
|
24
|
+
@config = new_config
|
25
|
+
|
26
|
+
subclasses.each do |sub|
|
27
|
+
sub.config = @config
|
28
|
+
end
|
29
|
+
@config
|
30
|
+
end
|
31
|
+
|
32
|
+
def data_source; (@data_source ||= nil); end
|
33
|
+
|
34
|
+
def data_source=(source)
|
35
|
+
@data_source = source
|
36
|
+
@loader = Loader.new(config.merge(source: source))
|
37
|
+
@loader.load_source
|
38
|
+
|
39
|
+
if source == :mock
|
40
|
+
data_class # Trigger mock data_class creation
|
41
|
+
end
|
42
|
+
|
43
|
+
subclasses.each do |sub|
|
44
|
+
sub.data_source = @data_source
|
45
|
+
end
|
46
|
+
|
47
|
+
@data_source
|
48
|
+
end
|
49
|
+
|
50
|
+
def data_class
|
51
|
+
return nil if self == Model
|
52
|
+
@data_class ||= (data_source.nil? ? nil : DataLoader.data_class(data_name: data_name, data_lib_name: data_lib_name, source: data_source))
|
53
|
+
end
|
54
|
+
alias :delegate :data_class
|
55
|
+
|
56
|
+
def inherited(sub)
|
57
|
+
unless sub.name.nil?
|
58
|
+
subclasses << sub
|
59
|
+
sub.setup(self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def has_wrapper_for?(val)
|
64
|
+
!!wrapper_for(val)
|
65
|
+
end
|
66
|
+
|
67
|
+
def wrapper_for(val)
|
68
|
+
subclasses.find do |subclass|
|
69
|
+
val == subclass.delegate
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def setup(parent)
|
74
|
+
self.config = parent.config
|
75
|
+
self.data_source = parent.data_source
|
76
|
+
end
|
77
|
+
|
78
|
+
def data_name
|
79
|
+
self.name.sub(/Model$/, '')
|
80
|
+
end
|
81
|
+
|
82
|
+
def data_lib_name
|
83
|
+
name = data_name
|
84
|
+
name.gsub!(/::/, '/')
|
85
|
+
name.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
86
|
+
name.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
87
|
+
name.tr!("-", "_")
|
88
|
+
name.downcase!
|
89
|
+
name
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
include ModelDelegation
|
95
|
+
|
96
|
+
attr_reader :data
|
97
|
+
alias :delegate :data
|
98
|
+
|
99
|
+
def initialize(*args)
|
100
|
+
if !args.nil? && args.length == 1 && args.first.kind_of?(data_class)
|
101
|
+
@data = args.first
|
102
|
+
else
|
103
|
+
@data = data_class.new(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
unless self.class.instance_methods(false).include?(:to_json)
|
107
|
+
class<<self
|
108
|
+
undef_method :to_json if respond_to?(:to_json)
|
109
|
+
undef_method :as_json if respond_to?(:as_json)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def ==(obj)
|
115
|
+
obj.equal?(self) || @data == obj.data
|
116
|
+
end
|
117
|
+
|
118
|
+
def data_class
|
119
|
+
self.class.data_class
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Peacekeeper
|
2
|
+
module ModelDelegation
|
3
|
+
class Pass
|
4
|
+
def self.===(o)
|
5
|
+
false
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(mid, *args, &block)
|
10
|
+
if !delegate.nil? && delegate.respond_to?(mid)
|
11
|
+
mblock = begin
|
12
|
+
delegate.method(mid).to_proc
|
13
|
+
rescue NameError
|
14
|
+
proc do |*args, &block|
|
15
|
+
delegate.send(mid, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
define_wrapped_singleton_method(mid, mblock)
|
19
|
+
__send__(mid, *args, &block)
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def respond_to_missing?(mid, include_private)
|
26
|
+
ret = delegate.respond_to?(mid, include_private)
|
27
|
+
if ret && include_private && !delegate.respond_to?(mid, false)
|
28
|
+
# Don't delegate private methods
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
|
34
|
+
def wrap(val)
|
35
|
+
if (self.kind_of?(Class) && val.kind_of?(delegate))
|
36
|
+
new(val)
|
37
|
+
elsif (self.kind_of?(Peacekeeper::Model) && val.kind_of?(delegate.class))
|
38
|
+
self.class.new(val)
|
39
|
+
elsif (Peacekeeper::Model.has_wrapper_for?(val.class))
|
40
|
+
Peacekeeper::Model.wrapper_for(val.class).new(val)
|
41
|
+
elsif (val.kind_of?(Hash))
|
42
|
+
Hash[*val.flat_map { |k, v| [k, wrap(v)] }]
|
43
|
+
elsif (val.kind_of?(Enumerable) || val.methods.include?(:each))
|
44
|
+
val.map { |i| wrap(i) }
|
45
|
+
else
|
46
|
+
val
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def define_wrapped_singleton_method(mid, mblock)
|
51
|
+
define_singleton_method(mid) do |*args, &block|
|
52
|
+
wrap(mblock.call(*args, &block))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def def_data_method(mid, &mblock)
|
57
|
+
define_method(mid) do |*args|
|
58
|
+
wrap(delegate.instance_exec(*args, &mblock))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def def_singleton_data_method(mid, &mblock)
|
63
|
+
define_singleton_method(mid) do |*args|
|
64
|
+
wrap(delegate.instance_exec(*args, &mblock))
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/peacekeeper/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
class AfterSettingAr; end
|
@@ -0,0 +1 @@
|
|
1
|
+
class BeforeSettingAr; end
|
@@ -0,0 +1 @@
|
|
1
|
+
class AfterSetting; end
|
@@ -0,0 +1 @@
|
|
1
|
+
class BeforeSetting; end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Peacekeeper::Loader do
|
4
|
+
describe 'manages a data source selection' do
|
5
|
+
# Implementation deatail...
|
6
|
+
Peacekeeper::Model.instance_variable_set(:@subclasses, [])
|
7
|
+
|
8
|
+
it 'is nil by default' do
|
9
|
+
Peacekeeper::Model.data_source.should.be.nil
|
10
|
+
end
|
11
|
+
|
12
|
+
describe 'set to Sequel' do
|
13
|
+
before do
|
14
|
+
Peacekeeper::Model.data_source = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'requires the Sequel library' do
|
18
|
+
loader = mock("Loader")
|
19
|
+
loader.should.receive(:load_source)
|
20
|
+
Peacekeeper::Loader.should.receive(:new).and_return(loader)
|
21
|
+
Peacekeeper::Model.data_source = :sequel
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'loads the Data object for subclasses created before' do
|
25
|
+
loader = mock("Loader")
|
26
|
+
loader.should.receive(:load_source).times(3)
|
27
|
+
Peacekeeper::Loader.should.receive(:new).times(3).and_return(loader)
|
28
|
+
|
29
|
+
class BeforeModel < Peacekeeper::Model;
|
30
|
+
end
|
31
|
+
Peacekeeper::Model.data_source = :sequel
|
32
|
+
lambda do
|
33
|
+
BeforeModel.data_class.should.equal Before
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'loads the Data object for subclasses created after' do
|
38
|
+
loader = mock("Loader")
|
39
|
+
loader.should.receive(:load_source).times(3)
|
40
|
+
Peacekeeper::Loader.should.receive(:new).times(3).and_return(loader)
|
41
|
+
|
42
|
+
Peacekeeper::Model.data_source = :sequel
|
43
|
+
class AfterModel < Peacekeeper::Model;
|
44
|
+
end
|
45
|
+
lambda do
|
46
|
+
AfterModel.data_class.should.equal After
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'propogates the ORM setting to subclasses' do
|
51
|
+
class BeforeSettingModel < Peacekeeper::Model;
|
52
|
+
end
|
53
|
+
Peacekeeper::Model.data_source = :sequel
|
54
|
+
class AfterSettingModel < Peacekeeper::Model;
|
55
|
+
end
|
56
|
+
|
57
|
+
BeforeSettingModel.data_source.should.equal :sequel
|
58
|
+
AfterSettingModel.data_source.should.equal :sequel
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should only connect to the Database once' do
|
62
|
+
class BeforeModel < Peacekeeper::Model;
|
63
|
+
end
|
64
|
+
class BeforeSettingModel < Peacekeeper::Model;
|
65
|
+
end
|
66
|
+
Peacekeeper::Model.data_source = :sequel
|
67
|
+
class AfterModel < Peacekeeper::Model;
|
68
|
+
end
|
69
|
+
class AfterSettingModel < Peacekeeper::Model;
|
70
|
+
end
|
71
|
+
Sequel::DATABASES.length.should.equal 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'set to Active Record' do
|
76
|
+
before do
|
77
|
+
Peacekeeper::Model.data_source = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'requires the Active Record library' do
|
81
|
+
loader = mock("Loader")
|
82
|
+
loader.should.receive(:load_source).times(5)
|
83
|
+
Peacekeeper::Loader.should.receive(:new).times(5).and_return(loader)
|
84
|
+
Peacekeeper::Model.data_source = :active_record
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should connect to the Database' do
|
88
|
+
Peacekeeper::Model.data_source = :active_record
|
89
|
+
ActiveRecord::Base.connection() # Force AR to ~actually~ connect to the DB
|
90
|
+
ActiveRecord::Base.connected?.should.equal true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'set to mock' do
|
95
|
+
Peacekeeper::Model.data_source = :nil
|
96
|
+
Peacekeeper::Model.config[:mock_library] = 'facon'
|
97
|
+
|
98
|
+
it 'requires the facon library' do
|
99
|
+
loader = mock("Loader")
|
100
|
+
loader.should.receive(:load_source).times(5)
|
101
|
+
Peacekeeper::Loader.should.receive(:new).times(5).and_return(loader)
|
102
|
+
|
103
|
+
Peacekeeper::Model.data_source = :mock
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'creates a data class ready for mocking' do
|
107
|
+
class MyMockModel < Peacekeeper::Model; end
|
108
|
+
defined?(MyMock).should.equal 'constant'
|
109
|
+
MyMock.should.receive(:delegate_call)
|
110
|
+
MyMockModel.delegate_call
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'returns empty mocks for data class calls by default' do
|
114
|
+
class MyMockableModel < Peacekeeper::Model; end
|
115
|
+
|
116
|
+
foo = MyMockableModel.get_foo
|
117
|
+
|
118
|
+
foo.name.should.equal 'MyMockable'
|
119
|
+
foo.should.be.kind_of Facon::Mock
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns a mock with properties set when #new is called with options' do
|
123
|
+
class MyInstantiableMockModel < Peacekeeper::Model; end
|
124
|
+
|
125
|
+
user = MyInstantiableMockModel.new(name: "Joe", position: :employee, vacation_days: 14)
|
126
|
+
|
127
|
+
user.name.should.equal "Joe"
|
128
|
+
user.position.should.equal :employee
|
129
|
+
user.vacation_days.should.equal 14
|
130
|
+
end
|
131
|
+
|
132
|
+
# Implementation deatail...
|
133
|
+
Peacekeeper::Model.instance_variable_set(:@subclasses, [])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Peacekeeper::Model do
|
4
|
+
it 'cannot be instantiated directly' do
|
5
|
+
-> { Peacekeeper::Model.new }.should.raise(RuntimeError)
|
6
|
+
end
|
7
|
+
|
8
|
+
class SubclassTestModel < Peacekeeper::Model; end
|
9
|
+
|
10
|
+
it 'derives a model name based on the subclass\'s name' do
|
11
|
+
SubclassTestModel.data_name.should.equal 'SubclassTest'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'derives a data library name based on the subclass\'s name' do
|
15
|
+
SubclassTestModel.data_lib_name.should.equal 'subclass_test'
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'manages a database config' do
|
19
|
+
#it 'is empty by default' do
|
20
|
+
# Peacekeeper::Model.config.should.be.empty
|
21
|
+
#end
|
22
|
+
|
23
|
+
it 'is inherited by subclasses' do
|
24
|
+
path = 'tmp/test_db.sqlite'
|
25
|
+
class SubclassBeforeModel < Peacekeeper::Model;
|
26
|
+
end
|
27
|
+
Peacekeeper::Model.config = {path: path}
|
28
|
+
class SubclassAfterModel < Peacekeeper::Model;
|
29
|
+
end
|
30
|
+
|
31
|
+
SubclassBeforeModel.config[:path].should.equal path
|
32
|
+
SubclassAfterModel.config[:path].should.equal path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'used to create a model subclass with Sequel' do
|
37
|
+
# Repeat config here in case these tests are run alone
|
38
|
+
Peacekeeper::Model.config[:protocol] = 'jdbc:sqlite::memory:'
|
39
|
+
Peacekeeper::Model.data_source = :sequel
|
40
|
+
|
41
|
+
class MyTestModel < Peacekeeper::Model
|
42
|
+
def test
|
43
|
+
:ok
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class MySubtestModel < Peacekeeper::Model; end
|
48
|
+
|
49
|
+
# Setup the DB and populate with some test data
|
50
|
+
DB = Sequel::Model.db
|
51
|
+
DB.create_table :my_tests do
|
52
|
+
primary_key :id
|
53
|
+
foreign_key :other_id, :my_tests
|
54
|
+
String :name
|
55
|
+
end
|
56
|
+
DB[:my_tests].insert(id: 1, name: 'A Test')
|
57
|
+
DB[:my_tests].insert(id: 2, other_id: 1, name: 'Other')
|
58
|
+
DB[:my_tests].filter(id: 1).update(other_id: 2)
|
59
|
+
|
60
|
+
DB.create_table :my_subtests do
|
61
|
+
primary_key :id
|
62
|
+
foreign_key :my_test_id, :my_tests
|
63
|
+
String :name
|
64
|
+
end
|
65
|
+
DB[:my_subtests].insert(id: 1, my_test_id: 1, name: 'First')
|
66
|
+
DB[:my_subtests].insert(id: 2, my_test_id: 1, name: 'Second')
|
67
|
+
MySubtestModel.new # Instantiate to force loading of data class
|
68
|
+
|
69
|
+
it 'delegates data class methods to the data class' do
|
70
|
+
(MyTestModel.respond_to?(:table_name)).should.be.true
|
71
|
+
MyTestModel.table_name.should.equal :my_tests
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'when instantiated' do
|
75
|
+
my_test_model = MyTestModel.new
|
76
|
+
|
77
|
+
it 'creates a data instance' do
|
78
|
+
my_test_model.data.class.should.equal MyTest
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'delegates data methods to the data object' do
|
82
|
+
my_test_model.columns.should.equal [:id, :other_id, :name]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'still has access to methods defined on the model' do
|
86
|
+
my_test_model.test.should.be.equal :ok
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'wraps delegated methods that return data class instances' do
|
90
|
+
a_test = MyTestModel.filter(name: 'Other').first
|
91
|
+
a_test.other.should.be.kind_of MyTestModel
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'wraps a data object return value in a model object' do
|
96
|
+
res = MyTestModel.first
|
97
|
+
res.should.be.kind_of MyTestModel
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'wraps a collection of data object return values in model objects' do
|
101
|
+
res = MyTestModel.all
|
102
|
+
res.should.be.kind_of Array
|
103
|
+
res.each { |i| i.should.be.kind_of MyTestModel }
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'wraps return values from other model objects' do
|
107
|
+
test = MyTestModel.first
|
108
|
+
res = test.my_subtests
|
109
|
+
res.should.be.kind_of Array
|
110
|
+
res.each { |i| i.should.be.kind_of MySubtestModel }
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'maps a hash return value to a hash' do
|
114
|
+
res = MyTestModel.new.associations
|
115
|
+
res.should.be.kind_of Hash
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'delegates class methods with an argument' do
|
119
|
+
my_test_model = MyTestModel.create name: 'Another Test'
|
120
|
+
my_test_model.should.be.kind_of MyTestModel
|
121
|
+
MyTestModel.filter(name: 'Another Test').first.should.equal my_test_model
|
122
|
+
end
|
123
|
+
it 'should prevent calling :to_json inherited from Object' do
|
124
|
+
class Object
|
125
|
+
def to_json
|
126
|
+
raise "don't call me"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
class MyTestModel < Peacekeeper::Model
|
130
|
+
end
|
131
|
+
class MyTest
|
132
|
+
def to_json
|
133
|
+
:ok
|
134
|
+
end
|
135
|
+
end
|
136
|
+
MyTestModel.new.to_json.should.equal :ok
|
137
|
+
-> { Object.new.to_json }.should.raise(RuntimeError)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should allow redefinition of :to_json in the model' do
|
141
|
+
class Object
|
142
|
+
def to_json
|
143
|
+
raise "don't call me"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
class MyTestModel < Peacekeeper::Model
|
147
|
+
def to_json
|
148
|
+
:ok
|
149
|
+
end
|
150
|
+
end
|
151
|
+
class MyTest
|
152
|
+
def to_json
|
153
|
+
:ko
|
154
|
+
end
|
155
|
+
end
|
156
|
+
MyTestModel.new.to_json.should.equal :ok
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'can define methods that operate directly on the data class' do
|
160
|
+
class MyTestModel
|
161
|
+
def_data_method :others_first_subtest do
|
162
|
+
other.my_subtests.first
|
163
|
+
end
|
164
|
+
end
|
165
|
+
res = MyTestModel.filter(id: 2).first.others_first_subtest
|
166
|
+
res.should.be.kind_of MySubtestModel
|
167
|
+
res.name.should.equal 'First'
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'can define methods that operate directly on the data class and takes arguments' do
|
171
|
+
class MyTestModel
|
172
|
+
def_data_method :others_nth_subtest do |n|
|
173
|
+
other.my_subtests[n]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
res = MyTestModel.filter(id: 2).first.others_nth_subtest(1)
|
177
|
+
res.should.be.kind_of MySubtestModel
|
178
|
+
res.name.should.equal 'Second'
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'can define class methods that operate directly on the data class' do
|
182
|
+
class MyTestModel
|
183
|
+
def_singleton_data_method :first_subtest do
|
184
|
+
first.my_subtests.first
|
185
|
+
end
|
186
|
+
end
|
187
|
+
res = MyTestModel.first_subtest
|
188
|
+
res.should.be.kind_of MySubtestModel
|
189
|
+
res.name.should.equal 'First'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# These are too close to testing the implementation with the implementation.
|
194
|
+
# We should probably either test URL construction indirectly or using mocks.
|
195
|
+
# TODO: Implement a test for config['options'] as well.
|
196
|
+
#describe 'database connection uri' do
|
197
|
+
# username = Peacekeeper::Model.config['username'] = 'username'
|
198
|
+
# password = Peacekeeper::Model.config['password'] = 'password'
|
199
|
+
# host = Peacekeeper::Model.config['host'] = 'localhost'
|
200
|
+
# database = Peacekeeper::Model.config['database'] = 'database'
|
201
|
+
|
202
|
+
# describe "when specified adapter is 'jdbc:mysql'" do
|
203
|
+
# it 'generate uri for jdbc:mysql' do
|
204
|
+
# adapter = Peacekeeper::Model.config['adapter'] = 'jdbc:mysql'
|
205
|
+
# Peacekeeper::Model.sequel_db_uri.should.eql "#{adapter}://#{host}/#{database}?user=#{username}&password=#{password}"
|
206
|
+
# end
|
207
|
+
# end
|
208
|
+
|
209
|
+
# describe "when specified adapter is not 'jdbc:mysql'" do
|
210
|
+
# it 'generate non-jdbc uri' do
|
211
|
+
# adapter = Peacekeeper::Model.config['adapter'] = 'mysql2'
|
212
|
+
# Peacekeeper::Model.sequel_db_uri.should.eql "#{adapter}://#{username}:#{password}@#{host}/#{database}"
|
213
|
+
# end
|
214
|
+
# end
|
215
|
+
|
216
|
+
# describe "when no adapter is specified" do
|
217
|
+
# it 'generate sqlite uri' do
|
218
|
+
# Peacekeeper::Model.config = {}
|
219
|
+
# Peacekeeper::Model.sequel_db_uri.should.eql 'sqlite:/'
|
220
|
+
# end
|
221
|
+
# end
|
222
|
+
#end
|
223
|
+
end
|
224
|
+
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Peacekeeper::Model do
|
4
|
+
describe 'used to create a model subclass with Active Record' do
|
5
|
+
class MyTestArModel < Peacekeeper::Model
|
6
|
+
def test
|
7
|
+
:ok
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MySubtestArModel < Peacekeeper::Model; end
|
12
|
+
|
13
|
+
# Setup the DB and populate with some test data
|
14
|
+
Peacekeeper::Model.config['database'] = ':memory:'
|
15
|
+
Peacekeeper::Model.config[:protocol] = 'jdbc:sqlite:'
|
16
|
+
Peacekeeper::Model.data_source = :active_record
|
17
|
+
|
18
|
+
ActiveRecord::Base.connection.execute("CREATE TABLE my_test_ars (id INTEGER PRIMARY KEY, other_id INTEGER, name STRING);")
|
19
|
+
ActiveRecord::Base.connection.execute("CREATE TABLE my_subtest_ars (id INTEGER PRIMARY KEY, my_test_ar_id INTEGER, name STRING);")
|
20
|
+
|
21
|
+
ActiveRecord::Base.connection.execute("INSERT INTO my_test_ars (id,other_id,name) VALUES (1, 2, 'A Test');")
|
22
|
+
ActiveRecord::Base.connection.execute("INSERT INTO my_test_ars (id,other_id,name) VALUES (2, 1, 'Other');")
|
23
|
+
ActiveRecord::Base.connection.execute("INSERT INTO my_subtest_ars (id,my_test_ar_id,name) VALUES (1, 1, 'First');")
|
24
|
+
ActiveRecord::Base.connection.execute("INSERT INTO my_subtest_ars (id,my_test_ar_id,name) VALUES (2, 1, 'Second');")
|
25
|
+
|
26
|
+
it 'delegates data class methods to the data class' do
|
27
|
+
(MyTestArModel.respond_to?(:table_name)).should.be.true
|
28
|
+
MyTestArModel.table_name.should.equal "my_test_ars"
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'when instantiated' do
|
32
|
+
my_test_model = MyTestArModel.new
|
33
|
+
|
34
|
+
it 'creates a data instance' do
|
35
|
+
my_test_model.data.class.should.equal MyTestAr
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'delegates data methods to the data object' do
|
39
|
+
my_test_model.attribute_names.should.equal ['id', 'other_id', 'name']
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'still has access to methods defined on the model' do
|
43
|
+
my_test_model.test.should.be.equal :ok
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'wraps delegated methods that return data class instances' do
|
47
|
+
a_test = MyTestArModel.where(name: 'Other').first
|
48
|
+
a_test.other.should.be.kind_of MyTestArModel
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'wraps a data object return value in a model object' do
|
53
|
+
res = MyTestArModel.first
|
54
|
+
res.should.be.kind_of MyTestArModel
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'wraps a collection of data object return values in model objects' do
|
58
|
+
res = MyTestArModel.all
|
59
|
+
res.should.be.kind_of Array
|
60
|
+
res.each { |i| i.should.be.kind_of MyTestArModel }
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'wraps return values from other model objects' do
|
64
|
+
test = MyTestArModel.first
|
65
|
+
res = test.my_subtest_ars
|
66
|
+
res.should.be.kind_of Array
|
67
|
+
res.each { |i| i.should.be.kind_of MySubtestArModel }
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'maps a hash return value to a hash' do
|
71
|
+
res = MyTestArModel.new.attributes
|
72
|
+
res.should.be.kind_of Hash
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'delegates class methods with an argument' do
|
76
|
+
my_test_model = MyTestArModel.create name: 'Another Test'
|
77
|
+
my_test_model.should.be.kind_of MyTestArModel
|
78
|
+
MyTestArModel.where(name: 'Another Test').first.should.equal my_test_model
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'can define methods that operate directly on the data class' do
|
82
|
+
class MyTestArModel
|
83
|
+
def_data_method :others_first_subtest do
|
84
|
+
other.my_subtest_ars.first
|
85
|
+
end
|
86
|
+
end
|
87
|
+
res = MyTestArModel.where(id: 2).first.others_first_subtest
|
88
|
+
res.should.be.kind_of MySubtestArModel
|
89
|
+
res.name.should.equal 'First'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'can define methods that operate directly on the data class and takes arguments' do
|
93
|
+
class MyTestArModel
|
94
|
+
def_data_method :others_nth_subtest do |n|
|
95
|
+
other.my_subtest_ars[n]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
res = MyTestArModel.where(id: 2).first.others_nth_subtest(1)
|
99
|
+
res.should.be.kind_of MySubtestArModel
|
100
|
+
res.name.should.equal 'Second'
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'can define class methods that operate directly on the data class' do
|
104
|
+
class MyTestArModel
|
105
|
+
def_singleton_data_method :first_subtest do
|
106
|
+
first.my_subtest_ars.first
|
107
|
+
end
|
108
|
+
end
|
109
|
+
res = MyTestArModel.first_subtest
|
110
|
+
res.should.be.kind_of MySubtestArModel
|
111
|
+
res.name.should.equal 'First'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift File.expand_path('../fixtures', __FILE__)
|
3
|
+
|
4
|
+
require 'ruby-debug'
|
5
|
+
begin
|
6
|
+
require 'pry'
|
7
|
+
rescue LoadError
|
8
|
+
$stderr.puts 'Install the pry gem for better debugging.'
|
9
|
+
end
|
10
|
+
require 'facon'
|
11
|
+
require 'peacekeeper'
|
12
|
+
|
13
|
+
# Until JRuby fixes http://jira.codehaus.org/browse/JRUBY-6550 ...
|
14
|
+
class Should
|
15
|
+
def satisfy(*args, &block)
|
16
|
+
if args.size == 1 && String === args.first
|
17
|
+
description = args.shift
|
18
|
+
else
|
19
|
+
description = ""
|
20
|
+
end
|
21
|
+
|
22
|
+
# ToDo Jruby bug not yet resolved see http://jira.codehaus.org/browse/JRUBY-6550 Victor Christensen at 2:06 PM on 4/20/12
|
23
|
+
#r = yield(@object, *args)
|
24
|
+
r = yield(@object)
|
25
|
+
if Bacon::Counter[:depth] > 0
|
26
|
+
Bacon::Counter[:requirements] += 1
|
27
|
+
raise Bacon::Error.new(:failed, description) unless @negated ^ r
|
28
|
+
else
|
29
|
+
@negated ? !r : !!r
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,52 +1,209 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: peacekeeper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Josh Ballanco
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
14
|
-
|
15
|
-
|
11
|
+
date: 2013-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sequel
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.38.0
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 3.38.0
|
25
|
+
prerelease: false
|
26
|
+
type: :runtime
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.6
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 3.2.6
|
39
|
+
prerelease: false
|
40
|
+
type: :runtime
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activerecord-jdbc-adapter
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.2.2
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ~>
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.2.2
|
53
|
+
prerelease: false
|
54
|
+
type: :runtime
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nasreddin
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.3'
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ~>
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0.3'
|
67
|
+
prerelease: false
|
68
|
+
type: :runtime
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: jdbc-sqlite3
|
71
|
+
version_requirements: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.7.2
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ~>
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 3.7.2
|
81
|
+
prerelease: false
|
82
|
+
type: :development
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bacon
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.1.0
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.1.0
|
95
|
+
prerelease: false
|
96
|
+
type: :development
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: facon
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.5.0
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ~>
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 0.5.0
|
109
|
+
prerelease: false
|
110
|
+
type: :development
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: kramdown
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.13.7
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ~>
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 0.13.7
|
123
|
+
prerelease: false
|
124
|
+
type: :development
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yard
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.8.2
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ~>
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 0.8.2
|
137
|
+
prerelease: false
|
138
|
+
type: :development
|
139
|
+
description: Using Peacekeeper, you can develop models separately from the ORM used to persist data.
|
16
140
|
email:
|
17
141
|
- jballanc@gmail.com
|
18
142
|
executables: []
|
19
143
|
extensions: []
|
20
144
|
extra_rdoc_files: []
|
21
145
|
files:
|
22
|
-
- .gitignore
|
23
|
-
- Gemfile
|
24
|
-
- Rakefile
|
25
146
|
- lib/peacekeeper.rb
|
147
|
+
- lib/peacekeeper/loader.rb
|
148
|
+
- lib/peacekeeper/model.rb
|
149
|
+
- lib/peacekeeper/model_delegation.rb
|
26
150
|
- lib/peacekeeper/version.rb
|
27
|
-
-
|
151
|
+
- test/test_helper.rb
|
152
|
+
- test/fixtures/data/active_record/after_ar.rb
|
153
|
+
- test/fixtures/data/active_record/after_setting_ar.rb
|
154
|
+
- test/fixtures/data/active_record/before_ar.rb
|
155
|
+
- test/fixtures/data/active_record/before_setting_ar.rb
|
156
|
+
- test/fixtures/data/active_record/my_subtest_ar.rb
|
157
|
+
- test/fixtures/data/active_record/my_test_ar.rb
|
158
|
+
- test/fixtures/data/sequel/after.rb
|
159
|
+
- test/fixtures/data/sequel/after_setting.rb
|
160
|
+
- test/fixtures/data/sequel/before.rb
|
161
|
+
- test/fixtures/data/sequel/before_setting.rb
|
162
|
+
- test/fixtures/data/sequel/my_subtest.rb
|
163
|
+
- test/fixtures/data/sequel/my_test.rb
|
164
|
+
- test/peacekeeper/test_loader.rb
|
165
|
+
- test/peacekeeper/test_model.rb
|
166
|
+
- test/peacekeeper/test_orm_model.rb
|
167
|
+
- Rakefile
|
168
|
+
- README.md
|
28
169
|
homepage: ''
|
29
170
|
licenses: []
|
30
|
-
|
171
|
+
metadata: {}
|
172
|
+
post_install_message:
|
31
173
|
rdoc_options: []
|
32
174
|
require_paths:
|
33
175
|
- lib
|
34
176
|
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
177
|
requirements:
|
37
|
-
- -
|
178
|
+
- - '>='
|
38
179
|
- !ruby/object:Gem::Version
|
39
180
|
version: '0'
|
40
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
182
|
requirements:
|
43
|
-
- -
|
183
|
+
- - '>='
|
44
184
|
- !ruby/object:Gem::Version
|
45
185
|
version: '0'
|
46
186
|
requirements: []
|
47
187
|
rubyforge_project: peacekeeper
|
48
|
-
rubygems_version: 1.
|
49
|
-
signing_key:
|
50
|
-
specification_version:
|
188
|
+
rubygems_version: 2.1.10
|
189
|
+
signing_key:
|
190
|
+
specification_version: 4
|
51
191
|
summary: Peacekeeper handles delegation to a variety of ORMs
|
52
|
-
test_files:
|
192
|
+
test_files:
|
193
|
+
- test/test_helper.rb
|
194
|
+
- test/fixtures/data/active_record/after_ar.rb
|
195
|
+
- test/fixtures/data/active_record/after_setting_ar.rb
|
196
|
+
- test/fixtures/data/active_record/before_ar.rb
|
197
|
+
- test/fixtures/data/active_record/before_setting_ar.rb
|
198
|
+
- test/fixtures/data/active_record/my_subtest_ar.rb
|
199
|
+
- test/fixtures/data/active_record/my_test_ar.rb
|
200
|
+
- test/fixtures/data/sequel/after.rb
|
201
|
+
- test/fixtures/data/sequel/after_setting.rb
|
202
|
+
- test/fixtures/data/sequel/before.rb
|
203
|
+
- test/fixtures/data/sequel/before_setting.rb
|
204
|
+
- test/fixtures/data/sequel/my_subtest.rb
|
205
|
+
- test/fixtures/data/sequel/my_test.rb
|
206
|
+
- test/peacekeeper/test_loader.rb
|
207
|
+
- test/peacekeeper/test_model.rb
|
208
|
+
- test/peacekeeper/test_orm_model.rb
|
209
|
+
has_rdoc:
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/peacekeeper.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "peacekeeper/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "peacekeeper"
|
7
|
-
s.version = Peacekeeper::VERSION
|
8
|
-
s.authors = ["Josh Ballanco"]
|
9
|
-
s.email = ["jballanc@gmail.com"]
|
10
|
-
s.homepage = ""
|
11
|
-
s.summary = %q{Peacekeeper handles delegation to a variety of ORMs}
|
12
|
-
s.description = %q{Using Peacekeeper, you can develop models separately from the ORM used to persist data.}
|
13
|
-
|
14
|
-
s.rubyforge_project = "peacekeeper"
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
|
21
|
-
# specify any dependencies here; for example:
|
22
|
-
# s.add_development_dependency "rspec"
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
24
|
-
end
|