activerecord_enum 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in activerecord_enum.gemspec
4
+ gemspec
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,10 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ desc 'Default: run unit tests.'
6
+ task :default => :spec
7
+
8
+ require "rspec/core/rake_task"
9
+ desc 'Run the test suite.'
10
+ RSpec::Core::RakeTask.new(:spec)
@@ -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,3 @@
1
+ module ActiverecordEnum
2
+ VERSION = "0.0.1"
3
+ 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.enum "color", :limit => ['red', 'gold'], :default => 'gold', :null => false
5
+ t.column "size", :enum, :limit => ['small', 'medium', 'large']
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :aircraft, :force => true do |t|
3
+ t.integer "id"
4
+ t.column "color", "enum('blue','red','yellow')", :default => 'red', :null => false
5
+ end
6
+ 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
@@ -0,0 +1,6 @@
1
+ ActiveRecord::Schema.define do
2
+ create_table :aircraft, :force => true do |t|
3
+ t.integer "id"
4
+ t.column "gadgets", "set('propeller','tail gun','gps')", :default => 'propeller,gps', :null => false
5
+ end
6
+ 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
@@ -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