├── rails └── init.rb ├── lib ├── enum_column_strict.rb ├── enum │ ├── schema_definitions.rb │ ├── quoting.rb │ ├── mysql_adapter.rb │ ├── schema_statements.rb │ ├── validations.rb │ ├── active_record_helper.rb │ └── enum_adapter.rb └── enum_column.rb ├── init.rb ├── test ├── fixtures │ ├── enum_controller.rb │ └── enumeration.rb ├── enum_controller_test.rb ├── test_helper.rb ├── db │ └── schema.rb └── enum_mysql_test.rb ├── LICENSE ├── enum_column.gemspec └── README.txt /rails/init.rb: -------------------------------------------------------------------------------- 1 | require 'enum_column' -------------------------------------------------------------------------------- /lib/enum_column_strict.rb: -------------------------------------------------------------------------------- 1 | require 'enum_column' -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + "/rails/init.rb" -------------------------------------------------------------------------------- /test/fixtures/enum_controller.rb: -------------------------------------------------------------------------------- 1 | class EnumController < ActionController::Base 2 | layout false 3 | 4 | def enum_select 5 | @test = Enumeration.new 6 | render :inline => "<%= enum_select('test', 'severity')%>" 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /lib/enum/schema_definitions.rb: -------------------------------------------------------------------------------- 1 | 2 | module ActiveRecord 3 | module ConnectionAdapters 4 | class TableDefinition 5 | def enum(*args) 6 | options = args.extract_options! 7 | column_names = args 8 | column_names.each { |name| column(name, 'enum', options) } 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/fixtures/enumeration.rb: -------------------------------------------------------------------------------- 1 | 2 | class Enumeration < ActiveRecord::Base 3 | validates_columns :color, :severity, :string_field, :int_field 4 | end 5 | 6 | class BasicEnum < ActiveRecord::Base 7 | validates_columns :value 8 | end 9 | 10 | class BasicDefaultEnum < ActiveRecord::Base 11 | validates_columns :value 12 | end 13 | 14 | class NonnullEnum < ActiveRecord::Base 15 | validates_columns :value 16 | end 17 | 18 | class NonnullDefaultEnum < ActiveRecord::Base 19 | validates_columns :value 20 | end 21 | -------------------------------------------------------------------------------- /lib/enum/quoting.rb: -------------------------------------------------------------------------------- 1 | module ActiveRecord 2 | module ConnectionAdapters # :nodoc: 3 | module Quoting 4 | alias __quote_enum quote 5 | 6 | # Quote a symbol as a normal string. This will support quoting of 7 | # enumerated values. 8 | def quote(value, column = nil) 9 | if !value.is_a? Symbol 10 | __quote_enum(value, column) 11 | else 12 | ActiveRecord::Base.send(:quote_bound_value, value.to_s) 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/enum_column.rb: -------------------------------------------------------------------------------- 1 | if defined?(::Rails::Railtie) 2 | class EnumColumnRailtie < Rails::Railtie 3 | initializer 'enum_column.initialize', :after => 'active_record.initialize_database' do |app| 4 | ActiveSupport.on_load :active_record do 5 | require 'enum/mysql_adapter' 6 | require 'enum/enum_adapter' 7 | require 'enum/schema_statements' 8 | require 'enum/schema_definitions' 9 | require 'enum/quoting' 10 | require 'enum/validations' 11 | end 12 | 13 | ActiveSupport.on_load :action_view do 14 | require 'enum/active_record_helper' 15 | end 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /lib/enum/mysql_adapter.rb: -------------------------------------------------------------------------------- 1 | adapter_class = if defined? ActiveRecord::ConnectionAdapters::MySQLJdbcConnection 2 | ActiveRecord::ConnectionAdapters::MySQLJdbcConnection 3 | elsif defined? ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter 4 | ActiveRecord::ConnectionAdapters::Mysql2SpatialAdapter::MainAdapter 5 | elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter 6 | ActiveRecord::ConnectionAdapters::Mysql2Adapter 7 | elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter 8 | ActiveRecord::ConnectionAdapters::MysqlAdapter 9 | end 10 | 11 | adapter_class.module_eval do 12 | alias __native_database_types_enum native_database_types 13 | 14 | def native_database_types #:nodoc 15 | types = __native_database_types_enum 16 | types[:enum] = { :name => "enum" } 17 | types 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /test/enum_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/test_helper' 2 | require 'fixtures/enumeration' 3 | require 'fixtures/enum_controller' 4 | 5 | class EnumControllerTest < ActionController::TestCase 6 | 7 | def setup 8 | Enumeration.connection.execute 'DELETE FROM enumerations' 9 | 10 | Rails.application.routes.draw do 11 | match '/enum_select' => "enum#enum_select" 12 | end 13 | end 14 | 15 | test "should render enum_select" do 16 | get :enum_select 17 | assert_response :success 18 | assert_equal '', @response.body 22 | end 23 | 24 | end -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # Include the files required to test Engines. 3 | 4 | # Load the default rails test helper - this will load the environment. 5 | require File.dirname(__FILE__) + '/../../../../test/test_helper' 6 | 7 | plugin_path = File::dirname(__FILE__) + '/..' 8 | schema_file = plugin_path + "/test/db/schema.rb" 9 | load(schema_file) if File.exist?(schema_file) 10 | 11 | # set up the fixtures location to use your engine's fixtures 12 | fixture_path = File.dirname(__FILE__) + "/fixtures/" 13 | ActiveSupport::TestCase.fixture_path = fixture_path 14 | $LOAD_PATH.unshift(ActiveSupport::TestCase.fixture_path) 15 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 16 | # ============================================================================= 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/db/schema.rb: -------------------------------------------------------------------------------- 1 | 2 | ActiveRecord::Schema.define do 3 | create_table :enumerations, :force => true do |t| 4 | t.column :severity, :enum, :limit => [:low, :medium, :high, :critical], 5 | :default => :medium 6 | t.column :color, :enum, :limit => [:red, :blue, :green, :yellow] 7 | t.column :string_field, :string, :limit => 8, :null => false 8 | t.column :int_field, :integer 9 | end 10 | 11 | 12 | create_table :basic_enums, :force => true do |t| 13 | t.column :value, :enum, :limit => [:good, :working] 14 | end 15 | 16 | create_table :basic_default_enums, :force => true do |t| 17 | t.column :value, :enum, :limit => [:good, :working],:default => :working 18 | end 19 | 20 | create_table :nonnull_enums, :force => true do |t| 21 | t.column :value, :enum, :limit => [:good, :working],:null => false 22 | end 23 | 24 | create_table :nonnull_default_enums, :force => true do |t| 25 | t.column :value, :enum, :limit => [:good, :working],:null => false,:default => :working 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /lib/enum/schema_statements.rb: -------------------------------------------------------------------------------- 1 | module ActiveRecord 2 | module ConnectionAdapters # :nodoc: 3 | module SchemaStatements 4 | alias __type_to_sql_enum type_to_sql 5 | 6 | # Add enumeration support for schema statement creation. This 7 | # will have to be adapted for every adapter if the type requires 8 | # anything by a list of allowed values. The overrides the standard 9 | # type_to_sql method and chains back to the default. This could 10 | # be done on a per adapter basis, but is generalized here. 11 | # 12 | # will generate enum('a', 'b', 'c') for :limit => [:a, :b, :c] 13 | def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: 14 | if type == :enum 15 | native = native_database_types[type] 16 | column_type_sql = (native || {})[:name] || 'enum' 17 | 18 | column_type_sql << "(#{limit.map { |v| quote(v) }.join(',')})" 19 | 20 | column_type_sql 21 | else 22 | __type_to_sql_enum(type, limit, precision, scale) 23 | end 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2011 Nick Pohodnya 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /enum_column.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'enum_column_strict' 3 | s.version = '0.0.2' 4 | s.authors = ['Nick Pohodnya', 'Aaron Weiner'] 5 | s.email = 'aweiner@mdsol.com' 6 | 7 | s.files = [ 8 | "README.txt", 9 | "LICENSE", 10 | "init.rb", 11 | "lib/enum_column.rb", 12 | "lib/enum_column_strict.rb", 13 | "lib/enum/active_record_helper.rb", 14 | "lib/enum/enum_adapter.rb", 15 | "lib/enum/mysql_adapter.rb", 16 | "lib/enum/quoting.rb", 17 | "lib/enum/schema_definitions.rb", 18 | "lib/enum/schema_statements.rb", 19 | "lib/enum/validations.rb" 20 | ] 21 | s.homepage = %q{http://github.com/mdsol/enum_column} 22 | s.require_paths = ["lib"] 23 | s.summary = %q{Enum type for MySQL db, without the symbol DOS vulnerability.} 24 | s.description = %q{Allows your rails models and views to take advantage of MySQL's native enum type. 25 | Forked from electronick's gem to address http://osvdb.org/show/osvdb/94679} 26 | s.test_files = [ 27 | "test/test_helper.rb", 28 | "test/db/schema.rb", 29 | "test/fixtures/enumeration.rb", 30 | "test/fixtures/enum_controller.rb", 31 | "test/enum_controller_test.rb", 32 | "test/enum_mysql_test.rb" 33 | ] 34 | 35 | end 36 | 37 | -------------------------------------------------------------------------------- /lib/enum/validations.rb: -------------------------------------------------------------------------------- 1 | 2 | module ActiveRecord 3 | module Validations 4 | module ClassMethods 5 | # Automatically validates the column against the schema definition 6 | # for nullability, format, and enumerations. Handles integers, floats, 7 | # enumerations, and string limits. 8 | # 9 | # Usage: validates_columns :severity, :name 10 | def validates_columns(*column_names) 11 | begin 12 | cols = columns_hash 13 | column_names.each do |name| 14 | col = cols[name.to_s] 15 | raise ArgumentError, "Cannot find column #{name}" unless col 16 | 17 | # test for nullability 18 | validates_presence_of(name) if !col.null 19 | 20 | # Test various known types. 21 | case col.type 22 | when :enum 23 | validates_inclusion_of name, :in => col.limit, :allow_nil => true 24 | 25 | when :integer, :float 26 | validates_numericality_of name, :allow_nil => true 27 | 28 | when :string 29 | if col.limit 30 | validates_length_of name, :maximum => col.limit, :allow_nil => true 31 | end 32 | end 33 | end 34 | rescue ActiveRecord::StatementInvalid=>e 35 | raise e unless e.message.include?("42S02") # swallow the exception if its for a missing table 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/enum/active_record_helper.rb: -------------------------------------------------------------------------------- 1 | if defined?(Rails::Generator) 2 | module Rails 3 | module Generator 4 | class GeneratedAttribute 5 | def field_type_with_enumerated_attribute 6 | return (@field_type = :enum_select) if type == :enum 7 | field_type_without_enumerated_attribute 8 | end 9 | alias_method_chain :field_type, :enumerated_attribute 10 | end 11 | end 12 | end 13 | end 14 | 15 | if defined?(ActionView::Base) 16 | module ActionView 17 | module Helpers 18 | 19 | #form_options_helper.rb 20 | module FormOptionsHelper 21 | #def select 22 | def enum_select(object, method, options={}, html_options={}) 23 | InstanceTag.new(object, method, self, options.delete(:object)).to_enum_select_tag(options, html_options) 24 | end 25 | end 26 | 27 | class InstanceTag 28 | def to_enum_select_tag(options, html_options={}) 29 | if self.object.respond_to?(method_name.to_sym) 30 | column = self.object.column_for_attribute(method_name) 31 | if (value = self.object.__send__(method_name.to_sym)) 32 | options[:selected] ||= value.to_s 33 | else 34 | options[:include_blank] = column.null if options[:include_blank].nil? 35 | end 36 | end 37 | to_select_tag(column.limit, options, html_options) 38 | end 39 | 40 | #initialize record_name, method, self 41 | if respond_to?(:to_tag) 42 | def to_tag_with_enumerated_attribute(options={}) 43 | #look for an enum 44 | if (column_type == :enum && self.object.class.respond_to?(method_name.to_sym)) 45 | to_enum_select_tag(options) 46 | else 47 | to_tag_without_enumerated_attribute(options) 48 | end 49 | end 50 | alias_method_chain :to_tag, :enumerated_attribute 51 | end 52 | 53 | end 54 | 55 | class FormBuilder 56 | def enum_select(method, options={}, html_options={}) 57 | @template.enum_select(@object_name, method, objectify_options(options), @default_options.merge(html_options)) 58 | end 59 | end 60 | 61 | end 62 | end 63 | end -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Overview 2 | 3 | This gem is an extension to ActiveRecord which enables native support of enumerations in the database schema using the ENUM type in MySQL. 4 | Currently only MySQL is implemented. 5 | Tested with Rails 3. For Rails 2 the enum-column plugin serves the same functionality but is vulnerable to DOS attacks with typical use. 6 | Works with Scaffolding. 7 | 8 | Supported adapters: 9 | mysql 10 | mysql2 11 | jdbcmysql (by Nilesh Trivedi) 12 | 13 | How to use it. 14 | 15 | In your Gemfile: 16 | 17 | gem 'enum_column_strict' 18 | 19 | In your schema: 20 | 21 | When you create your schema, specify the constraint as a limit: 22 | 23 | create_table :enumerations, :force => true do |t| 24 | t.column :severity, :enum, :limit => [:low, :medium, :high, :critical], :default => :medium 25 | t.column :color, :enum, :limit => [:red, :blue, :green, :yellow] 26 | ... 27 | end 28 | 29 | 30 | In the model: 31 | 32 | You can then automatically validate this column using: 33 | 34 | validates_columns :severity, :color 35 | 36 | The rest will be handled for you. All enumerated values will be given as symbols. 37 | 38 | @e = Enumeration.new 39 | @e.severity = :medium 40 | 41 | You can always use the column reflection to get the list of possible values from the database column. 42 | 43 | Enumeration.columns_hash['color'].limit 44 | or 45 | @enumeration.column_for_attribute(:color).limit 46 | 47 | Will yield: [:red, :blue, :green, :yellow] 48 | 49 | If you assign a string to the column, it will be converted to a symbol if it's valid, and nil otherwise, 50 | so if this is the only way you populate color, validates_presence_of may be the only validation you need. 51 | 52 | Enumeration.new(:color => "red") (color will be :red) 53 | Enumeration.new(:color => "infrared") (color will be nil) 54 | 55 | In views: 56 | 57 | You can use the enum_select helper to generate input for enumerated attributes: 58 | 59 | <%= enum_select(@enumeration, 'severity')%> 60 | or 61 | <%= form_for @enumeration do |f| %> 62 | <%= f.label :severity %> 63 | <%= f.enum_select :severity %> 64 | <% end %> 65 | 66 | -------------------------------------------------------------------------------- /lib/enum/enum_adapter.rb: -------------------------------------------------------------------------------- 1 | # This module provides all the column helper methods to deal with the 2 | # values and adds the common type management code for the adapters. 3 | 4 | 5 | # try rails 3.1, then rails 3.2+, mysql column adapters 6 | column_class = if defined? ActiveRecord::ConnectionAdapters::Mysql2Column 7 | ActiveRecord::ConnectionAdapters::Mysql2Column 8 | elsif defined? ActiveRecord::ConnectionAdapters::MysqlColumn 9 | ActiveRecord::ConnectionAdapters::MysqlColumn 10 | elsif defined? ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column 11 | ActiveRecord::ConnectionAdapters::Mysql2Adapter::Column 12 | elsif defined? ActiveRecord::ConnectionAdapters::MysqlAdapter::Column 13 | ActiveRecord::ConnectionAdapters::MysqlAdapter::Column 14 | else 15 | ObviousHint::NoMysqlAdapterFound 16 | end 17 | 18 | column_class.module_eval do 19 | 20 | alias __klass_enum klass 21 | # The class for enum is Symbol. 22 | def klass 23 | if type == :enum 24 | Symbol 25 | else 26 | __klass_enum 27 | end 28 | end 29 | 30 | alias __type_cast_enum type_cast 31 | # Convert to a symbol. 32 | def type_cast(value) 33 | if type == :enum 34 | value.is_a?(Symbol) ? value : string_to_valid_enum(value) 35 | else 36 | __type_cast_enum(value) 37 | end 38 | end 39 | 40 | alias __type_cast_code_enum type_cast_code 41 | # Code to convert to a symbol. 42 | def type_cast_code(var_name) 43 | if type == :enum 44 | "#{var_name}.is_a?(Symbol) ? #{var_name} : #{string_to_valid_enum_hash_code}[#{var_name}]" 45 | else 46 | __type_cast_code_enum(var_name) 47 | end 48 | end 49 | 50 | private 51 | alias __simplified_type_enum simplified_type 52 | # The enum simple type. 53 | def simplified_type(field_type) 54 | if field_type =~ /enum/i 55 | :enum 56 | else 57 | __simplified_type_enum(field_type) 58 | end 59 | end 60 | 61 | alias __extract_limit_enum extract_limit 62 | def extract_limit(sql_type) 63 | if sql_type =~ /^enum/i 64 | sql_type.sub(/^enum\('(.+)'\)/i, '\1').split("','").map { |v| v.intern } 65 | else 66 | __extract_limit_enum(sql_type) 67 | end 68 | end 69 | 70 | def string_to_valid_enum(str) 71 | @valid_strings_filter ||= Hash[enum_valid_string_assoc] 72 | @valid_strings_filter[str] 73 | end 74 | 75 | def string_to_valid_enum_hash_code 76 | Hash[enum_valid_string_assoc].to_s 77 | end 78 | 79 | def enum_valid_string_assoc 80 | limit.map(&:to_s).zip(limit) 81 | end 82 | 83 | end 84 | -------------------------------------------------------------------------------- /test/enum_mysql_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/test_helper' 2 | require 'fixtures/enumeration' 3 | 4 | class EnumerationsTest < Test::Unit::TestCase 5 | def setup 6 | Enumeration.connection.execute 'DELETE FROM enumerations' 7 | end 8 | 9 | def test_column_values 10 | columns = Enumeration.columns_hash 11 | color_column = columns['color'] 12 | assert color_column 13 | assert_equal [:red, :blue, :green, :yellow], color_column.limit 14 | 15 | severity_column = columns['severity'] 16 | assert severity_column 17 | assert_equal [:low, :medium, :high, :critical], severity_column.limit 18 | assert_equal :medium, severity_column.default 19 | end 20 | 21 | def test_insert_enum 22 | row = Enumeration.new 23 | row.color = :blue 24 | row.string_field = 'test' 25 | assert_equal :medium, row.severity 26 | assert row.save 27 | 28 | db_row = Enumeration.find(row.id) 29 | assert db_row 30 | assert_equal :blue, row.color 31 | assert_equal :medium, row.severity 32 | end 33 | 34 | # Uses the automatic validates_columns to create automatic validation rules 35 | # for columns based on the schema information. 36 | def test_bad_value 37 | row = Enumeration.new 38 | row.color = :violet 39 | row.string_field = 'test' 40 | assert !row.save 41 | 42 | assert row.errors 43 | assert_equal ['is not included in the list'], row.errors['color'] 44 | end 45 | 46 | def test_other_types 47 | row = Enumeration.new 48 | row.string_field = 'a' * 10 49 | assert !row.save 50 | assert_equal ['is too long (maximum is 8 characters)'], row.errors['string_field'] 51 | 52 | row = Enumeration.new 53 | assert !row.save 54 | assert_equal ['can\'t be blank'], row.errors['string_field'] 55 | 56 | row = Enumeration.new 57 | row.string_field = 'test' 58 | row.int_field = 'aaaa' 59 | assert !row.save 60 | assert_equal ['is not a number'], row.errors['int_field'] 61 | 62 | row = Enumeration.new 63 | row.string_field = 'test' 64 | row.int_field = '500' 65 | assert row.save 66 | end 67 | 68 | def test_view_helper 69 | request = ActionController::TestRequest.new 70 | response = ActionController::TestResponse.new 71 | request.action = 'test1' 72 | body = EnumController.process(request, response).body 73 | assert_equal '', body 74 | end 75 | 76 | def test_radio_helper 77 | request = ActionController::TestRequest.new 78 | response = ActionController::TestResponse.new 79 | request.action = 'test2' 80 | body = EnumController.process(request, response).body 81 | assert_equal '', body 82 | end 83 | 84 | 85 | # Basic tests 86 | def test_create_basic_default 87 | assert (object = BasicEnum.create) 88 | assert_nil object.value, 89 | "Enum columns without explicit default, default to null if allowed" 90 | assert !object.new_record? 91 | end 92 | 93 | def test_create_basic_good 94 | assert (object = BasicEnum.create(:value => :good)) 95 | assert_equal :good, object.value 96 | assert !object.new_record? 97 | assert (object = BasicEnum.create(:value => :working)) 98 | assert_equal :working, object.value 99 | assert !object.new_record? 100 | end 101 | 102 | def test_create_basic_null 103 | assert (object = BasicEnum.create(:value => nil)) 104 | assert_nil object.value 105 | assert !object.new_record? 106 | end 107 | 108 | def test_create_basic_bad 109 | assert (object = BasicEnum.create(:value => :bad)) 110 | assert object.new_record? 111 | end 112 | 113 | # Basic w/ Default 114 | 115 | ###################################################################### 116 | 117 | def test_create_basic_wd_default 118 | assert (object = BasicDefaultEnum.create) 119 | assert_equal :working, object.value, "Explicit default ignored columns" 120 | assert !object.new_record? 121 | end 122 | 123 | def test_create_basic_wd_good 124 | assert (object = BasicDefaultEnum.create(:value => :good)) 125 | assert_equal :good, object.value 126 | assert !object.new_record? 127 | assert (object = BasicDefaultEnum.create(:value => :working)) 128 | assert_equal :working, object.value 129 | assert !object.new_record? 130 | end 131 | 132 | def test_create_basic_wd_null 133 | assert (object = BasicDefaultEnum.create(:value => nil)) 134 | assert_nil object.value 135 | assert !object.new_record? 136 | end 137 | 138 | def test_create_basic_wd_bad 139 | assert (object = BasicDefaultEnum.create(:value => :bad)) 140 | assert object.new_record? 141 | end 142 | 143 | 144 | 145 | # Nonnull 146 | 147 | ###################################################################### 148 | 149 | def test_create_nonnull_default 150 | assert (object = NonnullEnum.create) 151 | # assert_equal :good, object.value, 152 | # "Enum columns without explicit default, default to first value if null not allowed" 153 | assert object.new_record? 154 | end 155 | 156 | def test_create_nonnull_good 157 | assert (object = NonnullEnum.create(:value => :good)) 158 | assert_equal :good, object.value 159 | assert !object.new_record? 160 | assert (object = NonnullEnum.create(:value => :working)) 161 | assert_equal :working, object.value 162 | assert !object.new_record? 163 | end 164 | 165 | def test_create_nonnull_null 166 | assert (object = NonnullEnum.create(:value => nil)) 167 | assert object.new_record? 168 | end 169 | 170 | def test_create_nonnull_bad 171 | assert (object = NonnullEnum.create(:value => :bad)) 172 | assert object.new_record? 173 | end 174 | 175 | # Nonnull w/ Default 176 | 177 | ###################################################################### 178 | 179 | def test_create_nonnull_wd_default 180 | assert (object = NonnullDefaultEnum.create) 181 | assert_equal :working, object.value 182 | assert !object.new_record? 183 | end 184 | 185 | def test_create_nonnull_wd_good 186 | assert (object = NonnullDefaultEnum.create(:value => :good)) 187 | assert_equal :good, object.value 188 | assert !object.new_record? 189 | assert (object = NonnullDefaultEnum.create(:value => :working)) 190 | assert_equal :working, object.value 191 | assert !object.new_record? 192 | end 193 | 194 | def test_create_nonnull_wd_null 195 | assert (object = NonnullDefaultEnum.create(:value => nil)) 196 | assert object.new_record? 197 | end 198 | 199 | def test_create_nonnull_wd_bad 200 | assert (object = NonnullDefaultEnum.create(:value => :bad)) 201 | assert object.new_record? 202 | end 203 | 204 | def test_quoting 205 | value = Enumeration.send(:sanitize_sql, ["value = ? ", :"'" ] ) 206 | assert_equal "value = '\\'' ", value 207 | end 208 | end 209 | --------------------------------------------------------------------------------