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 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
- create_table :hellos do |t|
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
- drop_finite in_table: :hellos, values: ['oy', 'que tal', 'hi']
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 = active_finite :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
- By using the method active_finite, there is no need to define the model classes
39
- explicitly.
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 (i.e. when working with
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
- create_table :hellos do |t|
53
- t.string :custom, :null => false
54
- end
55
- create_finite in_table: :hellos,
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
- drop_finite in_table: :hellos, values: ['oy', 'que tal', 'hi']
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/stuffihavemade/active_finite"
16
+ gem.homepage = "http://github.com/r4pdevteam/active_finite"
17
17
  gem.license = "MIT"
18
- gem.summary = %Q{An ActiveRecord addon for enums, based on DRY and that enums
19
- should be database columns}
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.3
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 active_finite sym
8
- anon = Class.new ActiveRecord::Base
9
- Object.const_set(sym.to_s.singularize.capitalize, anon)
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 create_finite args
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 drop_finite args
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
- vs.each do |v|
25
- objs = klass.where column_name => v
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 = active_finite table_name
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
@@ -1,97 +1,138 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- ActiveRecord::Base.establish_connection(
4
- :adapter => 'sqlite3',
5
- :database => ':memory:',
6
- :pool => 5,
7
- :timeout => 5000)
8
-
9
- describe 'active_finite' do
10
- it 'returns a class that is a child of active record base' do
11
- active_finite(:test).superclass.should eql ActiveRecord::Base
12
- end
13
- it 'properly singularizes its classes' do
14
- active_finite(:users).should eql User
15
- active_finite(:foxes).should eql Fox
16
- active_finite(:sheep).should eql Sheep
17
- end
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
- describe 'create_finite' do
21
- it 'adds finites as rows to the database' do
22
- ActiveRecord::Schema.define do
23
- create_table :colors do |t|
24
- t.string default_column_name, :null => false
25
- end
26
- end
27
- finites = ['red', 'blue', 'green']
28
- create_finite in_table: :colors, values: finites
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
- finites.each do |f|
31
- Color.where(default_column_name => f).should_not nil
32
- end
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
- it 'can change the column name' do
36
- ActiveRecord::Schema.define do
37
- create_table :characters do |t|
38
- t.string :column_name, :null => false
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
- create_finite in_table: :characters,
44
- values: finites,
45
- column_name: :column_name
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
- finites.each do |f|
48
- Color.where(:column_name => f).should_not nil
49
- end
88
+ finites.each do |f|
89
+ Color.where(:column_name => f).should_not nil
50
90
  end
91
+ end
51
92
 
52
- it 'can load from a json file' do
53
- ActiveRecord::Schema.define do
54
- create_table :villans do |t|
55
- t.string default_column_name, :null => false
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
- ['scaramanga', 'no', 'janus'].each do |v|
63
- Villan.where(default_column_name => v).should_not nil
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
- it 'will fail atomically' do
68
- ActiveRecord::Schema.define do
69
- create_table :wu_members do |t|
70
- t.string default_column_name, :null => false
71
- end
72
- end
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
- describe 'drop_finite' do
84
- it 'can delete previously added finites' do
85
- ActiveRecord::Schema.define do
86
- create_table :adjs do |t|
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
- create_finite in_table: :adj, values: ['delete', 'drop']
91
- drop_finite in_table: :adj, values: ['delete']
92
- Adj.where(default_column_name => 'delete').should nil
93
- Adj.where(default_column_name => 'drop').should_not nil
94
- end
95
- end
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.3
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-12 00:00:00 -04:00
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: see README.rdoc
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/stuffihavemade/active_finite
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: -927353165
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: An ActiveRecord addon for enums, based on DRY and that enums should be database columns
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