active_finite 0.1.3 → 0.1.4
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.rdoc +20 -23
- data/Rakefile +3 -4
- data/VERSION +1 -1
- data/lib/active_finite.rb +81 -9
- data/spec/active_finite_spec.rb +117 -76
- metadata +6 -6
data/README.rdoc
CHANGED
@@ -15,32 +15,30 @@ Let's start by defining a simple migration:
|
|
15
15
|
|
16
16
|
class Hellos < ActiveRecord::Migration
|
17
17
|
self.up
|
18
|
-
|
19
|
-
t.string default_column_name, :null => false
|
20
|
-
end
|
21
|
-
create_finite in_table: :hellos, values: ['oy', 'que tal', 'hi']
|
18
|
+
add_finites in_table: :hellos, values: ['oy', 'que tal', 'hi']
|
22
19
|
end
|
23
20
|
|
24
21
|
self.down
|
25
|
-
|
26
|
-
drop_table :hellos
|
22
|
+
delete_finites in_table: :hellos, values: ['oy', 'que tal', 'hi']
|
27
23
|
end
|
28
24
|
end
|
29
25
|
|
30
|
-
Note that if it doesn't matter what the column's name is, the method
|
31
|
-
default_column_name can be used.
|
32
|
-
|
33
26
|
Now that we some hellos in our Hello model, we can access them using:
|
34
|
-
hellos =
|
27
|
+
hellos = get_finite_table :hellos
|
35
28
|
|
36
29
|
The variable hellos now holds a class derived from ActiveRecord named
|
37
30
|
Hello, so all of the normal ActiveRecord methods can be used.
|
38
|
-
|
39
|
-
|
31
|
+
|
32
|
+
We can also a collection of all of the active record classes defined by
|
33
|
+
active_finite by using:
|
34
|
+
all_finite_tables
|
35
|
+
|
36
|
+
Using get_finite_table and all_finite_tables implicitly bring the associated
|
37
|
+
classes into scope, so a single call to all_finite_tables is sufficent to
|
38
|
+
define all of the models.
|
40
39
|
|
41
40
|
== Other options
|
42
|
-
If the column name must be different than the default
|
43
|
-
an existing database), the column_name option can be used. Also, a json
|
41
|
+
If the column name must be different than the default, the column_name option can be used. Also, a json
|
44
42
|
file can be used instead of explicitly listing the possible values in
|
45
43
|
the migration. For example:
|
46
44
|
|
@@ -49,22 +47,21 @@ the migration. For example:
|
|
49
47
|
require 'active_support/core_ext'
|
50
48
|
class HellosWithCustomColumn < ActiveRecord::Migration
|
51
49
|
self.up
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
values: ['oy', 'que tal', 'hi']
|
57
|
-
column_name: :custom
|
58
|
-
from_file: 'hellos.json'
|
50
|
+
add_finites in_table: :hellos,
|
51
|
+
values: ['oy', 'que tal', 'hi']
|
52
|
+
column_name: :custom
|
53
|
+
from_file: 'hellos.json'
|
59
54
|
end
|
60
55
|
|
61
56
|
self.down
|
62
|
-
|
63
|
-
drop_table :hellos
|
57
|
+
delete_finites in_table: :hellos, values: all
|
64
58
|
end
|
65
59
|
end
|
66
60
|
|
67
61
|
If both values and from_file are defined, active_finite will pull entries from both.
|
62
|
+
Another option to be aware of is that values do not have to be explicitly listed
|
63
|
+
upon deletion, using the all option is sufficent.
|
64
|
+
|
68
65
|
|
69
66
|
== Other ideas
|
70
67
|
Combine active_finite with foreigner[https://github.com/matthuhiggins/foreigner] to put foreign key constraints on users of defined enums.
|
data/Rakefile
CHANGED
@@ -13,11 +13,10 @@ require 'jeweler'
|
|
13
13
|
Jeweler::Tasks.new do |gem|
|
14
14
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
15
|
gem.name = "active_finite"
|
16
|
-
gem.homepage = "http://github.com/
|
16
|
+
gem.homepage = "http://github.com/r4pdevteam/active_finite"
|
17
17
|
gem.license = "MIT"
|
18
|
-
gem.summary = %Q{
|
19
|
-
|
20
|
-
gem.description = %Q{see README.rdoc}
|
18
|
+
gem.summary = %Q{one-line summary of your gem}
|
19
|
+
gem.description = %Q{longer description of your gem}
|
21
20
|
gem.email = "me@stuffihavemade.com"
|
22
21
|
gem.authors = ["me"]
|
23
22
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/lib/active_finite.rb
CHANGED
@@ -4,13 +4,68 @@ require 'active_support/inflector'
|
|
4
4
|
require 'active_record'
|
5
5
|
require 'json'
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
Object.
|
7
|
+
def get_finite_table sym, *args
|
8
|
+
class_name = as_class_name sym
|
9
|
+
class_not_defined = not(Object.const_defined? class_name)
|
10
|
+
should_force = args.any? {|x| x == :force}
|
11
|
+
if class_not_defined or should_force
|
12
|
+
anon = Class.new ActiveRecord::Base
|
13
|
+
Object.const_set class_name, anon
|
14
|
+
else
|
15
|
+
Object.const_get class_name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def as_class_name table_name
|
20
|
+
table_name.to_s.singularize.capitalize.to_sym
|
21
|
+
end
|
22
|
+
|
23
|
+
def all_finite_tables
|
24
|
+
master = get_finite_table(master_table_name)
|
25
|
+
if master.table_exists?
|
26
|
+
master
|
27
|
+
.where("#{default_column_name} != ?", master_table_name)
|
28
|
+
.collect {|x| x.send default_column_name.to_s}
|
29
|
+
.collect {|x| get_finite_table x}
|
30
|
+
else
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def master_table_name
|
36
|
+
:active_finites
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_to_master table_name
|
40
|
+
add_finites in_table: master_table_name, values: [table_name]
|
41
|
+
end
|
42
|
+
|
43
|
+
def delete_from_master table_name
|
44
|
+
delete_finites in_table: master_table_name, values: [table_name]
|
10
45
|
end
|
11
46
|
|
12
|
-
def
|
47
|
+
def is_in_master_table? table_name
|
48
|
+
if table_name.eql? master_table_name
|
49
|
+
true
|
50
|
+
else
|
51
|
+
get_finite_table(master_table_name)
|
52
|
+
.where("#{default_column_name} != ?", master_table_name)
|
53
|
+
.where("#{default_column_name} == ?", table_name)
|
54
|
+
.any?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
def add_finites args
|
13
60
|
modify_finite args do |vs, klass, column_name|
|
61
|
+
if not klass.table_exists?
|
62
|
+
ActiveRecord::Schema.define do
|
63
|
+
create_table klass.table_name do |t|
|
64
|
+
t.string column_name, :null => false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
add_to_master klass.table_name
|
68
|
+
end
|
14
69
|
vs.each do |v|
|
15
70
|
obj = klass.new
|
16
71
|
obj.send column_name.to_s + '=', v
|
@@ -19,13 +74,30 @@ def create_finite args
|
|
19
74
|
end
|
20
75
|
end
|
21
76
|
|
22
|
-
def
|
77
|
+
def delete_finites args,
|
78
|
+
delete_all = args[:values] == :all
|
79
|
+
if delete_all
|
80
|
+
args[:values] = []
|
81
|
+
end
|
23
82
|
modify_finite args do |vs, klass, column_name|
|
24
|
-
|
25
|
-
|
26
|
-
objs.each do |o|
|
83
|
+
if delete_all
|
84
|
+
klass.all.each do |o|
|
27
85
|
klass.destroy o
|
28
86
|
end
|
87
|
+
else
|
88
|
+
vs.each do |v|
|
89
|
+
objs = klass.where column_name => v
|
90
|
+
objs.each do |o|
|
91
|
+
klass.destroy o
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if klass.count.eql? 0
|
96
|
+
ActiveRecord::Schema.define do
|
97
|
+
drop_table klass.table_name
|
98
|
+
end
|
99
|
+
delete_from_master klass.table_name
|
100
|
+
Object.send 'remove_const', klass.to_s.to_sym
|
29
101
|
end
|
30
102
|
end
|
31
103
|
end
|
@@ -51,7 +123,7 @@ def modify_finite args
|
|
51
123
|
to_be_modified = to_be_modified.concat JSON.load open file_name
|
52
124
|
end
|
53
125
|
|
54
|
-
klass =
|
126
|
+
klass = get_finite_table table_name
|
55
127
|
ActiveRecord::Base.transaction do
|
56
128
|
yield to_be_modified, klass, column_name
|
57
129
|
end
|
data/spec/active_finite_spec.rb
CHANGED
@@ -1,97 +1,138 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
3
|
+
def reconnect
|
4
|
+
ActiveRecord::Base.establish_connection(
|
5
|
+
:adapter => 'sqlite3',
|
6
|
+
:database => ':memory:',
|
7
|
+
:pool => 5,
|
8
|
+
:timeout => 5000)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'get_finite_table' do
|
12
|
+
before :each do
|
13
|
+
reconnect
|
14
|
+
end
|
15
|
+
it 'returns a class that is a child of active record base' do
|
16
|
+
get_finite_table(:test).superclass.should eql ActiveRecord::Base
|
17
|
+
end
|
18
|
+
it 'brings a class into scope' do
|
19
|
+
get_finite_table :spaces
|
20
|
+
Object.const_defined?(:Space).should be true
|
18
21
|
end
|
22
|
+
it 'will not redefine a previously defined constant' do
|
23
|
+
Define = true
|
24
|
+
get_finite_table :defines
|
25
|
+
Define.should == true
|
26
|
+
end
|
27
|
+
it 'will redefine a previously defined constant with the force option' do
|
28
|
+
Anyway = true
|
29
|
+
get_finite_table :anyways, :force
|
30
|
+
Anyway.should_not == true
|
31
|
+
end
|
32
|
+
end
|
19
33
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
34
|
+
describe 'all_finite_tables' do
|
35
|
+
before :each do
|
36
|
+
reconnect
|
37
|
+
end
|
38
|
+
it 'returns all active record classes created by active_finite' do
|
39
|
+
add_finites in_table: :things, values: ['1']
|
40
|
+
add_finites in_table: :stuffs, values: ['s']
|
41
|
+
all_finite_tables.should == [Thing, Stuff]
|
42
|
+
end
|
43
|
+
it 'will no longer return a removed finite table' do
|
44
|
+
add_finites in_table: :things, values: ['1']
|
45
|
+
delete_finites in_table: :things, values: ['1']
|
46
|
+
all_finite_tables.should == []
|
47
|
+
end
|
48
|
+
end
|
29
49
|
|
30
|
-
|
31
|
-
|
32
|
-
|
50
|
+
describe 'as_class_name' do
|
51
|
+
before :each do
|
52
|
+
reconnect
|
53
|
+
end
|
54
|
+
it 'capitalizes its input' do
|
55
|
+
as_class_name(:as).should eql :A
|
56
|
+
end
|
57
|
+
it 'properly singularizes its input' do
|
58
|
+
as_class_name(:users).should eql :User
|
59
|
+
as_class_name(:foxes).should eql :Fox
|
60
|
+
as_class_name(:sheep).should eql :Sheep
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'add_finites' do
|
65
|
+
before :each do
|
66
|
+
reconnect
|
67
|
+
end
|
68
|
+
it 'adds finites as rows to the database' do
|
69
|
+
finites = ['red', 'blue', 'green']
|
70
|
+
add_finites in_table: :colors, values: finites
|
71
|
+
|
72
|
+
finites.each do |f|
|
73
|
+
Color.where(default_column_name => f).should_not nil
|
33
74
|
end
|
75
|
+
end
|
34
76
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
finites = ['mickey', 'donald', 'scrooge']
|
77
|
+
it 'creates the coresponding table if it doesn\`t exist' do
|
78
|
+
add_finites in_table: :tests, values: [1]
|
79
|
+
Object.const_defined?(:Test).should be true
|
80
|
+
end
|
42
81
|
|
43
|
-
|
44
|
-
|
45
|
-
|
82
|
+
it 'can use a different column name' do
|
83
|
+
finites = ['mickey', 'donald', 'scrooge']
|
84
|
+
add_finites in_table: :characters,
|
85
|
+
values: finites,
|
86
|
+
column_name: :column_name
|
46
87
|
|
47
|
-
|
48
|
-
|
49
|
-
end
|
88
|
+
finites.each do |f|
|
89
|
+
Color.where(:column_name => f).should_not nil
|
50
90
|
end
|
91
|
+
end
|
51
92
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
file_path = File.expand_path(File.dirname(__FILE__) + '/villans.json')
|
59
|
-
create_finite in_table: :villans,
|
60
|
-
from_file: file_path
|
93
|
+
it 'can load from a json file' do
|
94
|
+
file_path = File.expand_path(File.dirname(__FILE__) + '/villans.json')
|
95
|
+
add_finites in_table: :villans,
|
96
|
+
from_file: file_path
|
61
97
|
|
62
|
-
|
63
|
-
|
64
|
-
end
|
98
|
+
['scaramanga', 'no', 'janus'].each do |v|
|
99
|
+
Villan.where(default_column_name => v).should_not nil
|
65
100
|
end
|
101
|
+
end
|
66
102
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
begin
|
74
|
-
create_finite in_table: :wu_members, values: ['rza', 'gza', nil]
|
75
|
-
rescue
|
76
|
-
['rza', 'gza'].each do |w|
|
77
|
-
active_finite(:wu_members).where(default_column_name => w).should nil
|
78
|
-
end
|
103
|
+
it 'will fail atomically' do
|
104
|
+
begin
|
105
|
+
add_finites in_table: :wu_members, values: ['rza', 'gza', nil]
|
106
|
+
rescue
|
107
|
+
['rza', 'gza'].each do |w|
|
108
|
+
get_finite_table(:wu_members).where(default_column_name => w).should nil
|
79
109
|
end
|
80
110
|
end
|
81
111
|
end
|
112
|
+
end
|
82
113
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
t.string default_column_name, :null => false
|
88
|
-
end
|
114
|
+
describe 'delete_finies' do
|
115
|
+
before :each do
|
116
|
+
reconnect
|
117
|
+
end
|
89
118
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
119
|
+
it 'can delete previously added finites' do
|
120
|
+
add_finites in_table: :adjs, values: ['delete', 'drop']
|
121
|
+
delete_finites in_table: :adjs, values: ['delete']
|
122
|
+
Adj.where(default_column_name => 'delete').should nil
|
123
|
+
Adj.where(default_column_name => 'drop').should_not nil
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'will remove the table if there are no finites left' do
|
127
|
+
add_finites in_table: :deletes, values: ['delete']
|
128
|
+
delete_finites in_table: :deletes, values: ['delete']
|
129
|
+
Object.const_defined?(:Delete).should_not be true
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'can delete all values with the all option' do
|
133
|
+
add_finites in_table: :adjs, values: ['delete', 'drop']
|
134
|
+
delete_finites in_table: :adjs, values: :all
|
135
|
+
Object.const_defined?(:Adj).should_not be true
|
96
136
|
end
|
137
|
+
end
|
97
138
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: active_finite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- me
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-21 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -79,7 +79,7 @@ dependencies:
|
|
79
79
|
type: :development
|
80
80
|
prerelease: false
|
81
81
|
version_requirements: *id006
|
82
|
-
description:
|
82
|
+
description: longer description of your gem
|
83
83
|
email: me@stuffihavemade.com
|
84
84
|
executables: []
|
85
85
|
|
@@ -100,7 +100,7 @@ files:
|
|
100
100
|
- spec/spec_helper.rb
|
101
101
|
- spec/villans.json
|
102
102
|
has_rdoc: true
|
103
|
-
homepage: http://github.com/
|
103
|
+
homepage: http://github.com/r4pdevteam/active_finite
|
104
104
|
licenses:
|
105
105
|
- MIT
|
106
106
|
post_install_message:
|
@@ -113,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
113
113
|
requirements:
|
114
114
|
- - ">="
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
hash:
|
116
|
+
hash: 138921425
|
117
117
|
segments:
|
118
118
|
- 0
|
119
119
|
version: "0"
|
@@ -129,7 +129,7 @@ rubyforge_project:
|
|
129
129
|
rubygems_version: 1.5.0
|
130
130
|
signing_key:
|
131
131
|
specification_version: 3
|
132
|
-
summary:
|
132
|
+
summary: one-line summary of your gem
|
133
133
|
test_files:
|
134
134
|
- spec/active_finite_spec.rb
|
135
135
|
- spec/spec_helper.rb
|