From a08246f3db804eac1807ec15e59e0ebdc2ec5c90 Mon Sep 17 00:00:00 2001 From: Aaron Weiner Date: Wed, 26 Jun 2013 21:22:22 -0400 Subject: [PATCH 01/34] Avoid typecasting unexpected strings to symbols to prevent DoS due to memory leak --- lib/enum/enum_adapter.rb | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index ede5cb6..9da7531 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -31,7 +31,7 @@ def klass # Convert to a symbol. def type_cast(value) if type == :enum - self.class.value_to_symbol(value) + value.is_a?(Symbol) ? value : string_to_valid_enum(value) else __type_cast_enum(value) end @@ -41,26 +41,12 @@ def type_cast(value) # Code to convert to a symbol. def type_cast_code(var_name) if type == :enum - "#{self.class.name}.value_to_symbol(#{var_name})" + "#{var_name}.is_a?(Symbol) ? #{var_name} : #{string_to_valid_enum_hash_code}[#{var_name}]" else __type_cast_code_enum(var_name) end end - class << self - # Safely convert the value to a symbol. - def value_to_symbol(value) - case value - when Symbol - value - when String - value.empty? ? nil : value.intern - else - nil - end - end - end - private alias __simplified_type_enum simplified_type # The enum simple type. @@ -71,7 +57,7 @@ def simplified_type(field_type) __simplified_type_enum(field_type) end end - + alias __extract_limit_enum extract_limit def extract_limit(sql_type) if sql_type =~ /^enum/i @@ -81,5 +67,17 @@ def extract_limit(sql_type) end end + def string_to_valid_enum(str) + @valid_strings_filter ||= Hash[enum_valid_string_assoc] + @valid_strings_filter[str] + end + + def string_to_valid_enum_hash_code + Hash[limit.map(&:to_s).zip(limit)].to_s + end + + def enum_valid_string_assoc + limit.map(&:to_s).zip(limit) + end end From be82807a2ef01061a227a120e940b918971a3a07 Mon Sep 17 00:00:00 2001 From: Aaron Weiner Date: Wed, 17 Jul 2013 17:35:07 -0400 Subject: [PATCH 02/34] Slight code cleanup --- lib/enum/enum_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index 9da7531..cea10e5 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -73,7 +73,7 @@ def string_to_valid_enum(str) end def string_to_valid_enum_hash_code - Hash[limit.map(&:to_s).zip(limit)].to_s + Hash[enum_valid_string_assoc].to_s end def enum_valid_string_assoc From 3ca204eaa7092a9dad9b178fd629f20ecb321300 Mon Sep 17 00:00:00 2001 From: Aaron Weiner Date: Tue, 6 Aug 2013 11:31:29 -0400 Subject: [PATCH 03/34] Assume ownership, update README --- README.txt | 17 +++++++++++------ enum_column.gemspec | 23 ++++++++--------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/README.txt b/README.txt index c55cd5a..243df2d 100644 --- a/README.txt +++ b/README.txt @@ -2,7 +2,7 @@ Overview This gem is an extension to ActiveRecord which enables native support of enumerations in the database schema using the ENUM type in MySQL. Currently only MySQL is implemented. - Tested with Rails 3, for Rails 2 you should better use enum-column plugin (http://rubyforge.org/projects/enum-column/) + Tested with Rails 3. For Rails 2 the enum-column plugin serves the same functionality but is vulnerable to DOS attacks with typical use. Works with Scaffolding. Supported adapters: @@ -12,9 +12,9 @@ Overview How to use it. -In you Gemfile: +In your Gemfile: - gem 'enum_column3' + gem 'enum_column_strict' In your schema: @@ -43,13 +43,18 @@ You can always use the column reflection to get the list of possible values from Enumeration.columns_hash['color'].limit or @enumeration.column_for_attribute(:color).limit - + Will yield: [:red, :blue, :green, :yellow] - + +If you assign a string to the column, it will be converted to a symbol if it's valid, and nil otherwise, +so if this is the only way you populate color, validates_presence_of may be the only validation you need. + + Enumeration.new(:color => "red") (color will be :red) + Enumeration.new(:color => "infrared") (color will be nil) In views: - You can use enum_select helper to generate input for enumerated attribute as: + You can use the enum_select helper to generate input for enumerated attributes: <%= enum_select(@enumeration, 'severity')%> or diff --git a/enum_column.gemspec b/enum_column.gemspec index ec33446..b134c1c 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -1,7 +1,8 @@ Gem::Specification.new do |s| - s.name = %q{enum_column3} - s.version = "0.1.4" - s.authors = ['Nick Pohodnya'] + s.name = 'enum_column_strict' + s.version = '0.0.1' + s.authors = ['Nick Pohodnya', 'Aaron Weiner'] + s.email = 'aweiner@mdsol.com' s.files = [ "README.txt", @@ -17,9 +18,11 @@ Gem::Specification.new do |s| "lib/enum/schema_statements.rb", "lib/enum/validations.rb" ] - s.homepage = %q{http://github.com/electronick/enum_column} + s.homepage = %q{http://github.com/mdsol/enum_column} s.require_paths = ["lib"] - s.summary = %q{Enable enum type for MySQL db.} + s.summary = %q{Enum type for MySQL db, without the symbol DOS vulnerability.} + s.description = %q{Allows your rails models and views to take advantage of MySQL's native enum type. +Forked from electronick's gem to address http://osvdb.org/show/osvdb/94679} s.test_files = [ "test/test_helper.rb", "test/db/schema.rb", @@ -29,15 +32,5 @@ Gem::Specification.new do |s| "test/enum_mysql_test.rb" ] - if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION - s.specification_version = 3 - - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - else - end - else - end - end From cbca08a122191a83e14b11349bdf77ba38cef6d3 Mon Sep 17 00:00:00 2001 From: Aaron Weiner Date: Thu, 8 Aug 2013 14:00:06 -0400 Subject: [PATCH 04/34] Rename initializer file to match new gem name --- enum_column.gemspec | 4 ++-- lib/{enum_column3.rb => enum_column_strict.rb} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename lib/{enum_column3.rb => enum_column_strict.rb} (100%) diff --git a/enum_column.gemspec b/enum_column.gemspec index b134c1c..9c14381 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'enum_column_strict' - s.version = '0.0.1' + s.version = '0.0.2' s.authors = ['Nick Pohodnya', 'Aaron Weiner'] s.email = 'aweiner@mdsol.com' @@ -9,7 +9,7 @@ Gem::Specification.new do |s| "LICENSE", "init.rb", "lib/enum_column.rb", - "lib/enum_column3.rb", + "lib/enum_column_strict.rb", "lib/enum/active_record_helper.rb", "lib/enum/enum_adapter.rb", "lib/enum/mysql_adapter.rb", diff --git a/lib/enum_column3.rb b/lib/enum_column_strict.rb similarity index 100% rename from lib/enum_column3.rb rename to lib/enum_column_strict.rb From 8ffa96ea4a644185799af53e5b8be5de4b218b5e Mon Sep 17 00:00:00 2001 From: Adam Godel Date: Wed, 1 Jul 2015 18:11:28 -0400 Subject: [PATCH 05/34] makes compatible with Mysql2SpatialAdapter --- lib/enum/mysql_adapter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 7ce64d5..f8fb2ae 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -1,5 +1,7 @@ adapter_class = if defined? ActiveRecord::ConnectionAdapters::MySQLJdbcConnection ActiveRecord::ConnectionAdapters::MySQLJdbcConnection +elsif defined? ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter + ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::Mysql2Adapter elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter @@ -7,7 +9,7 @@ end adapter_class.module_eval do - alias __native_database_types_enum native_database_types + alias __native_database_types_enum native_database_types if defined? native_database_types def native_database_types #:nodoc types = __native_database_types_enum From 01be1420e2e2f204f03af62baa7b57f1046f2383 Mon Sep 17 00:00:00 2001 From: Adam Godel Date: Thu, 2 Jul 2015 09:32:24 -0400 Subject: [PATCH 06/34] makes gem compatible with mysql2spatial adapter --- lib/enum/mysql_adapter.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index f8fb2ae..5fc9d3e 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -1,7 +1,7 @@ adapter_class = if defined? ActiveRecord::ConnectionAdapters::MySQLJdbcConnection ActiveRecord::ConnectionAdapters::MySQLJdbcConnection elsif defined? ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter - ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter + ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter::MainAdapter elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::Mysql2Adapter elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter @@ -9,11 +9,12 @@ end adapter_class.module_eval do - alias __native_database_types_enum native_database_types if defined? native_database_types + alias __native_database_types_enum native_database_types #if defined? native_database_types def native_database_types #:nodoc types = __native_database_types_enum types[:enum] = { :name => "enum" } types end + end \ No newline at end of file From 3ae91844f611c9128b7c5543de0fb4ce606de852 Mon Sep 17 00:00:00 2001 From: Adam Godel Date: Thu, 2 Jul 2015 09:55:59 -0400 Subject: [PATCH 07/34] removes commented code --- lib/enum/mysql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 5fc9d3e..2f8cfe7 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -9,7 +9,7 @@ end adapter_class.module_eval do - alias __native_database_types_enum native_database_types #if defined? native_database_types + alias __native_database_types_enum native_database_types def native_database_types #:nodoc types = __native_database_types_enum From b59ec1d24220801f4e84993488ffb656a54e70c6 Mon Sep 17 00:00:00 2001 From: Stan Cheng Date: Tue, 18 Aug 2015 10:14:44 -0400 Subject: [PATCH 08/34] V0.1.5: Move alias statements to after method definitions --- enum_column.gemspec | 6 +++--- lib/enum/enum_adapter.rb | 11 ++++++----- lib/enum/mysql_adapter.rb | 3 +-- lib/enum/quoting.rb | 3 ++- lib/enum/schema_statements.rb | 5 +++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 9c14381..0922d9c 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| - s.name = 'enum_column_strict' - s.version = '0.0.2' - s.authors = ['Nick Pohodnya', 'Aaron Weiner'] + s.name = 'enum_column3' + s.version = '0.1.5' + s.authors = ['Jewlr', 'Nick Pohodnya', 'Aaron Weiner'] s.email = 'aweiner@mdsol.com' s.files = [ diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index cea10e5..862077a 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -17,7 +17,6 @@ column_class.module_eval do - alias __klass_enum klass # The class for enum is Symbol. def klass if type == :enum @@ -26,8 +25,8 @@ def klass __klass_enum end end + alias __klass_enum klass - alias __type_cast_enum type_cast # Convert to a symbol. def type_cast(value) if type == :enum @@ -36,8 +35,8 @@ def type_cast(value) __type_cast_enum(value) end end + alias __type_cast_enum type_cast - alias __type_cast_code_enum type_cast_code # Code to convert to a symbol. def type_cast_code(var_name) if type == :enum @@ -46,9 +45,10 @@ def type_cast_code(var_name) __type_cast_code_enum(var_name) end end + alias __type_cast_code_enum type_cast_code private - alias __simplified_type_enum simplified_type + # The enum simple type. def simplified_type(field_type) if field_type =~ /enum/i @@ -57,8 +57,8 @@ def simplified_type(field_type) __simplified_type_enum(field_type) end end + alias __simplified_type_enum simplified_type - alias __extract_limit_enum extract_limit def extract_limit(sql_type) if sql_type =~ /^enum/i sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } @@ -66,6 +66,7 @@ def extract_limit(sql_type) __extract_limit_enum(sql_type) end end + alias __extract_limit_enum extract_limit def string_to_valid_enum(str) @valid_strings_filter ||= Hash[enum_valid_string_assoc] diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 2f8cfe7..8c93ee3 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -9,12 +9,11 @@ end adapter_class.module_eval do - alias __native_database_types_enum native_database_types def native_database_types #:nodoc types = __native_database_types_enum types[:enum] = { :name => "enum" } types end - + alias __native_database_types_enum native_database_types end \ No newline at end of file diff --git a/lib/enum/quoting.rb b/lib/enum/quoting.rb index 637ac40..2a7544c 100644 --- a/lib/enum/quoting.rb +++ b/lib/enum/quoting.rb @@ -1,7 +1,6 @@ module ActiveRecord module ConnectionAdapters # :nodoc: module Quoting - alias __quote_enum quote # Quote a symbol as a normal string. This will support quoting of # enumerated values. @@ -12,6 +11,8 @@ def quote(value, column = nil) ActiveRecord::Base.send(:quote_bound_value, value.to_s) end end + + alias __quote_enum quote end end end diff --git a/lib/enum/schema_statements.rb b/lib/enum/schema_statements.rb index 6895bd8..2436cd0 100644 --- a/lib/enum/schema_statements.rb +++ b/lib/enum/schema_statements.rb @@ -1,12 +1,11 @@ module ActiveRecord module ConnectionAdapters # :nodoc: module SchemaStatements - alias __type_to_sql_enum type_to_sql # Add enumeration support for schema statement creation. This # will have to be adapted for every adapter if the type requires # anything by a list of allowed values. The overrides the standard - # type_to_sql method and chains back to the default. This could + # type_to_sql method and chains back to the default. This could # be done on a per adapter basis, but is generalized here. # # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] @@ -22,6 +21,8 @@ def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: __type_to_sql_enum(type, limit, precision, scale) end end + + alias __type_to_sql_enum type_to_sql end end end From ec80e81f7db3f4318353ca1ca36bf372a8b16e98 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Wed, 19 Aug 2015 12:56:09 -0400 Subject: [PATCH 09/34] Revert alias lines being moved --- lib/enum/enum_adapter.rb | 10 +++++----- lib/enum/mysql_adapter.rb | 4 ++-- lib/enum/quoting.rb | 2 +- lib/enum/schema_statements.rb | 3 +-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index 862077a..e9ac04e 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -18,6 +18,7 @@ column_class.module_eval do # The class for enum is Symbol. + alias __klass_enum klass def klass if type == :enum Symbol @@ -25,9 +26,9 @@ def klass __klass_enum end end - alias __klass_enum klass # Convert to a symbol. + alias __type_cast_enum type_cast def type_cast(value) if type == :enum value.is_a?(Symbol) ? value : string_to_valid_enum(value) @@ -35,9 +36,9 @@ def type_cast(value) __type_cast_enum(value) end end - alias __type_cast_enum type_cast # Code to convert to a symbol. + alias __type_cast_code_enum type_cast_code def type_cast_code(var_name) if type == :enum "#{var_name}.is_a?(Symbol) ? #{var_name} : #{string_to_valid_enum_hash_code}[#{var_name}]" @@ -45,11 +46,11 @@ def type_cast_code(var_name) __type_cast_code_enum(var_name) end end - alias __type_cast_code_enum type_cast_code private # The enum simple type. + alias __simplified_type_enum simplified_type def simplified_type(field_type) if field_type =~ /enum/i :enum @@ -57,8 +58,8 @@ def simplified_type(field_type) __simplified_type_enum(field_type) end end - alias __simplified_type_enum simplified_type + alias __extract_limit_enum extract_limit def extract_limit(sql_type) if sql_type =~ /^enum/i sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } @@ -66,7 +67,6 @@ def extract_limit(sql_type) __extract_limit_enum(sql_type) end end - alias __extract_limit_enum extract_limit def string_to_valid_enum(str) @valid_strings_filter ||= Hash[enum_valid_string_assoc] diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 8c93ee3..59ccafa 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -10,10 +10,10 @@ adapter_class.module_eval do + alias __native_database_types_enum native_database_types def native_database_types #:nodoc types = __native_database_types_enum types[:enum] = { :name => "enum" } types end - alias __native_database_types_enum native_database_types -end \ No newline at end of file +end diff --git a/lib/enum/quoting.rb b/lib/enum/quoting.rb index 2a7544c..842497f 100644 --- a/lib/enum/quoting.rb +++ b/lib/enum/quoting.rb @@ -4,6 +4,7 @@ module Quoting # Quote a symbol as a normal string. This will support quoting of # enumerated values. + alias __quote_enum quote def quote(value, column = nil) if !value.is_a? Symbol __quote_enum(value, column) @@ -12,7 +13,6 @@ def quote(value, column = nil) end end - alias __quote_enum quote end end end diff --git a/lib/enum/schema_statements.rb b/lib/enum/schema_statements.rb index 2436cd0..3e436a8 100644 --- a/lib/enum/schema_statements.rb +++ b/lib/enum/schema_statements.rb @@ -9,6 +9,7 @@ module SchemaStatements # be done on a per adapter basis, but is generalized here. # # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] + alias __type_to_sql_enum type_to_sql def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: if type == :enum native = native_database_types[type] @@ -21,8 +22,6 @@ def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: __type_to_sql_enum(type, limit, precision, scale) end end - - alias __type_to_sql_enum type_to_sql end end end From a760013fe404143adca570a3aa51b2c2fa61460b Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 10:51:16 -0400 Subject: [PATCH 10/34] Fixes and compatability with Rails 4.2 --- README.txt | 17 ++-- enum_column.gemspec | 45 +++------ lib/enum/enum_adapter.rb | 91 +++---------------- lib/enum/enum_column_adapter.rb | 81 +++++++++++++++++ lib/enum/enum_type.rb | 23 +++++ lib/enum/mysql_adapter.rb | 6 +- lib/enum/quoting.rb | 3 +- lib/enum/schema_statements.rb | 4 +- lib/enum_column.rb | 4 +- ...{enum_column_strict.rb => enum_column3.rb} | 0 10 files changed, 146 insertions(+), 128 deletions(-) create mode 100644 lib/enum/enum_column_adapter.rb create mode 100644 lib/enum/enum_type.rb rename lib/{enum_column_strict.rb => enum_column3.rb} (100%) diff --git a/README.txt b/README.txt index 243df2d..c55cd5a 100644 --- a/README.txt +++ b/README.txt @@ -2,7 +2,7 @@ Overview This gem is an extension to ActiveRecord which enables native support of enumerations in the database schema using the ENUM type in MySQL. Currently only MySQL is implemented. - Tested with Rails 3. For Rails 2 the enum-column plugin serves the same functionality but is vulnerable to DOS attacks with typical use. + Tested with Rails 3, for Rails 2 you should better use enum-column plugin (http://rubyforge.org/projects/enum-column/) Works with Scaffolding. Supported adapters: @@ -12,9 +12,9 @@ Overview How to use it. -In your Gemfile: +In you Gemfile: - gem 'enum_column_strict' + gem 'enum_column3' In your schema: @@ -43,18 +43,13 @@ You can always use the column reflection to get the list of possible values from Enumeration.columns_hash['color'].limit or @enumeration.column_for_attribute(:color).limit - + Will yield: [:red, :blue, :green, :yellow] - -If you assign a string to the column, it will be converted to a symbol if it's valid, and nil otherwise, -so if this is the only way you populate color, validates_presence_of may be the only validation you need. - - Enumeration.new(:color => "red") (color will be :red) - Enumeration.new(:color => "infrared") (color will be nil) + In views: - You can use the enum_select helper to generate input for enumerated attributes: + You can use enum_select helper to generate input for enumerated attribute as: <%= enum_select(@enumeration, 'severity')%> or diff --git a/enum_column.gemspec b/enum_column.gemspec index 0922d9c..cc85de6 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -1,36 +1,17 @@ +# -*- encoding: utf-8 -*- +# stub: enum_column3 0.1.4 ruby lib + Gem::Specification.new do |s| - s.name = 'enum_column3' - s.version = '0.1.5' - s.authors = ['Jewlr', 'Nick Pohodnya', 'Aaron Weiner'] - s.email = 'aweiner@mdsol.com' + s.name = "enum_column3" + s.version = "0.1.4" - s.files = [ - "README.txt", - "LICENSE", - "init.rb", - "lib/enum_column.rb", - "lib/enum_column_strict.rb", - "lib/enum/active_record_helper.rb", - "lib/enum/enum_adapter.rb", - "lib/enum/mysql_adapter.rb", - "lib/enum/quoting.rb", - "lib/enum/schema_definitions.rb", - "lib/enum/schema_statements.rb", - "lib/enum/validations.rb" - ] - s.homepage = %q{http://github.com/mdsol/enum_column} + s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] - s.summary = %q{Enum type for MySQL db, without the symbol DOS vulnerability.} - s.description = %q{Allows your rails models and views to take advantage of MySQL's native enum type. -Forked from electronick's gem to address http://osvdb.org/show/osvdb/94679} - s.test_files = [ - "test/test_helper.rb", - "test/db/schema.rb", - "test/fixtures/enumeration.rb", - "test/fixtures/enum_controller.rb", - "test/enum_controller_test.rb", - "test/enum_mysql_test.rb" - ] - + s.authors = ["Nick Pohodnya"] + s.date = "2015-08-19" + s.files = ["LICENSE", "README.txt", "init.rb", "lib/enum/active_record_helper.rb", "lib/enum/enum_adapter.rb", "lib/enum/mysql_adapter.rb", "lib/enum/quoting.rb", "lib/enum/schema_definitions.rb", "lib/enum/schema_statements.rb", "lib/enum/validations.rb", "lib/enum_column.rb", "lib/enum_column3.rb", "test/db/schema.rb", "test/enum_controller_test.rb", "test/enum_mysql_test.rb", "test/fixtures/enum_controller.rb", "test/fixtures/enumeration.rb", "test/test_helper.rb"] + s.homepage = "http://github.com/electronick/enum_column" + s.rubygems_version = "2.4.8" + s.summary = "Enable enum type for MySQL db." + s.test_files = ["test/test_helper.rb", "test/db/schema.rb", "test/fixtures/enumeration.rb", "test/fixtures/enum_controller.rb", "test/enum_controller_test.rb", "test/enum_mysql_test.rb"] end - diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index e9ac04e..c50e624 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -1,84 +1,23 @@ # This module provides all the column helper methods to deal with the # values and adds the common type management code for the adapters. - -# try rails 3.1, then rails 3.2+, mysql column adapters -column_class = if defined? ActiveRecord::ConnectionAdapters::Mysql2Column - ActiveRecord::ConnectionAdapters::Mysql2Column -elsif defined? ActiveRecord::ConnectionAdapters::MysqlColumn - ActiveRecord::ConnectionAdapters::MysqlColumn -elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column - ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column -elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter::Column - ActiveRecord::ConnectionAdapters::MysqlAdapter::Column -else - ObviousHint::NoMysqlAdapterFound +adapter_class = if defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter + ActiveRecord::ConnectionAdapters::Mysql2Adapter +elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter + ActiveRecord::ConnectionAdapters::MysqlAdapter end -column_class.module_eval do - - # The class for enum is Symbol. - alias __klass_enum klass - def klass - if type == :enum - Symbol - else - __klass_enum - end - end - - # Convert to a symbol. - alias __type_cast_enum type_cast - def type_cast(value) - if type == :enum - value.is_a?(Symbol) ? value : string_to_valid_enum(value) - else - __type_cast_enum(value) - end - end +if adapter_class + adapter_class.class_eval do - # Code to convert to a symbol. - alias __type_cast_code_enum type_cast_code - def type_cast_code(var_name) - if type == :enum - "#{var_name}.is_a?(Symbol) ? #{var_name} : #{string_to_valid_enum_hash_code}[#{var_name}]" - else - __type_cast_code_enum(var_name) - end + protected + def initialize_type_map_with_enum_types(m) + initialize_type_map_without_enum_types(m) + m.register_type(%r(enum)i) do |sql_type| + limit = sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } + ActiveRecord::Type::Enum.new(limit: limit) + end + end + alias_method_chain :initialize_type_map, :enum_types end - -private - - # The enum simple type. - alias __simplified_type_enum simplified_type - def simplified_type(field_type) - if field_type =~ /enum/i - :enum - else - __simplified_type_enum(field_type) - end - end - - alias __extract_limit_enum extract_limit - def extract_limit(sql_type) - if sql_type =~ /^enum/i - sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } - else - __extract_limit_enum(sql_type) - end - end - - def string_to_valid_enum(str) - @valid_strings_filter ||= Hash[enum_valid_string_assoc] - @valid_strings_filter[str] - end - - def string_to_valid_enum_hash_code - Hash[enum_valid_string_assoc].to_s - end - - def enum_valid_string_assoc - limit.map(&:to_s).zip(limit) - end - end diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb new file mode 100644 index 0000000..e3a4237 --- /dev/null +++ b/lib/enum/enum_column_adapter.rb @@ -0,0 +1,81 @@ +# This module provides all the column helper methods to deal with the +# values and adds the common type management code for the adapters. + + +# try rails 3.1, then rails 3.2+, mysql column adapters +column_class = if defined? ActiveRecord::ConnectionAdapters::Mysql2Column + ActiveRecord::ConnectionAdapters::Mysql2Column +elsif defined? ActiveRecord::ConnectionAdapters::MysqlColumn + ActiveRecord::ConnectionAdapters::MysqlColumn +elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column + ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column +elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter::Column + ActiveRecord::ConnectionAdapters::MysqlAdapter::Column +else + ObviousHint::NoMysqlAdapterFound +end + +column_class.class_eval do + + alias __klass_enum klass + # The class for enum is Symbol. + def klass + if type == :enum + Symbol + else + __klass_enum + end + end + + alias __type_cast_enum type_cast_from_database + # Convert to a symbol. + def type_cast_from_database(value) + if type == :enum + self.class.value_to_symbol(value) + else + __type_cast_enum(value) + end + end + + # Deprecated in Rails 4.1 + if respond_to?(:type_cast_code) + alias __type_cast_code_enum type_cast_code + # Code to convert to a symbol. + def type_cast_code(var_name) + if type == :enum + "#{self.class.name}.value_to_symbol(#{var_name})" + else + __type_cast_code_enum(var_name) + end + end + end + + class << self + # Safely convert the value to a symbol. + def value_to_symbol(value) + case value + when Symbol + value + when String + value.empty? ? nil : value.intern + else + nil + end + end + end + +private + + # Deprecated in Rails 4.2 + if respond_to?(:extract_limit) + alias __extract_limit_enum extract_limit + def extract_limit(sql_type) + if sql_type =~ /^enum/i + sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } + else + __extract_limit_enum(sql_type) + end + end + end + +end diff --git a/lib/enum/enum_type.rb b/lib/enum/enum_type.rb new file mode 100644 index 0000000..0c707f3 --- /dev/null +++ b/lib/enum/enum_type.rb @@ -0,0 +1,23 @@ +module ActiveRecord + module Type + class Enum < Value # :nodoc: + def type + :enum + end + + def type_cast_for_database + value.to_s + end + + private + + def cast_value(value) + if value == '' + nil + else + value.to_sym + end + end + end + end +end diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 59ccafa..7ce64d5 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -1,7 +1,5 @@ adapter_class = if defined? ActiveRecord::ConnectionAdapters::MySQLJdbcConnection ActiveRecord::ConnectionAdapters::MySQLJdbcConnection -elsif defined? ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter - ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter::MainAdapter elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::Mysql2Adapter elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter @@ -9,11 +7,11 @@ end adapter_class.module_eval do - alias __native_database_types_enum native_database_types + def native_database_types #:nodoc types = __native_database_types_enum types[:enum] = { :name => "enum" } types end -end +end \ No newline at end of file diff --git a/lib/enum/quoting.rb b/lib/enum/quoting.rb index 842497f..637ac40 100644 --- a/lib/enum/quoting.rb +++ b/lib/enum/quoting.rb @@ -1,10 +1,10 @@ module ActiveRecord module ConnectionAdapters # :nodoc: module Quoting + alias __quote_enum quote # Quote a symbol as a normal string. This will support quoting of # enumerated values. - alias __quote_enum quote def quote(value, column = nil) if !value.is_a? Symbol __quote_enum(value, column) @@ -12,7 +12,6 @@ def quote(value, column = nil) ActiveRecord::Base.send(:quote_bound_value, value.to_s) end end - end end end diff --git a/lib/enum/schema_statements.rb b/lib/enum/schema_statements.rb index 3e436a8..6895bd8 100644 --- a/lib/enum/schema_statements.rb +++ b/lib/enum/schema_statements.rb @@ -1,15 +1,15 @@ module ActiveRecord module ConnectionAdapters # :nodoc: module SchemaStatements + alias __type_to_sql_enum type_to_sql # Add enumeration support for schema statement creation. This # will have to be adapted for every adapter if the type requires # anything by a list of allowed values. The overrides the standard - # type_to_sql method and chains back to the default. This could + # type_to_sql method and chains back to the default. This could # be done on a per adapter basis, but is generalized here. # # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] - alias __type_to_sql_enum type_to_sql def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: if type == :enum native = native_database_types[type] diff --git a/lib/enum_column.rb b/lib/enum_column.rb index 7d951bb..ca6e88f 100644 --- a/lib/enum_column.rb +++ b/lib/enum_column.rb @@ -3,7 +3,9 @@ class EnumColumnRailtie < Rails::Railtie initializer 'enum_column.initialize', :after => 'active_record.initialize_database' do |app| ActiveSupport.on_load :active_record do require 'enum/mysql_adapter' + require 'enum/enum_type' require 'enum/enum_adapter' + require 'enum/enum_column_adapter' require 'enum/schema_statements' require 'enum/schema_definitions' require 'enum/quoting' @@ -15,4 +17,4 @@ class EnumColumnRailtie < Rails::Railtie end end end -end \ No newline at end of file +end diff --git a/lib/enum_column_strict.rb b/lib/enum_column3.rb similarity index 100% rename from lib/enum_column_strict.rb rename to lib/enum_column3.rb From 504730ca39198bc3afcd6b8c960aefa56f372abc Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 10:51:59 -0400 Subject: [PATCH 11/34] Update version --- enum_column.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index cc85de6..8c3f1e8 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "0.1.4" + s.version = "0.1.6" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] From 8dd883ac61de292a9ec578da026165169333d5b1 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:01:29 -0400 Subject: [PATCH 12/34] Backwards compatability for Rails 4.1 --- lib/enum/enum_type.rb | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/lib/enum/enum_type.rb b/lib/enum/enum_type.rb index 0c707f3..930b9e7 100644 --- a/lib/enum/enum_type.rb +++ b/lib/enum/enum_type.rb @@ -1,23 +1,25 @@ -module ActiveRecord - module Type - class Enum < Value # :nodoc: - def type - :enum - end +if defined? ActiveRecord::Type::Value + module ActiveRecord + module Type + class Enum < Value # :nodoc: + def type + :enum + end - def type_cast_for_database - value.to_s - end + def type_cast_for_database + value.to_s + end - private + private - def cast_value(value) - if value == '' - nil - else - value.to_sym + def cast_value(value) + if value == '' + nil + else + value.to_sym + end end - end + end end end end From 074d852332de7871f0d4fc7d056760b0cd800846 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:05:16 -0400 Subject: [PATCH 13/34] Prevent aliasing of initialize_type_map on older Rails versions --- lib/enum/enum_adapter.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index c50e624..77276c1 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -11,13 +11,15 @@ adapter_class.class_eval do protected - def initialize_type_map_with_enum_types(m) - initialize_type_map_without_enum_types(m) - m.register_type(%r(enum)i) do |sql_type| - limit = sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } - ActiveRecord::Type::Enum.new(limit: limit) + if respond_to?(:initialize_type_map) + def initialize_type_map_with_enum_types(m) + initialize_type_map_without_enum_types(m) + m.register_type(%r(enum)i) do |sql_type| + limit = sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } + ActiveRecord::Type::Enum.new(limit: limit) + end end + alias_method_chain :initialize_type_map, :enum_types end - alias_method_chain :initialize_type_map, :enum_types end end From c98e7ec7b4d0f8b3493da4f480d7bf2d9d449304 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:07:08 -0400 Subject: [PATCH 14/34] Protect type_cast_from_database from bc breaks --- lib/enum/enum_column_adapter.rb | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index e3a4237..c45cb97 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -27,13 +27,15 @@ def klass end end - alias __type_cast_enum type_cast_from_database - # Convert to a symbol. - def type_cast_from_database(value) - if type == :enum - self.class.value_to_symbol(value) - else - __type_cast_enum(value) + if respond_to?(:type_cast_from_database) + alias __type_cast_enum type_cast_from_database + # Convert to a symbol. + def type_cast_from_database(value) + if type == :enum + self.class.value_to_symbol(value) + else + __type_cast_enum(value) + end end end From 64f255236b336be8c6382fcecca24632fc7a012c Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:17:49 -0400 Subject: [PATCH 15/34] Situational method declaration based on Rails versions --- lib/enum/enum_column_adapter.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index c45cb97..a92c356 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -27,15 +27,24 @@ def klass end end + def __enum_type_cast(value) + if type == :enum + self.class.value_to_symbol(value) + else + __type_cast_enum(value) + end + end + if respond_to?(:type_cast_from_database) alias __type_cast_enum type_cast_from_database # Convert to a symbol. def type_cast_from_database(value) - if type == :enum - self.class.value_to_symbol(value) - else - __type_cast_enum(value) - end + __enum_type_cast(value) + end + elsif respond_to?(:type_cast) + alias __type_cast_enum type_cast + def type_cast(value) + __enum_type_cast(value) end end From c3f51a0625de20152f18e44561260dd671a8f8c3 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:22:28 -0400 Subject: [PATCH 16/34] Restore simplified_type --- lib/enum/enum_column_adapter.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index a92c356..f341820 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -77,6 +77,19 @@ def value_to_symbol(value) private + # Deprecated in Rails 4.2 + if respond_to?(:simplified_type) + alias __simplified_type_enum simplified_type + # The enum simple type. + def simplified_type(field_type) + if field_type =~ /enum/i + :enum + else + __simplified_type_enum(field_type) + end + end + end + # Deprecated in Rails 4.2 if respond_to?(:extract_limit) alias __extract_limit_enum extract_limit From afd4e4710abcbe2af64b7d585272e75528eac27c Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 11:38:50 -0400 Subject: [PATCH 17/34] See if method_defined is more reliable --- lib/enum/enum_column_adapter.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index f341820..9a0df4a 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -35,13 +35,13 @@ def __enum_type_cast(value) end end - if respond_to?(:type_cast_from_database) + if method_defined?(:type_cast_from_database) alias __type_cast_enum type_cast_from_database # Convert to a symbol. def type_cast_from_database(value) __enum_type_cast(value) end - elsif respond_to?(:type_cast) + elsif method_defined?(:type_cast) alias __type_cast_enum type_cast def type_cast(value) __enum_type_cast(value) @@ -49,7 +49,7 @@ def type_cast(value) end # Deprecated in Rails 4.1 - if respond_to?(:type_cast_code) + if method_defined?(:type_cast_code) alias __type_cast_code_enum type_cast_code # Code to convert to a symbol. def type_cast_code(var_name) @@ -78,7 +78,7 @@ def value_to_symbol(value) private # Deprecated in Rails 4.2 - if respond_to?(:simplified_type) + if method_defined?(:simplified_type) alias __simplified_type_enum simplified_type # The enum simple type. def simplified_type(field_type) @@ -91,7 +91,7 @@ def simplified_type(field_type) end # Deprecated in Rails 4.2 - if respond_to?(:extract_limit) + if method_defined?(:extract_limit) alias __extract_limit_enum extract_limit def extract_limit(sql_type) if sql_type =~ /^enum/i From bf6e15dcdfb073564f668493b8cc6349aafa24ca Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 12:16:17 -0400 Subject: [PATCH 18/34] Turns out that instance_methods and private_instance_methods are the reliable way to do it --- lib/enum/enum_column_adapter.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index 9a0df4a..0e52c98 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -35,13 +35,13 @@ def __enum_type_cast(value) end end - if method_defined?(:type_cast_from_database) + if instance_methods.include?(:type_cast_from_database) alias __type_cast_enum type_cast_from_database # Convert to a symbol. def type_cast_from_database(value) __enum_type_cast(value) end - elsif method_defined?(:type_cast) + elsif instance_methods.include?(:type_cast) alias __type_cast_enum type_cast def type_cast(value) __enum_type_cast(value) @@ -49,7 +49,7 @@ def type_cast(value) end # Deprecated in Rails 4.1 - if method_defined?(:type_cast_code) + if instance_methods.include?(:type_cast_code) alias __type_cast_code_enum type_cast_code # Code to convert to a symbol. def type_cast_code(var_name) @@ -78,7 +78,7 @@ def value_to_symbol(value) private # Deprecated in Rails 4.2 - if method_defined?(:simplified_type) + if private_instance_methods.include?(:simplified_type) alias __simplified_type_enum simplified_type # The enum simple type. def simplified_type(field_type) @@ -91,7 +91,7 @@ def simplified_type(field_type) end # Deprecated in Rails 4.2 - if method_defined?(:extract_limit) + if private_instance_methods.include?(:extract_limit) alias __extract_limit_enum extract_limit def extract_limit(sql_type) if sql_type =~ /^enum/i From 0088bb18547a295568d7326d832beaad44496726 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 12:26:40 -0400 Subject: [PATCH 19/34] Must not forget about forwards compatability --- lib/enum/enum_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/enum_adapter.rb b/lib/enum/enum_adapter.rb index 77276c1..b7b6b0c 100644 --- a/lib/enum/enum_adapter.rb +++ b/lib/enum/enum_adapter.rb @@ -11,7 +11,7 @@ adapter_class.class_eval do protected - if respond_to?(:initialize_type_map) + if instance_methods.include?(:initialize_type_map) def initialize_type_map_with_enum_types(m) initialize_type_map_without_enum_types(m) m.register_type(%r(enum)i) do |sql_type| From 00e451ef60f855f8c820ba03b6b429ec0c285b7a Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 20 Aug 2015 13:46:48 -0400 Subject: [PATCH 20/34] Add parameter to type_cast_for_database --- lib/enum/enum_type.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/enum_type.rb b/lib/enum/enum_type.rb index 930b9e7..4d30117 100644 --- a/lib/enum/enum_type.rb +++ b/lib/enum/enum_type.rb @@ -6,7 +6,7 @@ def type :enum end - def type_cast_for_database + def type_cast_for_database(value) value.to_s end From b269e21430c07bdf86ad6796444eb1d45ef5b204 Mon Sep 17 00:00:00 2001 From: Stan Cheng Date: Mon, 31 Aug 2015 13:10:53 -0400 Subject: [PATCH 21/34] Bump to 0.1.7: Fix mapping of nil value for enum --- enum_column.gemspec | 2 +- lib/enum/enum_type.rb | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 8c3f1e8..6f9a9dc 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "0.1.6" + s.version = "0.1.7" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] diff --git a/lib/enum/enum_type.rb b/lib/enum/enum_type.rb index 4d30117..9ae0678 100644 --- a/lib/enum/enum_type.rb +++ b/lib/enum/enum_type.rb @@ -7,13 +7,17 @@ def type end def type_cast_for_database(value) - value.to_s + if value.nil? || value == '' + nil + else + value.to_s + end end private def cast_value(value) - if value == '' + if value.nil? || value == '' nil else value.to_sym From 0e5bea9bdd513295586d9b9d03698ca68a44fa07 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Mon, 14 Sep 2015 12:55:27 -0400 Subject: [PATCH 22/34] v0.1.8: Fix default value not returning as a symbol --- lib/enum/enum_column_adapter.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index 0e52c98..e3d5264 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -27,6 +27,20 @@ def klass end end + if instance_methods.include?(:extract_default) + alias __extract_default_enum extract_default + def extract_default + if type == :enum + if @default == '' || @default.nil? + @default = nil + else + @default = @default.intern + end + end + __extract_default_enum + end + end + def __enum_type_cast(value) if type == :enum self.class.value_to_symbol(value) From 7f426ca347aa23d2f775b8e276476b18d752fcba Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Mon, 14 Sep 2015 12:58:49 -0400 Subject: [PATCH 23/34] Version bump the gemspec to 0.1.8 --- enum_column.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 6f9a9dc..1d98dd8 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "0.1.7" + s.version = "0.1.8" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] From 9b29aff1c5396a38adef7016874571deeab8ceed Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Tue, 9 May 2017 16:09:41 -0400 Subject: [PATCH 24/34] Add new adapter name and bump gemspec --- enum_column.gemspec | 2 +- lib/enum/enum_column_adapter.rb | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 1d98dd8..7002f59 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "0.1.8" + s.version = "0.1.9" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index e3d5264..6130bc5 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -11,6 +11,8 @@ ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter::Column ActiveRecord::ConnectionAdapters::MysqlAdapter::Column +elsif defined? ActiveRecord::ConnectionAdapters::MySQL::Column + ActiveRecord::ConnectionAdapters::MySQL::Column else ObviousHint::NoMysqlAdapterFound end From 96dcebf6de80ec402a8d361f624d30325ed44742 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Tue, 9 May 2017 16:37:00 -0400 Subject: [PATCH 25/34] Remove klass alias and method as Rails5 seems to have deprecated it --- lib/enum/enum_column_adapter.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index 6130bc5..6a1e60e 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -19,16 +19,6 @@ column_class.class_eval do - alias __klass_enum klass - # The class for enum is Symbol. - def klass - if type == :enum - Symbol - else - __klass_enum - end - end - if instance_methods.include?(:extract_default) alias __extract_default_enum extract_default def extract_default From 2e7d879715ff6ee565f12ed722692acf3919f5a3 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Tue, 9 May 2017 16:37:21 -0400 Subject: [PATCH 26/34] Bump gemspec to 5.0.0 --- enum_column.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 7002f59..1121b71 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "0.1.9" + s.version = "5.0.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] From ebffc003d3d2482e415c94619cfd9fbc0b36f539 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Fri, 12 May 2017 12:13:30 -0400 Subject: [PATCH 27/34] Remove second argument in enum_column quoting for Rails 5.1 --- enum_column.gemspec | 2 +- lib/enum/quoting.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 1121b71..870644d 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "5.0.0" + s.version = "5.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] diff --git a/lib/enum/quoting.rb b/lib/enum/quoting.rb index 637ac40..1b6c1f9 100644 --- a/lib/enum/quoting.rb +++ b/lib/enum/quoting.rb @@ -5,9 +5,9 @@ module Quoting # Quote a symbol as a normal string. This will support quoting of # enumerated values. - def quote(value, column = nil) + def quote(value) if !value.is_a? Symbol - __quote_enum(value, column) + __quote_enum(value) else ActiveRecord::Base.send(:quote_bound_value, value.to_s) end From a1db70c8c7802107835321091850b376ece7e848 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Wed, 17 May 2017 16:25:24 -0400 Subject: [PATCH 28/34] Implement modified ColumnDumper for enum type --- lib/enum/schema_dumper.rb | 18 ++++++++++++++++++ lib/enum_column.rb | 1 + 2 files changed, 19 insertions(+) create mode 100644 lib/enum/schema_dumper.rb diff --git a/lib/enum/schema_dumper.rb b/lib/enum/schema_dumper.rb new file mode 100644 index 0000000..57afff5 --- /dev/null +++ b/lib/enum/schema_dumper.rb @@ -0,0 +1,18 @@ +module ActiveRecord + module ConnectionAdapters + module MySQL + module ColumnDumper # :nodoc: + private + alias __schema_type_enum schema_type + def schema_type(column) + case column.sql_type + when /enum/i + :enum + else + __schema_type_enum(column) + end + end + end + end + end +end diff --git a/lib/enum_column.rb b/lib/enum_column.rb index ca6e88f..78d7b25 100644 --- a/lib/enum_column.rb +++ b/lib/enum_column.rb @@ -8,6 +8,7 @@ class EnumColumnRailtie < Rails::Railtie require 'enum/enum_column_adapter' require 'enum/schema_statements' require 'enum/schema_definitions' + require 'enum/schema_dumper' require 'enum/quoting' require 'enum/validations' end From f7899cb1f673fcaf58118b2dfbbeae5425a85665 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Fri, 19 May 2017 13:37:03 -0400 Subject: [PATCH 29/34] Utilize the new prepend methodology and add the new register_type to the MysqlAdapter --- lib/enum/mysql_adapter.rb | 51 ++++++++++++++++++++++++++++++----- lib/enum/schema_dumper.rb | 18 ------------- lib/enum/schema_statements.rb | 27 ------------------- lib/enum_column.rb | 2 -- 4 files changed, 44 insertions(+), 54 deletions(-) delete mode 100644 lib/enum/schema_dumper.rb delete mode 100644 lib/enum/schema_statements.rb diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 7ce64d5..261940c 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -1,17 +1,54 @@ adapter_class = if defined? ActiveRecord::ConnectionAdapters::MySQLJdbcConnection ActiveRecord::ConnectionAdapters::MySQLJdbcConnection +# elsif defined? ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter +# ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter ActiveRecord::ConnectionAdapters::Mysql2Adapter elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter ActiveRecord::ConnectionAdapters::MysqlAdapter end -adapter_class.module_eval do - alias __native_database_types_enum native_database_types +module EnumColumn + module ConnectionAdapters + module EnumAdapter - def native_database_types #:nodoc - types = __native_database_types_enum - types[:enum] = { :name => "enum" } - types + def native_database_types #:nodoc + types = super + types[:enum] = { :name => "enum" } + types + end + + # Add enumeration support for schema statement creation. This + # will have to be adapted for every adapter if the type requires + # anything by a list of allowed values. The overrides the standard + # type_to_sql method and chains back to the default. This could + # be done on a per adapter basis, but is generalized here. + # + # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] + def type_to_sql(type, limit = nil, precision = nil, scale = nil) + if type.to_s == 'enum' + native = native_database_types[type] + column_type_sql = (native || {})[:name] || 'enum' + + column_type_sql << "(#{limit[:limit].map { |v| quote(v) }.join(',')})" + + column_type_sql + else + super(type, limit, precision, scale) + end + end + + private + def initialize_type_map(m) + super + + m.register_type(%r(enum)i) do |sql_type| + limit = sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } + ActiveRecord::Type::Enum.new(limit: limit) + end + end + end end -end \ No newline at end of file +end + +adapter_class.prepend(EnumColumn::ConnectionAdapters::EnumAdapter) diff --git a/lib/enum/schema_dumper.rb b/lib/enum/schema_dumper.rb deleted file mode 100644 index 57afff5..0000000 --- a/lib/enum/schema_dumper.rb +++ /dev/null @@ -1,18 +0,0 @@ -module ActiveRecord - module ConnectionAdapters - module MySQL - module ColumnDumper # :nodoc: - private - alias __schema_type_enum schema_type - def schema_type(column) - case column.sql_type - when /enum/i - :enum - else - __schema_type_enum(column) - end - end - end - end - end -end diff --git a/lib/enum/schema_statements.rb b/lib/enum/schema_statements.rb deleted file mode 100644 index 6895bd8..0000000 --- a/lib/enum/schema_statements.rb +++ /dev/null @@ -1,27 +0,0 @@ -module ActiveRecord - module ConnectionAdapters # :nodoc: - module SchemaStatements - alias __type_to_sql_enum type_to_sql - - # Add enumeration support for schema statement creation. This - # will have to be adapted for every adapter if the type requires - # anything by a list of allowed values. The overrides the standard - # type_to_sql method and chains back to the default. This could - # be done on a per adapter basis, but is generalized here. - # - # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] - def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: - if type == :enum - native = native_database_types[type] - column_type_sql = (native || {})[:name] || 'enum' - - column_type_sql << "(#{limit.map { |v| quote(v) }.join(',')})" - - column_type_sql - else - __type_to_sql_enum(type, limit, precision, scale) - end - end - end - end -end diff --git a/lib/enum_column.rb b/lib/enum_column.rb index 78d7b25..fe343b3 100644 --- a/lib/enum_column.rb +++ b/lib/enum_column.rb @@ -6,9 +6,7 @@ class EnumColumnRailtie < Rails::Railtie require 'enum/enum_type' require 'enum/enum_adapter' require 'enum/enum_column_adapter' - require 'enum/schema_statements' require 'enum/schema_definitions' - require 'enum/schema_dumper' require 'enum/quoting' require 'enum/validations' end From 6e7ec8d79ec302c9c3292be60fbc9c4030ff593a Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Fri, 19 May 2017 13:37:52 -0400 Subject: [PATCH 30/34] Version bump to 5.1.1 --- enum_column.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enum_column.gemspec b/enum_column.gemspec index 870644d..772ce95 100644 --- a/enum_column.gemspec +++ b/enum_column.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = "enum_column3" - s.version = "5.1.0" + s.version = "5.1.1" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] From 3440eaaefdab7b158cebf609a7357d7cec8132da Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Mon, 29 May 2017 11:52:08 -0400 Subject: [PATCH 31/34] Fix type_to_sql method to use the new keyword argument syntax --- lib/enum/mysql_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 261940c..9583e37 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -25,7 +25,7 @@ def native_database_types #:nodoc # be done on a per adapter basis, but is generalized here. # # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] - def type_to_sql(type, limit = nil, precision = nil, scale = nil) + def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **) # :nodoc: if type.to_s == 'enum' native = native_database_types[type] column_type_sql = (native || {})[:name] || 'enum' @@ -34,7 +34,7 @@ def type_to_sql(type, limit = nil, precision = nil, scale = nil) column_type_sql else - super(type, limit, precision, scale) + super(type, limit: limit, precision: precision, scale: scale, unsigned: unsigned) end end From 9e81474e6459232c64b52d9c3288d0a61e7feb46 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Wed, 31 May 2017 14:46:25 -0400 Subject: [PATCH 32/34] limit var in type_to_sql is now direct, not a hash --- lib/enum/mysql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 9583e37..fa376c9 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -30,7 +30,7 @@ def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **) native = native_database_types[type] column_type_sql = (native || {})[:name] || 'enum' - column_type_sql << "(#{limit[:limit].map { |v| quote(v) }.join(',')})" + column_type_sql << "(#{limit.map { |v| quote(v) }.join(',')})" column_type_sql else From 17b631556e444387e139121a75af54d1e28c5fe8 Mon Sep 17 00:00:00 2001 From: Stan Cheng Date: Thu, 9 Aug 2018 10:24:46 -0400 Subject: [PATCH 33/34] Set default parameter --- lib/enum/mysql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index fa376c9..74f430c 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -39,7 +39,7 @@ def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **) end private - def initialize_type_map(m) + def initialize_type_map(m = type_map) super m.register_type(%r(enum)i) do |sql_type| From c3f769b8d455fda3a08847fcf4b3c64a2cab87e0 Mon Sep 17 00:00:00 2001 From: Schuyler Jager Date: Thu, 27 Jun 2019 10:39:29 -0400 Subject: [PATCH 34/34] Simple retrofit to ensure that enum_column doesn't collide when testing with other SQL adapters such as Postgres or CockroachDB --- lib/enum/enum_column_adapter.rb | 142 ++++++++++++++++---------------- lib/enum/mysql_adapter.rb | 4 +- 2 files changed, 74 insertions(+), 72 deletions(-) diff --git a/lib/enum/enum_column_adapter.rb b/lib/enum/enum_column_adapter.rb index 6a1e60e..4f95271 100644 --- a/lib/enum/enum_column_adapter.rb +++ b/lib/enum/enum_column_adapter.rb @@ -13,99 +13,99 @@ ActiveRecord::ConnectionAdapters::MysqlAdapter::Column elsif defined? ActiveRecord::ConnectionAdapters::MySQL::Column ActiveRecord::ConnectionAdapters::MySQL::Column -else - ObviousHint::NoMysqlAdapterFound end -column_class.class_eval do +if column_class + column_class.class_eval do - if instance_methods.include?(:extract_default) - alias __extract_default_enum extract_default - def extract_default - if type == :enum - if @default == '' || @default.nil? - @default = nil - else - @default = @default.intern + if instance_methods.include?(:extract_default) + alias __extract_default_enum extract_default + def extract_default + if type == :enum + if @default == '' || @default.nil? + @default = nil + else + @default = @default.intern + end end + __extract_default_enum end - __extract_default_enum end - end - def __enum_type_cast(value) - if type == :enum - self.class.value_to_symbol(value) - else - __type_cast_enum(value) + def __enum_type_cast(value) + if type == :enum + self.class.value_to_symbol(value) + else + __type_cast_enum(value) + end end - end - if instance_methods.include?(:type_cast_from_database) - alias __type_cast_enum type_cast_from_database - # Convert to a symbol. - def type_cast_from_database(value) - __enum_type_cast(value) - end - elsif instance_methods.include?(:type_cast) - alias __type_cast_enum type_cast - def type_cast(value) - __enum_type_cast(value) + if instance_methods.include?(:type_cast_from_database) + alias __type_cast_enum type_cast_from_database + # Convert to a symbol. + def type_cast_from_database(value) + __enum_type_cast(value) + end + elsif instance_methods.include?(:type_cast) + alias __type_cast_enum type_cast + def type_cast(value) + __enum_type_cast(value) + end end - end - # Deprecated in Rails 4.1 - if instance_methods.include?(:type_cast_code) - alias __type_cast_code_enum type_cast_code - # Code to convert to a symbol. - def type_cast_code(var_name) - if type == :enum - "#{self.class.name}.value_to_symbol(#{var_name})" - else - __type_cast_code_enum(var_name) + # Deprecated in Rails 4.1 + if instance_methods.include?(:type_cast_code) + alias __type_cast_code_enum type_cast_code + # Code to convert to a symbol. + def type_cast_code(var_name) + if type == :enum + "#{self.class.name}.value_to_symbol(#{var_name})" + else + __type_cast_code_enum(var_name) + end end end - end - class << self - # Safely convert the value to a symbol. - def value_to_symbol(value) - case value - when Symbol - value - when String - value.empty? ? nil : value.intern - else - nil + class << self + # Safely convert the value to a symbol. + def value_to_symbol(value) + case value + when Symbol + value + when String + value.empty? ? nil : value.intern + else + nil + end end end - end -private + private - # Deprecated in Rails 4.2 - if private_instance_methods.include?(:simplified_type) - alias __simplified_type_enum simplified_type - # The enum simple type. - def simplified_type(field_type) - if field_type =~ /enum/i - :enum - else - __simplified_type_enum(field_type) + # Deprecated in Rails 4.2 + if private_instance_methods.include?(:simplified_type) + alias __simplified_type_enum simplified_type + # The enum simple type. + def simplified_type(field_type) + if field_type =~ /enum/i + :enum + else + __simplified_type_enum(field_type) + end end end - end - # Deprecated in Rails 4.2 - if private_instance_methods.include?(:extract_limit) - alias __extract_limit_enum extract_limit - def extract_limit(sql_type) - if sql_type =~ /^enum/i - sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } - else - __extract_limit_enum(sql_type) + # Deprecated in Rails 4.2 + if private_instance_methods.include?(:extract_limit) + alias __extract_limit_enum extract_limit + def extract_limit(sql_type) + if sql_type =~ /^enum/i + sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } + else + __extract_limit_enum(sql_type) + end end end - end + end end diff --git a/lib/enum/mysql_adapter.rb b/lib/enum/mysql_adapter.rb index 74f430c..d7729f5 100644 --- a/lib/enum/mysql_adapter.rb +++ b/lib/enum/mysql_adapter.rb @@ -51,4 +51,6 @@ def initialize_type_map(m = type_map) end end -adapter_class.prepend(EnumColumn::ConnectionAdapters::EnumAdapter) +if adapter_class + adapter_class.prepend(EnumColumn::ConnectionAdapters::EnumAdapter) +end