active-record-binder 1.1.0 → 1.2.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/README.md +217 -0
- data/bin/arb +13 -0
- data/doc/Binder.html +150 -0
- data/doc/Binder/AR.html +1880 -0
- data/doc/Binder/Command.html +252 -0
- data/doc/Binder/Help.html +374 -0
- data/doc/Binder/Migrate.html +682 -0
- data/doc/Binder/Strategy.html +550 -0
- data/doc/Binder/Version.html +285 -0
- data/doc/Class.html +220 -0
- data/doc/CommandParser.html +268 -0
- data/doc/CommandParser/ParseError.html +123 -0
- data/doc/DeferedDelegator.html +414 -0
- data/doc/MigrationProcessError.html +123 -0
- data/doc/MigrationVersionError.html +123 -0
- data/doc/String.html +245 -0
- data/doc/_index.html +256 -0
- data/doc/class_list.html +53 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +328 -0
- data/doc/file.README.html +300 -0
- data/doc/file_list.html +55 -0
- data/doc/frames.html +28 -0
- data/doc/index.html +300 -0
- data/doc/js/app.js +214 -0
- data/doc/js/full_list.js +173 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +348 -0
- data/doc/top-level-namespace.html +114 -0
- data/extras/cli_help.png +0 -0
- data/lib/active_record_binder.rb +21 -37
- data/lib/cli/command.rb +101 -0
- data/lib/cli/command_parser.rb +29 -0
- data/lib/cli/commands/commands.rb +4 -0
- data/lib/cli/commands/help.rb +35 -0
- data/lib/cli/commands/migrate.rb +77 -0
- data/lib/cli/commands/version.rb +16 -0
- data/lib/cli/core_ext.rb +21 -0
- data/lib/defered_delegator.rb +69 -0
- data/lib/version.rb +3 -0
- data/test/active_record_binder_test.rb +262 -0
- data/test/foo.sqlite3 +0 -0
- data/test/migrations.rb +29 -0
- data/test/minitest_helper.rb +15 -0
- data/test/mocks.rb +24 -0
- metadata +62 -5
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'version'
|
2
|
+
|
3
|
+
module Binder
|
4
|
+
# Public: [Command] Displays the current ARB version. Used via the `arb` command.
|
5
|
+
class Version < Binder::Strategy
|
6
|
+
def execute args
|
7
|
+
"Binder::AR::Version => #{Binder::VERSION}".colorize(:orange)
|
8
|
+
end
|
9
|
+
|
10
|
+
def description
|
11
|
+
"Displays Binder::AR's gem current version"
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_class :V
|
15
|
+
end
|
16
|
+
end
|
data/lib/cli/core_ext.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class Class
|
2
|
+
# Public: Handy ! Returns all subclasses of a specific class.
|
3
|
+
#
|
4
|
+
# Returns an Array of Classes.
|
5
|
+
def subclasses
|
6
|
+
ObjectSpace.each_object(Class).select { |klass| klass < self }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class String
|
11
|
+
# Public: Colorize a string for a Unix terminal.
|
12
|
+
#
|
13
|
+
# code - The color code: a Numeric [0-255] or a Symbol [:red, :green, :orange, :purple, :rose].
|
14
|
+
#
|
15
|
+
# Returns a colorized string.
|
16
|
+
def colorize code
|
17
|
+
colors = { red: 31, green: 32, orange: 33, purple: 34, rose: 35 }
|
18
|
+
code = colors[code] unless code.kind_of? Numeric
|
19
|
+
"\e[#{code}m#{self}\e[0m"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Private: A simple module that delegates classes methods when needed, keeping the calls in memory.
|
2
|
+
#
|
3
|
+
# Examples
|
4
|
+
#
|
5
|
+
# class Foo
|
6
|
+
# def self.foo arg
|
7
|
+
# "World of #{arg}"
|
8
|
+
# end
|
9
|
+
# #
|
10
|
+
# def self.bar
|
11
|
+
# "Hello"
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# class Baz
|
16
|
+
# extend DeferedDelegator
|
17
|
+
# register_delegators :bar, :foo
|
18
|
+
# #
|
19
|
+
# def initialize obj
|
20
|
+
# @obj = obj
|
21
|
+
# end
|
22
|
+
# #
|
23
|
+
# def foobar
|
24
|
+
# delegate_to @obj
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# class Bar < Baz
|
29
|
+
# foo "Foo"
|
30
|
+
# bar
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Bar.new Foo
|
34
|
+
# Bar.foobar
|
35
|
+
# # => "World of Foo"
|
36
|
+
# # => "Hello"
|
37
|
+
module DeferedDelegator
|
38
|
+
# Public: Allows to register delegators
|
39
|
+
#
|
40
|
+
# args - List of Symbols, the method name that will be delegated.
|
41
|
+
#
|
42
|
+
# Returns Nothing.
|
43
|
+
def register_delegators *args
|
44
|
+
args.each do |delegator|
|
45
|
+
delegator = delegator.to_s
|
46
|
+
module_eval %Q{
|
47
|
+
def self.#{delegator} *parameters
|
48
|
+
@delegators ||= []
|
49
|
+
@delegators << { name: :#{delegator}, params: parameters }
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public: Triggers the delegation and run the delegated methods
|
56
|
+
#
|
57
|
+
# klass_or_object - A Class or an Object to delegate to.
|
58
|
+
#
|
59
|
+
# Returns Nothing.
|
60
|
+
def delegate_to klass_or_object
|
61
|
+
@delegators.each do |data|
|
62
|
+
unless data.empty?
|
63
|
+
name = data[:name]
|
64
|
+
args = data[:params]
|
65
|
+
klass_or_object.send(name, *args)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
require_relative 'minitest_helper'
|
2
|
+
require_relative '../lib/active_record_binder'
|
3
|
+
require_relative './mocks'
|
4
|
+
require_relative './migrations'
|
5
|
+
|
6
|
+
describe Binder::AR do
|
7
|
+
describe 'Database information' do
|
8
|
+
context 'default' do
|
9
|
+
it 'should have a sensible default to an ENV variable' do
|
10
|
+
ENV['APP_DB'] = 'Foo'
|
11
|
+
Binder::AR.default_database.must_equal ENV['APP_DB']
|
12
|
+
end
|
13
|
+
end # default
|
14
|
+
|
15
|
+
context 'specified' do
|
16
|
+
it 'should have a way to set a database' do
|
17
|
+
Binder::AR.database 'Foobar'
|
18
|
+
Binder::AR.database.must_equal 'Foobar'
|
19
|
+
end
|
20
|
+
it 'should switch to default if nothing is specified' do
|
21
|
+
Binder::AR.database nil
|
22
|
+
Binder::AR.database.must_equal Binder::AR.default_database
|
23
|
+
end
|
24
|
+
context 'each subclass' do
|
25
|
+
it 'should have different settings from another' do
|
26
|
+
MockBond.database 'Bar'
|
27
|
+
OtherMockBond.database 'Baz'
|
28
|
+
MockBond.database.must_equal 'Bar'
|
29
|
+
OtherMockBond.database.must_equal 'Baz'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end # Specified
|
33
|
+
end # Database
|
34
|
+
|
35
|
+
describe 'Connection adapter' do
|
36
|
+
context 'default' do
|
37
|
+
it 'should use sqlite as a default adapter' do
|
38
|
+
Binder::AR.default_adapter.must_equal :sqlite3
|
39
|
+
end
|
40
|
+
end
|
41
|
+
context 'specified' do
|
42
|
+
it 'should give a way to set a specific adapter' do
|
43
|
+
Binder::AR.adapter :mysql2
|
44
|
+
Binder::AR.adapter.must_equal :mysql2
|
45
|
+
end
|
46
|
+
it 'should use sqlite if nothing is specified' do
|
47
|
+
Binder::AR.adapter nil
|
48
|
+
Binder::AR.adapter.must_equal Binder::AR.default_adapter
|
49
|
+
end
|
50
|
+
context 'each subclass' do
|
51
|
+
it 'should have different settings from another' do
|
52
|
+
MockBond.adapter 'Bar'
|
53
|
+
OtherMockBond.adapter 'Baz'
|
54
|
+
MockBond.adapter.must_equal 'Bar'
|
55
|
+
OtherMockBond.adapter.must_equal 'Baz'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end # specified
|
59
|
+
end # Connection adapter
|
60
|
+
|
61
|
+
describe 'Connection params' do
|
62
|
+
it 'should give a way to set connection parameters' do
|
63
|
+
params = { user: 'Poney', password: 'Poney234' }
|
64
|
+
Binder::AR.connect_with params
|
65
|
+
Binder::AR.connect_with.must_equal params
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'Binder Object' do
|
70
|
+
let(:binder) { MockBond.new :foo }
|
71
|
+
it 'On instanciation, should automaticaly create an AR Record object matching the table name and namespaced under the current binder class' do
|
72
|
+
binder.table.must_equal binder.class::Foo
|
73
|
+
end
|
74
|
+
end # Connection parms
|
75
|
+
|
76
|
+
describe 'AR Bound Object' do
|
77
|
+
let(:model) { MockBond.new(:foo).table }
|
78
|
+
|
79
|
+
it 'should be an instance of a subclass ActiveRecord::Base' do
|
80
|
+
model.superclass.must_equal ActiveRecord::Base
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'connection' do
|
84
|
+
it 'should respond to connect' do
|
85
|
+
model.must_respond_to :connect
|
86
|
+
end
|
87
|
+
it 'should respond to connected?' do
|
88
|
+
model.must_respond_to :connected?
|
89
|
+
end
|
90
|
+
it 'should be connected automaticaly on instanciation' do
|
91
|
+
# Should be replace with something else, but it activates the connection so it's pretty easy
|
92
|
+
model.first
|
93
|
+
model.connected?.must_equal true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe 'ActiveRecord methods' do
|
98
|
+
it 'should respond to find' do
|
99
|
+
model.must_respond_to :find
|
100
|
+
end
|
101
|
+
it 'should respond to first' do
|
102
|
+
model.must_respond_to :first
|
103
|
+
end
|
104
|
+
it 'should respond to all' do
|
105
|
+
model.must_respond_to :all
|
106
|
+
end
|
107
|
+
it 'should respond to delete' do
|
108
|
+
model.must_respond_to :delete
|
109
|
+
end
|
110
|
+
it 'should respond to update_attributes' do
|
111
|
+
model.first.must_respond_to :update_attributes
|
112
|
+
end
|
113
|
+
it 'should respond to save' do
|
114
|
+
model.new.must_respond_to :save
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe 'ActiveRecord relations' do
|
119
|
+
it 'should handle one to one relationships' do
|
120
|
+
model.has_one :article
|
121
|
+
model.first.article.must_equal Article.first
|
122
|
+
end
|
123
|
+
|
124
|
+
# As it's active record, it should work with other associations types too.
|
125
|
+
# TODO: Test other associations
|
126
|
+
end
|
127
|
+
end # Ar Bound Object
|
128
|
+
|
129
|
+
describe 'Migration system' do
|
130
|
+
context 'schema definition' do
|
131
|
+
let(:migration) { FooCreateTable }
|
132
|
+
|
133
|
+
it 'should have a Version method' do
|
134
|
+
Binder::AR.must_respond_to :Version
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'inheriting through the Version method should create a subclass of ActiveRecord::Migration' do
|
138
|
+
migration.superclass.superclass.must_equal ActiveRecord::Migration
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'Versionning' do
|
142
|
+
it "should have a version method, that returns this migration's version" do
|
143
|
+
migration.version.must_equal 1.0
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end # schema definition
|
147
|
+
|
148
|
+
context 'migration' do
|
149
|
+
it 'should have a migrate method' do
|
150
|
+
Binder::AR.must_respond_to :migrate
|
151
|
+
MockBond.must_respond_to :migrate
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should create a schema containing the metadata for the migration system, namespaced inside the binder' do
|
155
|
+
# Reset migrations
|
156
|
+
MockBond.migrate 0
|
157
|
+
MockBond.migrate
|
158
|
+
MockBond::MetaSchema.must_be_kind_of Object
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'can take a version number as an argument and return the executed-down-to migration number' do
|
162
|
+
MockBond.migrate(1.0).must_equal 1.0
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'should fail if the migration version specified does not exist' do
|
166
|
+
->{ MockBond.migrate(10.0) }.must_raise MigrationVersionError
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'migrate up and down' do
|
170
|
+
before do
|
171
|
+
# Make sure that we are at the first migration
|
172
|
+
MockBond.migrate 0
|
173
|
+
MockBond.migrate 1.0
|
174
|
+
@schema = MockBond.meta_schema
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should set the current migration to the desired number' do
|
178
|
+
MockBond.migrate 1.1
|
179
|
+
@schema.first.version.must_equal 1.1
|
180
|
+
end
|
181
|
+
it 'should make the change for the desired migration' do
|
182
|
+
MockBond.migrate 1.1
|
183
|
+
tags = MockBond.new(:tag).table
|
184
|
+
tags.create(name: 'foobar')
|
185
|
+
tags.first.name.must_equal "foobar"
|
186
|
+
end
|
187
|
+
|
188
|
+
describe 'version unspecified' do
|
189
|
+
it 'should migrate to the last version' do
|
190
|
+
MockBond.migrate
|
191
|
+
@schema.first.version.must_equal 1.1
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context 'Schema MetaDatas' do
|
197
|
+
before do
|
198
|
+
MockBond.meta_schema
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'should inherit from ActiveRecord::Base' do
|
202
|
+
MockBond::MetaSchema.superclass.must_equal ActiveRecord::Base
|
203
|
+
end
|
204
|
+
|
205
|
+
describe 'Meta schema' do
|
206
|
+
let(:meta_schema) { MockBond.meta_schema }
|
207
|
+
|
208
|
+
it 'should be accessible through the method schema_meta' do
|
209
|
+
meta_schema.must_equal MockBond::MetaSchema
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'should create a metadata table namespaced under the binder class name' do
|
213
|
+
meta_schema.table_name.must_equal "mock_bond_meta_schemas"
|
214
|
+
end
|
215
|
+
|
216
|
+
its 'table should have a version column' do
|
217
|
+
meta_schema.new.must_respond_to :version
|
218
|
+
end
|
219
|
+
end # Describe Meta Schema
|
220
|
+
end # Context Schema Metadatas
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class TestDelegators
|
227
|
+
extend DeferedDelegator
|
228
|
+
end
|
229
|
+
|
230
|
+
class TestDelegatedTo
|
231
|
+
def self.foo
|
232
|
+
@@test ||= []
|
233
|
+
@@test << true
|
234
|
+
end
|
235
|
+
|
236
|
+
def self.bar
|
237
|
+
@@test ||= []
|
238
|
+
@@test << false
|
239
|
+
end
|
240
|
+
|
241
|
+
def self.test
|
242
|
+
@@test
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe DeferedDelegator do
|
247
|
+
it 'provides a way to register delegators for a class' do
|
248
|
+
TestDelegators.register_delegators :foo
|
249
|
+
TestDelegators.must_respond_to :foo
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'provides a way to call the delegation process and execute every registered delegation' do
|
253
|
+
TestDelegators.register_delegators :foo, :bar
|
254
|
+
|
255
|
+
TestDelegators.foo
|
256
|
+
TestDelegators.bar
|
257
|
+
|
258
|
+
TestDelegators.delegate_to TestDelegatedTo
|
259
|
+
|
260
|
+
TestDelegatedTo.test.must_equal [true, false]
|
261
|
+
end
|
262
|
+
end
|
data/test/foo.sqlite3
ADDED
Binary file
|
data/test/migrations.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative './mocks'
|
2
|
+
require_relative '../lib/active_record_binder'
|
3
|
+
|
4
|
+
class FooCreateTable < MockBond::Version 1.0
|
5
|
+
def self.up
|
6
|
+
create_table :tags do |t|
|
7
|
+
t.string :name
|
8
|
+
t.integer :tag_id, default: 0
|
9
|
+
t.timestamps
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.down
|
14
|
+
drop_table :tags
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class BarCreateTable < MockBond::Version 1.1
|
19
|
+
def self.up
|
20
|
+
create_table :foobz do |t|
|
21
|
+
t.string :foobar
|
22
|
+
t.timestamps
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.down
|
27
|
+
drop_table :foobz
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
require 'mocha/setup'
|
5
|
+
|
6
|
+
require 'turn/autorun'
|
7
|
+
Turn.config.format = :pretty
|
8
|
+
|
9
|
+
class MiniTest::Spec
|
10
|
+
class << self
|
11
|
+
alias :its :it
|
12
|
+
alias :they :it
|
13
|
+
alias :context :describe
|
14
|
+
end
|
15
|
+
end
|
data/test/mocks.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../lib/active_record_binder'
|
2
|
+
|
3
|
+
# Helper
|
4
|
+
class Class
|
5
|
+
def __DIR__
|
6
|
+
File.expand_path File.dirname(__FILE__)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class MockBond < Binder::AR
|
11
|
+
database __DIR__ + '/foo.sqlite3'
|
12
|
+
adapter :sqlite3
|
13
|
+
|
14
|
+
has_one :article
|
15
|
+
end
|
16
|
+
|
17
|
+
class OtherMockBond < Binder::AR
|
18
|
+
database :bar
|
19
|
+
adapter :sqlite3
|
20
|
+
end
|
21
|
+
|
22
|
+
# See test/foo.sqlite3
|
23
|
+
class Article < ActiveRecord::Base
|
24
|
+
end
|