activerecord_enum 0.0.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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +16 -0
- data/Rakefile +10 -0
- data/activerecord_enum.gemspec +27 -0
- data/lib/activerecord_enum/version.rb +3 -0
- data/lib/activerecord_enum.rb +89 -0
- data/spec/enum_spec.rb +48 -0
- data/spec/schema/enum_new.rb +7 -0
- data/spec/schema/enum_old.rb +6 -0
- data/spec/schema/set_new.rb +7 -0
- data/spec/schema/set_old.rb +6 -0
- data/spec/set_spec.rb +55 -0
- data/spec/spec_helper.rb +33 -0
- metadata +162 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# ActiveRecord Enum
|
|
2
|
+
|
|
3
|
+
Provides ActiveRecord support for the nonstandard `ENUM` and `SET` data types.
|
|
4
|
+
|
|
5
|
+
## Hypothetically asked questions
|
|
6
|
+
|
|
7
|
+
### Y U NO WORK?!
|
|
8
|
+
Sorry, it currently only works with Rails 3.0.x and the mysql2 adapter. I plan to support 3.1.x and other adapters at some point.
|
|
9
|
+
|
|
10
|
+
### Why doesn't it validate anything?
|
|
11
|
+
Right now it really only supports schema operations - attribute access is left untouched. I'll be working on that too at some point.
|
|
12
|
+
|
|
13
|
+
### Nonstandard SQL?! What's your problem, jerkweed?
|
|
14
|
+
This isn't a plugin everyone should use. There are a number of plugins to simulate enum behavior backed by standard datatypes. Personally, I like [https://github.com/nofxx/symbolize].
|
|
15
|
+
|
|
16
|
+
However, sometimes we can't or won't avoid working with these data types. When that happens, I got you covered.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "activerecord_enum/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "activerecord_enum"
|
|
7
|
+
s.version = ActiverecordEnum::VERSION
|
|
8
|
+
s.platform = Gem::Platform::RUBY
|
|
9
|
+
s.authors = ["Ian Young"]
|
|
10
|
+
s.email = ["ian.greenleaf+github@gmail.com"]
|
|
11
|
+
s.homepage = ""
|
|
12
|
+
s.summary = %q{Enum data types for ActiveRecord}
|
|
13
|
+
s.description = %q{Adds the ENUM data type natively to ActiveRecord.}
|
|
14
|
+
|
|
15
|
+
s.rubyforge_project = "activerecord_enum"
|
|
16
|
+
|
|
17
|
+
s.add_dependency "activerecord", "~> 3.0.9"
|
|
18
|
+
s.add_development_dependency "rake"
|
|
19
|
+
s.add_development_dependency "bundler"
|
|
20
|
+
s.add_development_dependency "mysql2", "~> 0.2.0"
|
|
21
|
+
s.add_development_dependency "rspec", "~> 2.6.0"
|
|
22
|
+
|
|
23
|
+
s.files = `git ls-files`.split("\n")
|
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
26
|
+
s.require_paths = ["lib"]
|
|
27
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'active_record'
|
|
2
|
+
require 'active_record/connection_adapters/mysql2_adapter'
|
|
3
|
+
require 'active_record/connection_adapters/abstract/schema_definitions.rb'
|
|
4
|
+
|
|
5
|
+
module ActiverecordEnum
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module ActiveRecord
|
|
9
|
+
module ConnectionAdapters
|
|
10
|
+
class Mysql2Adapter < AbstractAdapter
|
|
11
|
+
def native_database_types_with_enum
|
|
12
|
+
native_database_types_without_enum.merge( :enum => { :name => "enum" }, :set => { :name => "set" } )
|
|
13
|
+
end
|
|
14
|
+
alias_method :native_database_types_without_enum, :native_database_types
|
|
15
|
+
alias_method :native_database_types, :native_database_types_with_enum
|
|
16
|
+
|
|
17
|
+
def type_to_sql_with_enum type, limit=nil, *args
|
|
18
|
+
if type.to_s == "enum" || type.to_s == "set"
|
|
19
|
+
"#{type}(#{quoted_comma_list limit})"
|
|
20
|
+
else
|
|
21
|
+
type_to_sql_without_enum type, limit, *args
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
alias_method :type_to_sql_without_enum, :type_to_sql
|
|
25
|
+
alias_method :type_to_sql, :type_to_sql_with_enum
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
def quoted_comma_list list
|
|
29
|
+
list.to_a.map{|n| "'#{n}'"}.join(",")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
module ActiveRecord
|
|
36
|
+
module ConnectionAdapters
|
|
37
|
+
class Column
|
|
38
|
+
def initialize_with_enum name, default, sql_type=nil, *args
|
|
39
|
+
initialize_without_enum name, default, sql_type, *args
|
|
40
|
+
@type = simplified_type_with_enum sql_type
|
|
41
|
+
@limit = extract_limit_with_enum sql_type
|
|
42
|
+
@default = extract_default_with_enum default
|
|
43
|
+
end
|
|
44
|
+
alias_method :initialize_without_enum, :initialize
|
|
45
|
+
alias_method :initialize, :initialize_with_enum
|
|
46
|
+
|
|
47
|
+
def simplified_type_with_enum field_type
|
|
48
|
+
if field_type =~ /enum|set/i
|
|
49
|
+
$&.to_sym
|
|
50
|
+
else
|
|
51
|
+
simplified_type field_type
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def extract_limit_with_enum field_type
|
|
56
|
+
if field_type =~ /(?:enum|set)\(([^)]+)\)/i
|
|
57
|
+
$1.scan( /'([^']*)'/ ).flatten
|
|
58
|
+
else
|
|
59
|
+
extract_limit field_type
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def extract_default_with_enum default
|
|
64
|
+
if type == :set
|
|
65
|
+
default.split "," if default.present?
|
|
66
|
+
else
|
|
67
|
+
extract_default default
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
module ActiveRecord
|
|
74
|
+
module ConnectionAdapters
|
|
75
|
+
class TableDefinition
|
|
76
|
+
def enum *args
|
|
77
|
+
options = args.extract_options!
|
|
78
|
+
column_names = args
|
|
79
|
+
column_names.each { |name| column(name, :enum, options) }
|
|
80
|
+
end
|
|
81
|
+
def set *args
|
|
82
|
+
options = args.extract_options!
|
|
83
|
+
options[:default] = options[:default].join "," if options[:default].present?
|
|
84
|
+
column_names = args
|
|
85
|
+
column_names.each { |name| column(name, :set, options) }
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/spec/enum_spec.rb
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "ENUM datatype" do
|
|
4
|
+
|
|
5
|
+
describe "schema dump" do
|
|
6
|
+
before { load_schema "enum_old" }
|
|
7
|
+
subject { dumped_schema }
|
|
8
|
+
|
|
9
|
+
it "dumps native format" do
|
|
10
|
+
subject.should match %r{t\.enum\s+"color",\s+:limit => \["blue", "red", "yellow"\]}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "dumps default option" do
|
|
14
|
+
subject.should match %r{t\.enum\s+"color",.+:default => "red"}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "dumps null option" do
|
|
18
|
+
subject.should match %r{t\.enum\s+"color",.+:null => false$}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "schema loading" do
|
|
23
|
+
before { load_schema "enum_new" }
|
|
24
|
+
subject { ActiveRecord::Base.connection.select_one "SHOW FIELDS FROM balloons WHERE Field='color'" }
|
|
25
|
+
|
|
26
|
+
it "loads native format" do
|
|
27
|
+
subject[ "Type" ].should == "enum('red','gold')"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "loads default option" do
|
|
31
|
+
subject[ "Default" ].should == "gold"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "loads null option" do
|
|
35
|
+
subject[ "Null" ].should == "NO"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "loads native column format" do
|
|
39
|
+
subject = ActiveRecord::Base.connection.select_one "SHOW FIELDS FROM balloons WHERE Field='size'"
|
|
40
|
+
subject[ "Type" ].should == "enum('small','medium','large')"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "validation" do
|
|
45
|
+
it "validates assigned value is member of the list"
|
|
46
|
+
it "allows nil when null enabled"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ActiveRecord::Schema.define do
|
|
2
|
+
create_table :balloons, :force => true do |t|
|
|
3
|
+
t.integer "id"
|
|
4
|
+
t.set "ribbons", :limit => ['red', 'green', 'gold'], :default => ['gold', 'green'], :null => false
|
|
5
|
+
t.column "gasses", :set, :limit => ['helium', 'hydrogen']
|
|
6
|
+
end
|
|
7
|
+
end
|
data/spec/set_spec.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "SET datatype" do
|
|
4
|
+
|
|
5
|
+
describe "schema dump" do
|
|
6
|
+
before { load_schema "set_old" }
|
|
7
|
+
subject { dumped_schema }
|
|
8
|
+
|
|
9
|
+
it "dumps native format" do
|
|
10
|
+
subject.should match %r{t\.set\s+"gadgets",\s+:limit => \["propeller", "tail gun", "gps"\]}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "dumps default option" do
|
|
14
|
+
subject.should match %r{t\.set\s+"gadgets",.+:default => \["propeller", "gps"\]}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "dumps null option" do
|
|
18
|
+
subject.should match %r{t\.set\s+"gadgets",.+:null => false$}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "schema loading" do
|
|
23
|
+
before { load_schema "set_new" }
|
|
24
|
+
subject { ActiveRecord::Base.connection.select_one "SHOW FIELDS FROM balloons WHERE Field='ribbons'" }
|
|
25
|
+
|
|
26
|
+
it "loads native format" do
|
|
27
|
+
subject[ "Type" ].should == "set('red','green','gold')"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "loads default option" do
|
|
31
|
+
subject[ "Default" ].should == "green,gold"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "loads null option" do
|
|
35
|
+
subject[ "Null" ].should == "NO"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "loads native column format" do
|
|
39
|
+
subject = ActiveRecord::Base.connection.select_one "SHOW FIELDS FROM balloons WHERE Field='gasses'"
|
|
40
|
+
subject[ "Type" ].should == "set('helium','hydrogen')"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "assignment" do
|
|
45
|
+
it "accepts single value"
|
|
46
|
+
it "accepts array of values"
|
|
47
|
+
it "accepts comma-separated values"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "validation" do
|
|
51
|
+
it "validates assigned values are members of the list"
|
|
52
|
+
it "allows nil when null enabled"
|
|
53
|
+
it "allows empty list"
|
|
54
|
+
end
|
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
require 'activerecord_enum'
|
|
3
|
+
|
|
4
|
+
def load_schema filename
|
|
5
|
+
# silence verbose schema loading
|
|
6
|
+
original_stdout = $stdout
|
|
7
|
+
$stdout = StringIO.new
|
|
8
|
+
|
|
9
|
+
root = File.expand_path(File.dirname(__FILE__))
|
|
10
|
+
load root + "/schema/#{filename}.rb"
|
|
11
|
+
|
|
12
|
+
ensure
|
|
13
|
+
$stdout = original_stdout
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def dumped_schema
|
|
17
|
+
stream = StringIO.new
|
|
18
|
+
ActiveRecord::SchemaDumper.ignore_tables = []
|
|
19
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
20
|
+
stream.string.lines.select {|l| /^\s*#/.match(l).nil? }.join
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
ActiveRecord::Base.configurations = {
|
|
24
|
+
"enum_test" => {
|
|
25
|
+
:adapter => "mysql2",
|
|
26
|
+
:host => "localhost",
|
|
27
|
+
:username => "enum_test",
|
|
28
|
+
:password => "enum_test",
|
|
29
|
+
:database => "enum_test",
|
|
30
|
+
:socket => "/tmp/mysql.sock"
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
ActiveRecord::Base.establish_connection "enum_test"
|
metadata
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: activerecord_enum
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
hash: 29
|
|
5
|
+
prerelease:
|
|
6
|
+
segments:
|
|
7
|
+
- 0
|
|
8
|
+
- 0
|
|
9
|
+
- 1
|
|
10
|
+
version: 0.0.1
|
|
11
|
+
platform: ruby
|
|
12
|
+
authors:
|
|
13
|
+
- Ian Young
|
|
14
|
+
autorequire:
|
|
15
|
+
bindir: bin
|
|
16
|
+
cert_chain: []
|
|
17
|
+
|
|
18
|
+
date: 2011-08-19 00:00:00 -07:00
|
|
19
|
+
default_executable:
|
|
20
|
+
dependencies:
|
|
21
|
+
- !ruby/object:Gem::Dependency
|
|
22
|
+
name: activerecord
|
|
23
|
+
prerelease: false
|
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ~>
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
hash: 21
|
|
30
|
+
segments:
|
|
31
|
+
- 3
|
|
32
|
+
- 0
|
|
33
|
+
- 9
|
|
34
|
+
version: 3.0.9
|
|
35
|
+
type: :runtime
|
|
36
|
+
version_requirements: *id001
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: rake
|
|
39
|
+
prerelease: false
|
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
hash: 3
|
|
46
|
+
segments:
|
|
47
|
+
- 0
|
|
48
|
+
version: "0"
|
|
49
|
+
type: :development
|
|
50
|
+
version_requirements: *id002
|
|
51
|
+
- !ruby/object:Gem::Dependency
|
|
52
|
+
name: bundler
|
|
53
|
+
prerelease: false
|
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
55
|
+
none: false
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
hash: 3
|
|
60
|
+
segments:
|
|
61
|
+
- 0
|
|
62
|
+
version: "0"
|
|
63
|
+
type: :development
|
|
64
|
+
version_requirements: *id003
|
|
65
|
+
- !ruby/object:Gem::Dependency
|
|
66
|
+
name: mysql2
|
|
67
|
+
prerelease: false
|
|
68
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
69
|
+
none: false
|
|
70
|
+
requirements:
|
|
71
|
+
- - ~>
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
hash: 23
|
|
74
|
+
segments:
|
|
75
|
+
- 0
|
|
76
|
+
- 2
|
|
77
|
+
- 0
|
|
78
|
+
version: 0.2.0
|
|
79
|
+
type: :development
|
|
80
|
+
version_requirements: *id004
|
|
81
|
+
- !ruby/object:Gem::Dependency
|
|
82
|
+
name: rspec
|
|
83
|
+
prerelease: false
|
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
|
85
|
+
none: false
|
|
86
|
+
requirements:
|
|
87
|
+
- - ~>
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
hash: 23
|
|
90
|
+
segments:
|
|
91
|
+
- 2
|
|
92
|
+
- 6
|
|
93
|
+
- 0
|
|
94
|
+
version: 2.6.0
|
|
95
|
+
type: :development
|
|
96
|
+
version_requirements: *id005
|
|
97
|
+
description: Adds the ENUM data type natively to ActiveRecord.
|
|
98
|
+
email:
|
|
99
|
+
- ian.greenleaf+github@gmail.com
|
|
100
|
+
executables: []
|
|
101
|
+
|
|
102
|
+
extensions: []
|
|
103
|
+
|
|
104
|
+
extra_rdoc_files: []
|
|
105
|
+
|
|
106
|
+
files:
|
|
107
|
+
- .gitignore
|
|
108
|
+
- Gemfile
|
|
109
|
+
- README.markdown
|
|
110
|
+
- Rakefile
|
|
111
|
+
- activerecord_enum.gemspec
|
|
112
|
+
- lib/activerecord_enum.rb
|
|
113
|
+
- lib/activerecord_enum/version.rb
|
|
114
|
+
- spec/enum_spec.rb
|
|
115
|
+
- spec/schema/enum_new.rb
|
|
116
|
+
- spec/schema/enum_old.rb
|
|
117
|
+
- spec/schema/set_new.rb
|
|
118
|
+
- spec/schema/set_old.rb
|
|
119
|
+
- spec/set_spec.rb
|
|
120
|
+
- spec/spec_helper.rb
|
|
121
|
+
has_rdoc: true
|
|
122
|
+
homepage: ""
|
|
123
|
+
licenses: []
|
|
124
|
+
|
|
125
|
+
post_install_message:
|
|
126
|
+
rdoc_options: []
|
|
127
|
+
|
|
128
|
+
require_paths:
|
|
129
|
+
- lib
|
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
|
+
none: false
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
hash: 3
|
|
136
|
+
segments:
|
|
137
|
+
- 0
|
|
138
|
+
version: "0"
|
|
139
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
|
+
none: false
|
|
141
|
+
requirements:
|
|
142
|
+
- - ">="
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
hash: 3
|
|
145
|
+
segments:
|
|
146
|
+
- 0
|
|
147
|
+
version: "0"
|
|
148
|
+
requirements: []
|
|
149
|
+
|
|
150
|
+
rubyforge_project: activerecord_enum
|
|
151
|
+
rubygems_version: 1.6.2
|
|
152
|
+
signing_key:
|
|
153
|
+
specification_version: 3
|
|
154
|
+
summary: Enum data types for ActiveRecord
|
|
155
|
+
test_files:
|
|
156
|
+
- spec/enum_spec.rb
|
|
157
|
+
- spec/schema/enum_new.rb
|
|
158
|
+
- spec/schema/enum_old.rb
|
|
159
|
+
- spec/schema/set_new.rb
|
|
160
|
+
- spec/schema/set_old.rb
|
|
161
|
+
- spec/set_spec.rb
|
|
162
|
+
- spec/spec_helper.rb
|