activerecord-string-enum 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +35 -0
- data/Rakefile +2 -0
- data/activerecord-string-enum.gemspec +29 -0
- data/lib/active_record/string_enum.rb +179 -0
- data/lib/active_record/string_enum/version.rb +5 -0
- data/test/cases/helper.rb +209 -0
- data/test/cases/str_enum_test.rb +295 -0
- data/test/cases/test_case.rb +54 -0
- data/test/config.rb +5 -0
- data/test/config.yml +12 -0
- data/test/fixtures/books.yml +5 -0
- data/test/models/arunit2_model.rb +3 -0
- data/test/models/book.rb +12 -0
- data/test/schema/schema.rb +7 -0
- data/test/support/config.rb +34 -0
- data/test/support/connection.rb +20 -0
- data/test/support/connection_helper.rb +14 -0
- data/test/support/ddl_helper.rb +8 -0
- data/test/support/schema_dumping_helper.rb +20 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 119c5e3985161d99305ceaffd9626b89e3f53e9b
|
4
|
+
data.tar.gz: c1ea2773a67525dd178650aba25b3253886f139a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cfe8875234b49015f76bd59272f2dc94400ebdeddd9c34f828017463ec842a8a781e5dbb367dba15a179decc10fd10f25d0b60e69c64071a8954ccd00df34dc1
|
7
|
+
data.tar.gz: 1d30978531fb961b3b6fd0fc6ee38dd7cefc1f99d21f57c49af114f7b567d4a0f4e929c2fd2fd840c1a92c34f112a5b185b5d31c9de8178457e74b232e5cbdbe
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2015 Phusion V.O.F.
|
2
|
+
Copyright (c) 2004-2015 David Heinemeier Hansson
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Activerecord::StringEnum
|
2
|
+
|
3
|
+
Make ActiveRecord 4's Enum store as strings instead of integers.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'activerecord-string-enum'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install activerecord-string-enum
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
class Task < ActiveRecord::Base
|
24
|
+
extend ActiveRecord::StringEnum
|
25
|
+
|
26
|
+
str_enum :status, [:running, :finished]
|
27
|
+
end
|
28
|
+
|
29
|
+
## Contributing
|
30
|
+
|
31
|
+
1. Fork it ( https://github.com/phusion/activerecord-string-enum/fork )
|
32
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
33
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
34
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
35
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_record/string_enum/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "activerecord-string-enum"
|
8
|
+
spec.version = ActiveRecord::StringEnum::VERSION
|
9
|
+
spec.authors = ["Tinco Andringa"]
|
10
|
+
spec.email = ["tinco@phusion.nl"]
|
11
|
+
spec.summary = %q{Make ActiveRecord 4's Enum store as strings instead of integers.}
|
12
|
+
spec.description = %q{Make ActiveRecord 4's Enum store as strings instead of integers.}
|
13
|
+
spec.homepage = "https://github.com/phusion/activerecord-string-enum"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "activesupport", "4.2.0"
|
24
|
+
spec.add_development_dependency "activerecord", "4.2.0"
|
25
|
+
spec.add_development_dependency "erubis"
|
26
|
+
spec.add_development_dependency "sqlite3"
|
27
|
+
spec.add_development_dependency "mocha"
|
28
|
+
spec.add_development_dependency "simplecov"
|
29
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require "active_record/string_enum/version"
|
2
|
+
require 'active_record/type/value'
|
3
|
+
require 'active_support/core_ext/object/deep_dup'
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
# Declare an enum attribute where the values map to integers in the database,
|
7
|
+
# but can be queried by name. Example:
|
8
|
+
#
|
9
|
+
# class Conversation < ActiveRecord::Base
|
10
|
+
# enum status: [ :active, :archived ]
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # conversation.update! status: :active
|
14
|
+
# conversation.active!
|
15
|
+
# conversation.active? # => true
|
16
|
+
# conversation.status # => "active"
|
17
|
+
#
|
18
|
+
# # conversation.update! status: :archived
|
19
|
+
# conversation.archived!
|
20
|
+
# conversation.archived? # => true
|
21
|
+
# conversation.status # => "archived"
|
22
|
+
#
|
23
|
+
# # conversation.update! status: :archived
|
24
|
+
# conversation.status = "archived"
|
25
|
+
#
|
26
|
+
# # conversation.update! status: nil
|
27
|
+
# conversation.status = nil
|
28
|
+
# conversation.status.nil? # => true
|
29
|
+
# conversation.status # => nil
|
30
|
+
#
|
31
|
+
# Scopes based on the allowed values of the enum field will be provided
|
32
|
+
# as well. With the above example:
|
33
|
+
#
|
34
|
+
# Conversation.active
|
35
|
+
# Conversation.archived
|
36
|
+
#
|
37
|
+
# Of course, you can also query them directly if the scopes doesn't fit your
|
38
|
+
# needs:
|
39
|
+
#
|
40
|
+
# Conversation.where(status: [:active, :archived])
|
41
|
+
# Conversation.where.not(status: :active)
|
42
|
+
#
|
43
|
+
# You can set the default value from the database declaration, like:
|
44
|
+
#
|
45
|
+
# create_table :conversations do |t|
|
46
|
+
# t.column :status, :string, default: :active
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# In rare circumstances you might need to access the mapping directly.
|
50
|
+
# The mappings are exposed through a class method with the pluralized attribute
|
51
|
+
# name.
|
52
|
+
#
|
53
|
+
# Conversation.statuses[0] # => :active
|
54
|
+
# Conversation.statuses[1] # => :archived
|
55
|
+
#
|
56
|
+
|
57
|
+
module StringEnum
|
58
|
+
def self.extended(base) # :nodoc:
|
59
|
+
base.class_attribute(:defined_str_enums)
|
60
|
+
base.defined_str_enums = {}
|
61
|
+
end
|
62
|
+
|
63
|
+
def inherited(base) # :nodoc:
|
64
|
+
base.defined_str_enums = defined_str_enums.deep_dup
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
68
|
+
class EnumType < Type::Value
|
69
|
+
def initialize(name, mapping)
|
70
|
+
@name = name
|
71
|
+
@mapping = mapping
|
72
|
+
end
|
73
|
+
|
74
|
+
def cast(value)
|
75
|
+
return if value.blank?
|
76
|
+
|
77
|
+
if mapping.include?(value.to_s)
|
78
|
+
value
|
79
|
+
else
|
80
|
+
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def deserialize(value)
|
85
|
+
return if value.nil?
|
86
|
+
cast(value)
|
87
|
+
end
|
88
|
+
|
89
|
+
def serialize(value)
|
90
|
+
value.to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
attr_reader :name, :mapping
|
96
|
+
end
|
97
|
+
|
98
|
+
def str_enum(definitions)
|
99
|
+
klass = self
|
100
|
+
definitions.each do |name, values|
|
101
|
+
# statuses = [ ]
|
102
|
+
enum_values = values.map(&:to_s)
|
103
|
+
name = name.to_sym
|
104
|
+
|
105
|
+
# def self.statuses statuses end
|
106
|
+
detect_enum_conflict!(name, name.to_s.pluralize, true)
|
107
|
+
klass.singleton_class.send(:define_method, name.to_s.pluralize) { values }
|
108
|
+
|
109
|
+
detect_enum_conflict!(name, name)
|
110
|
+
detect_enum_conflict!(name, "#{name}=")
|
111
|
+
|
112
|
+
# TODO: in Rails 4.2.1 this will be legal:
|
113
|
+
# attribute name, EnumType.new(name, enum_values)
|
114
|
+
# instead of the next two lines:
|
115
|
+
type = EnumType.new(name, enum_values)
|
116
|
+
define_method("#{name}=") { |value| self[name] = type.cast(value) }
|
117
|
+
|
118
|
+
_enum_methods_module.module_eval do
|
119
|
+
enum_values.each do |value|
|
120
|
+
# def active?() status == :active end
|
121
|
+
klass.send(:detect_enum_conflict!, name, "#{value}?")
|
122
|
+
define_method("#{value}?") { self[name] == value }
|
123
|
+
|
124
|
+
# def active!() update! status: :active end
|
125
|
+
klass.send(:detect_enum_conflict!, name, "#{value}!")
|
126
|
+
define_method("#{value}!") { update! name => value }
|
127
|
+
|
128
|
+
# scope :active, -> { where status: :active }
|
129
|
+
klass.send(:detect_enum_conflict!, name, value, true)
|
130
|
+
klass.scope value, -> { klass.where name => value }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
defined_str_enums[name.to_s] = enum_values
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
private
|
138
|
+
def _enum_methods_module
|
139
|
+
@_enum_methods_module ||= begin
|
140
|
+
mod = Module.new
|
141
|
+
include mod
|
142
|
+
mod
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
ENUM_CONFLICT_MESSAGE = \
|
147
|
+
"You tried to define an enum named \"%{enum}\" on the model \"%{klass}\", but " \
|
148
|
+
"this will generate a %{type} method \"%{method}\", which is already defined " \
|
149
|
+
"by %{source}."
|
150
|
+
|
151
|
+
def detect_enum_conflict!(enum_name, method_name, klass_method = false)
|
152
|
+
if klass_method && dangerous_class_method?(method_name)
|
153
|
+
raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
|
154
|
+
enum: enum_name,
|
155
|
+
klass: self.name,
|
156
|
+
type: 'class',
|
157
|
+
method: method_name,
|
158
|
+
source: 'Active Record'
|
159
|
+
}
|
160
|
+
elsif !klass_method && dangerous_attribute_method?(method_name)
|
161
|
+
raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
|
162
|
+
enum: enum_name,
|
163
|
+
klass: self.name,
|
164
|
+
type: 'instance',
|
165
|
+
method: method_name,
|
166
|
+
source: 'Active Record'
|
167
|
+
}
|
168
|
+
elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
|
169
|
+
raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
|
170
|
+
enum: enum_name,
|
171
|
+
klass: self.name,
|
172
|
+
type: 'instance',
|
173
|
+
method: method_name,
|
174
|
+
source: 'another enum'
|
175
|
+
}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'config'
|
5
|
+
|
6
|
+
require 'active_support/testing/autorun'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
require 'active_record'
|
10
|
+
require 'cases/test_case'
|
11
|
+
require 'active_support/dependencies'
|
12
|
+
require 'active_support/logger'
|
13
|
+
require 'active_support/core_ext/string/strip'
|
14
|
+
|
15
|
+
require 'support/config'
|
16
|
+
require 'support/connection'
|
17
|
+
|
18
|
+
# TODO: Move all these random hacks into the ARTest namespace and into the support/ dir
|
19
|
+
|
20
|
+
Thread.abort_on_exception = true
|
21
|
+
|
22
|
+
# Show backtraces for deprecated behavior for quicker cleanup.
|
23
|
+
ActiveSupport::Deprecation.debug = true
|
24
|
+
|
25
|
+
# Disable available locale checks to avoid warnings running the test suite.
|
26
|
+
I18n.enforce_available_locales = false
|
27
|
+
|
28
|
+
# Enable raise errors in after_commit and after_rollback.
|
29
|
+
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
30
|
+
|
31
|
+
# Connect to the database
|
32
|
+
ARTest.connect
|
33
|
+
|
34
|
+
# Quote "type" if it's a reserved word for the current connection.
|
35
|
+
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
|
36
|
+
|
37
|
+
def current_adapter?(*types)
|
38
|
+
types.any? do |type|
|
39
|
+
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
40
|
+
ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters.const_get(type))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def in_memory_db?
|
45
|
+
current_adapter?(:SQLite3Adapter) &&
|
46
|
+
ActiveRecord::Base.connection_pool.spec.config[:database] == ":memory:"
|
47
|
+
end
|
48
|
+
|
49
|
+
def mysql_56?
|
50
|
+
current_adapter?(:Mysql2Adapter) &&
|
51
|
+
ActiveRecord::Base.connection.send(:version).join(".") >= "5.6.0"
|
52
|
+
end
|
53
|
+
|
54
|
+
def mysql_enforcing_gtid_consistency?
|
55
|
+
current_adapter?(:MysqlAdapter, :Mysql2Adapter) && 'ON' == ActiveRecord::Base.connection.show_variable('enforce_gtid_consistency')
|
56
|
+
end
|
57
|
+
|
58
|
+
def supports_savepoints?
|
59
|
+
ActiveRecord::Base.connection.supports_savepoints?
|
60
|
+
end
|
61
|
+
|
62
|
+
def with_env_tz(new_tz = 'US/Eastern')
|
63
|
+
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
|
64
|
+
yield
|
65
|
+
ensure
|
66
|
+
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
|
67
|
+
end
|
68
|
+
|
69
|
+
def with_timezone_config(cfg)
|
70
|
+
verify_default_timezone_config
|
71
|
+
|
72
|
+
old_default_zone = ActiveRecord::Base.default_timezone
|
73
|
+
old_awareness = ActiveRecord::Base.time_zone_aware_attributes
|
74
|
+
old_zone = Time.zone
|
75
|
+
|
76
|
+
if cfg.has_key?(:default)
|
77
|
+
ActiveRecord::Base.default_timezone = cfg[:default]
|
78
|
+
end
|
79
|
+
if cfg.has_key?(:aware_attributes)
|
80
|
+
ActiveRecord::Base.time_zone_aware_attributes = cfg[:aware_attributes]
|
81
|
+
end
|
82
|
+
if cfg.has_key?(:zone)
|
83
|
+
Time.zone = cfg[:zone]
|
84
|
+
end
|
85
|
+
yield
|
86
|
+
ensure
|
87
|
+
ActiveRecord::Base.default_timezone = old_default_zone
|
88
|
+
ActiveRecord::Base.time_zone_aware_attributes = old_awareness
|
89
|
+
Time.zone = old_zone
|
90
|
+
end
|
91
|
+
|
92
|
+
# This method makes sure that tests don't leak global state related to time zones.
|
93
|
+
EXPECTED_ZONE = nil
|
94
|
+
EXPECTED_DEFAULT_TIMEZONE = :utc
|
95
|
+
EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES = false
|
96
|
+
def verify_default_timezone_config
|
97
|
+
if Time.zone != EXPECTED_ZONE
|
98
|
+
$stderr.puts <<-MSG
|
99
|
+
\n#{self}
|
100
|
+
Global state `Time.zone` was leaked.
|
101
|
+
Expected: #{EXPECTED_ZONE}
|
102
|
+
Got: #{Time.zone}
|
103
|
+
MSG
|
104
|
+
end
|
105
|
+
if ActiveRecord::Base.default_timezone != EXPECTED_DEFAULT_TIMEZONE
|
106
|
+
$stderr.puts <<-MSG
|
107
|
+
\n#{self}
|
108
|
+
Global state `ActiveRecord::Base.default_timezone` was leaked.
|
109
|
+
Expected: #{EXPECTED_DEFAULT_TIMEZONE}
|
110
|
+
Got: #{ActiveRecord::Base.default_timezone}
|
111
|
+
MSG
|
112
|
+
end
|
113
|
+
if ActiveRecord::Base.time_zone_aware_attributes != EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES
|
114
|
+
$stderr.puts <<-MSG
|
115
|
+
\n#{self}
|
116
|
+
Global state `ActiveRecord::Base.time_zone_aware_attributes` was leaked.
|
117
|
+
Expected: #{EXPECTED_TIME_ZONE_AWARE_ATTRIBUTES}
|
118
|
+
Got: #{ActiveRecord::Base.time_zone_aware_attributes}
|
119
|
+
MSG
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def enable_extension!(extension, connection)
|
124
|
+
return false unless connection.supports_extensions?
|
125
|
+
return connection.reconnect! if connection.extension_enabled?(extension)
|
126
|
+
|
127
|
+
connection.enable_extension extension
|
128
|
+
connection.commit_db_transaction
|
129
|
+
connection.reconnect!
|
130
|
+
end
|
131
|
+
|
132
|
+
def disable_extension!(extension, connection)
|
133
|
+
return false unless connection.supports_extensions?
|
134
|
+
return true unless connection.extension_enabled?(extension)
|
135
|
+
|
136
|
+
connection.disable_extension extension
|
137
|
+
connection.reconnect!
|
138
|
+
end
|
139
|
+
|
140
|
+
class ActiveSupport::TestCase
|
141
|
+
include ActiveRecord::TestFixtures
|
142
|
+
|
143
|
+
self.fixture_path = FIXTURES_ROOT
|
144
|
+
self.use_instantiated_fixtures = false
|
145
|
+
self.use_transactional_fixtures = true
|
146
|
+
|
147
|
+
def create_fixtures(*fixture_set_names, &block)
|
148
|
+
ActiveRecord::FixtureSet.create_fixtures(ActiveSupport::TestCase.fixture_path, fixture_set_names, fixture_class_names, &block)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def load_schema
|
153
|
+
# silence verbose schema loading
|
154
|
+
original_stdout = $stdout
|
155
|
+
$stdout = StringIO.new
|
156
|
+
|
157
|
+
adapter_name = ActiveRecord::Base.connection.adapter_name.downcase
|
158
|
+
adapter_specific_schema_file = SCHEMA_ROOT + "/#{adapter_name}_specific_schema.rb"
|
159
|
+
|
160
|
+
load SCHEMA_ROOT + "/schema.rb"
|
161
|
+
|
162
|
+
if File.exist?(adapter_specific_schema_file)
|
163
|
+
load adapter_specific_schema_file
|
164
|
+
end
|
165
|
+
ensure
|
166
|
+
$stdout = original_stdout
|
167
|
+
end
|
168
|
+
|
169
|
+
load_schema
|
170
|
+
|
171
|
+
class SQLSubscriber
|
172
|
+
attr_reader :logged
|
173
|
+
attr_reader :payloads
|
174
|
+
|
175
|
+
def initialize
|
176
|
+
@logged = []
|
177
|
+
@payloads = []
|
178
|
+
end
|
179
|
+
|
180
|
+
def start(name, id, payload)
|
181
|
+
@payloads << payload
|
182
|
+
@logged << [payload[:sql].squish, payload[:name], payload[:binds]]
|
183
|
+
end
|
184
|
+
|
185
|
+
def finish(name, id, payload); end
|
186
|
+
end
|
187
|
+
|
188
|
+
module InTimeZone
|
189
|
+
private
|
190
|
+
|
191
|
+
def in_time_zone(zone)
|
192
|
+
old_zone = Time.zone
|
193
|
+
old_tz = ActiveRecord::Base.time_zone_aware_attributes
|
194
|
+
|
195
|
+
Time.zone = zone ? ActiveSupport::TimeZone[zone] : nil
|
196
|
+
ActiveRecord::Base.time_zone_aware_attributes = !zone.nil?
|
197
|
+
yield
|
198
|
+
ensure
|
199
|
+
Time.zone = old_zone
|
200
|
+
ActiveRecord::Base.time_zone_aware_attributes = old_tz
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
require 'mocha/setup' # FIXME: stop using mocha
|
205
|
+
|
206
|
+
# FIXME: we have tests that depend on run order, we should fix that and
|
207
|
+
# remove this method call.
|
208
|
+
require 'active_support/test_case'
|
209
|
+
ActiveSupport::TestCase.test_order = :sorted
|
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'active_record/string_enum'
|
2
|
+
require 'cases/helper'
|
3
|
+
require 'models/book'
|
4
|
+
|
5
|
+
class EnumTest < ActiveRecord::TestCase
|
6
|
+
fixtures :books
|
7
|
+
|
8
|
+
setup do
|
9
|
+
@book = books(:awdr)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "query state by predicate" do
|
13
|
+
assert @book.proposed?
|
14
|
+
assert_not @book.written?
|
15
|
+
assert_not @book.published?
|
16
|
+
|
17
|
+
assert @book.unread?
|
18
|
+
end
|
19
|
+
|
20
|
+
test "query state with strings" do
|
21
|
+
assert_equal "proposed", @book.status
|
22
|
+
assert_equal "unread", @book.read_status
|
23
|
+
end
|
24
|
+
|
25
|
+
test "find via scope" do
|
26
|
+
assert_equal @book, Book.proposed.first
|
27
|
+
assert_equal @book, Book.unread.first
|
28
|
+
end
|
29
|
+
|
30
|
+
test "update by declaration" do
|
31
|
+
@book.written!
|
32
|
+
assert @book.written?
|
33
|
+
end
|
34
|
+
|
35
|
+
test "update by setter" do
|
36
|
+
@book.update! status: :written
|
37
|
+
assert @book.written?
|
38
|
+
end
|
39
|
+
|
40
|
+
test "enum methods are overwritable" do
|
41
|
+
assert_equal "do publish work...", @book.published!
|
42
|
+
assert @book.published?
|
43
|
+
end
|
44
|
+
|
45
|
+
test "direct assignment" do
|
46
|
+
@book.status = :written
|
47
|
+
assert @book.written?
|
48
|
+
end
|
49
|
+
|
50
|
+
test "assign string value" do
|
51
|
+
@book.status = "written"
|
52
|
+
assert @book.written?
|
53
|
+
end
|
54
|
+
|
55
|
+
test "enum changed attributes" do
|
56
|
+
old_status = @book.status
|
57
|
+
@book.status = :published
|
58
|
+
assert_equal old_status, @book.changed_attributes[:status]
|
59
|
+
end
|
60
|
+
|
61
|
+
test "enum changes" do
|
62
|
+
old_status = @book.status
|
63
|
+
@book.status = :published
|
64
|
+
assert_equal [old_status, 'published'], @book.changes[:status]
|
65
|
+
end
|
66
|
+
|
67
|
+
test "enum attribute was" do
|
68
|
+
old_status = @book.status
|
69
|
+
@book.status = :published
|
70
|
+
assert_equal old_status, @book.attribute_was(:status)
|
71
|
+
end
|
72
|
+
|
73
|
+
test "enum attribute changed" do
|
74
|
+
@book.status = :published
|
75
|
+
assert @book.attribute_changed?(:status)
|
76
|
+
end
|
77
|
+
|
78
|
+
test "enum attribute changed to" do
|
79
|
+
@book.status = :published
|
80
|
+
assert @book.attribute_changed?(:status, to: 'published')
|
81
|
+
end
|
82
|
+
|
83
|
+
test "enum attribute changed from" do
|
84
|
+
old_status = @book.status
|
85
|
+
@book.status = :published
|
86
|
+
assert @book.attribute_changed?(:status, from: old_status)
|
87
|
+
end
|
88
|
+
|
89
|
+
test "enum attribute changed from old status to new status" do
|
90
|
+
old_status = @book.status
|
91
|
+
@book.status = :published
|
92
|
+
assert @book.attribute_changed?(:status, from: old_status, to: 'published')
|
93
|
+
end
|
94
|
+
|
95
|
+
test "enum didn't change" do
|
96
|
+
old_status = @book.status
|
97
|
+
@book.status = old_status
|
98
|
+
assert_not @book.attribute_changed?(:status)
|
99
|
+
end
|
100
|
+
|
101
|
+
test "persist changes that are dirty" do
|
102
|
+
@book.status = :published
|
103
|
+
assert @book.attribute_changed?(:status)
|
104
|
+
@book.status = :written
|
105
|
+
assert @book.attribute_changed?(:status)
|
106
|
+
end
|
107
|
+
|
108
|
+
test "reverted changes that are not dirty" do
|
109
|
+
old_status = @book.status
|
110
|
+
@book.status = :published
|
111
|
+
assert @book.attribute_changed?(:status)
|
112
|
+
@book.status = old_status
|
113
|
+
assert_not @book.attribute_changed?(:status)
|
114
|
+
end
|
115
|
+
|
116
|
+
test "reverted changes are not dirty going from nil to value and back" do
|
117
|
+
book = Book.create!(nullable_status: nil)
|
118
|
+
|
119
|
+
book.nullable_status = :married
|
120
|
+
assert book.attribute_changed?(:nullable_status)
|
121
|
+
|
122
|
+
book.nullable_status = nil
|
123
|
+
assert_not book.attribute_changed?(:nullable_status)
|
124
|
+
end
|
125
|
+
|
126
|
+
test "assign non existing value raises an error" do
|
127
|
+
e = assert_raises(ArgumentError) do
|
128
|
+
@book.status = :unknown
|
129
|
+
end
|
130
|
+
assert_equal "'unknown' is not a valid status", e.message
|
131
|
+
end
|
132
|
+
|
133
|
+
test "assign nil value" do
|
134
|
+
@book.status = nil
|
135
|
+
assert @book.status.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
test "assign empty string value" do
|
139
|
+
@book.status = ''
|
140
|
+
assert @book.status.nil?, "Book was blank?: #{@book.status.blank?}"
|
141
|
+
end
|
142
|
+
|
143
|
+
test "assign long empty string value" do
|
144
|
+
@book.status = ' '
|
145
|
+
assert @book.status.nil?
|
146
|
+
end
|
147
|
+
|
148
|
+
test "constant to access the mapping" do
|
149
|
+
assert_equal Book.statuses[0], :proposed
|
150
|
+
assert_equal Book.statuses[1], :written
|
151
|
+
assert_equal Book.statuses[2], :published
|
152
|
+
end
|
153
|
+
|
154
|
+
test "building new objects with enum scopes" do
|
155
|
+
assert Book.written.build.written?
|
156
|
+
assert Book.read.build.read?
|
157
|
+
end
|
158
|
+
|
159
|
+
test "creating new objects with enum scopes" do
|
160
|
+
assert Book.written.create.written?
|
161
|
+
assert Book.read.create.read?
|
162
|
+
end
|
163
|
+
|
164
|
+
test "_before_type_cast returns the enum label (required for form fields)" do
|
165
|
+
assert_equal "proposed", @book.status_before_type_cast
|
166
|
+
end
|
167
|
+
|
168
|
+
test "reserved enum names" do
|
169
|
+
klass = Class.new(ActiveRecord::Base) do
|
170
|
+
self.table_name = "books"
|
171
|
+
enum status: [:proposed, :written, :published]
|
172
|
+
end
|
173
|
+
|
174
|
+
conflicts = [
|
175
|
+
:column, # generates class method .columns, which conflicts with an AR method
|
176
|
+
:logger, # generates #logger, which conflicts with an AR method
|
177
|
+
:attributes, # generates #attributes=, which conflicts with an AR method
|
178
|
+
]
|
179
|
+
|
180
|
+
conflicts.each_with_index do |name, i|
|
181
|
+
assert_raises(ArgumentError, "enum name `#{name}` should not be allowed") do
|
182
|
+
klass.class_eval { enum name => ["value_#{i}"] }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
test "reserved enum values" do
|
188
|
+
klass = Class.new(ActiveRecord::Base) do
|
189
|
+
self.table_name = "books"
|
190
|
+
enum status: [:proposed, :written, :published]
|
191
|
+
end
|
192
|
+
|
193
|
+
conflicts = [
|
194
|
+
:new, # generates a scope that conflicts with an AR class method
|
195
|
+
:valid, # generates #valid?, which conflicts with an AR method
|
196
|
+
:save, # generates #save!, which conflicts with an AR method
|
197
|
+
:proposed, # same value as an existing enum
|
198
|
+
:public, :private, :protected, # some important methods on Module and Class
|
199
|
+
:name, :parent, :superclass
|
200
|
+
]
|
201
|
+
|
202
|
+
conflicts.each_with_index do |value, i|
|
203
|
+
assert_raises(ArgumentError, "enum value `#{value}` should not be allowed") do
|
204
|
+
klass.class_eval { enum "status_#{i}" => [value] }
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
test "overriding enum method should not raise" do
|
210
|
+
assert_nothing_raised do
|
211
|
+
Class.new(ActiveRecord::Base) do
|
212
|
+
self.table_name = "books"
|
213
|
+
|
214
|
+
def published!
|
215
|
+
super
|
216
|
+
"do publish work..."
|
217
|
+
end
|
218
|
+
|
219
|
+
enum status: [:proposed, :written, :published]
|
220
|
+
|
221
|
+
def written!
|
222
|
+
super
|
223
|
+
"do written work..."
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
test "validate uniqueness" do
|
230
|
+
klass = Class.new(ActiveRecord::Base) do
|
231
|
+
extend ActiveRecord::StringEnum
|
232
|
+
def self.name; 'Book'; end
|
233
|
+
str_enum status: [:proposed, :written]
|
234
|
+
validates_uniqueness_of :status
|
235
|
+
end
|
236
|
+
klass.delete_all
|
237
|
+
klass.create!(status: "proposed")
|
238
|
+
book = klass.new(status: "written")
|
239
|
+
assert book.valid?
|
240
|
+
book.status = "proposed"
|
241
|
+
assert_not book.valid?
|
242
|
+
end
|
243
|
+
|
244
|
+
test "validate inclusion of value in array" do
|
245
|
+
klass = Class.new(ActiveRecord::Base) do
|
246
|
+
extend ActiveRecord::StringEnum
|
247
|
+
def self.name; 'Book'; end
|
248
|
+
str_enum status: [:proposed, :written]
|
249
|
+
validates_inclusion_of :status, in: ["written"]
|
250
|
+
end
|
251
|
+
klass.delete_all
|
252
|
+
invalid_book = klass.new(status: "proposed")
|
253
|
+
assert_not invalid_book.valid?
|
254
|
+
valid_book = klass.new(status: "written")
|
255
|
+
assert valid_book.valid?
|
256
|
+
end
|
257
|
+
|
258
|
+
test "enums are distinct per class" do
|
259
|
+
klass1 = Class.new(ActiveRecord::Base) do
|
260
|
+
extend ActiveRecord::StringEnum
|
261
|
+
self.table_name = "books"
|
262
|
+
str_enum status: [:proposed, :written]
|
263
|
+
end
|
264
|
+
|
265
|
+
klass2 = Class.new(ActiveRecord::Base) do
|
266
|
+
extend ActiveRecord::StringEnum
|
267
|
+
self.table_name = "books"
|
268
|
+
str_enum status: [:drafted, :uploaded]
|
269
|
+
end
|
270
|
+
|
271
|
+
book1 = klass1.proposed.create!
|
272
|
+
book1.status = :written
|
273
|
+
assert_equal ['proposed', 'written'], book1.status_change
|
274
|
+
|
275
|
+
book2 = klass2.drafted.create!
|
276
|
+
book2.status = :uploaded
|
277
|
+
assert_equal ['drafted', 'uploaded'], book2.status_change
|
278
|
+
end
|
279
|
+
|
280
|
+
test "enums are inheritable" do
|
281
|
+
subklass1 = Class.new(Book)
|
282
|
+
|
283
|
+
subklass2 = Class.new(Book) do
|
284
|
+
str_enum status: [:drafted, :uploaded]
|
285
|
+
end
|
286
|
+
|
287
|
+
book1 = subklass1.proposed.create!
|
288
|
+
book1.status = :written
|
289
|
+
assert_equal ['proposed', 'written'], book1.status_change
|
290
|
+
|
291
|
+
book2 = subklass2.drafted.create!
|
292
|
+
book2.status = :uploaded
|
293
|
+
assert_equal ['drafted', 'uploaded'], book2.status_change
|
294
|
+
end
|
295
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'active_support/test_case'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
# = Active Record Test Case
|
5
|
+
#
|
6
|
+
# Defines some test assertions to test against SQL queries.
|
7
|
+
class TestCase < ActiveSupport::TestCase #:nodoc:
|
8
|
+
def teardown
|
9
|
+
SQLCounter.clear_log
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class SQLCounter
|
14
|
+
class << self
|
15
|
+
attr_accessor :ignored_sql, :log, :log_all
|
16
|
+
def clear_log; self.log = []; self.log_all = []; end
|
17
|
+
end
|
18
|
+
|
19
|
+
self.clear_log
|
20
|
+
|
21
|
+
self.ignored_sql = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/, /^BEGIN/, /^COMMIT/]
|
22
|
+
|
23
|
+
# FIXME: this needs to be refactored so specific database can add their own
|
24
|
+
# ignored SQL, or better yet, use a different notification for the queries
|
25
|
+
# instead examining the SQL content.
|
26
|
+
oracle_ignored = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from all_triggers/im, /^\s*select .* from all_constraints/im, /^\s*select .* from all_tab_cols/im]
|
27
|
+
mysql_ignored = [/^SHOW TABLES/i, /^SHOW FULL FIELDS/, /^SHOW CREATE TABLE /i, /^SHOW VARIABLES /]
|
28
|
+
postgresql_ignored = [/^\s*select\b.*\bfrom\b.*pg_namespace\b/im, /^\s*select tablename\b.*from pg_tables\b/im, /^\s*select\b.*\battname\b.*\bfrom\b.*\bpg_attribute\b/im, /^SHOW search_path/i]
|
29
|
+
sqlite3_ignored = [/^\s*SELECT name\b.*\bFROM sqlite_master/im]
|
30
|
+
|
31
|
+
[oracle_ignored, mysql_ignored, postgresql_ignored, sqlite3_ignored].each do |db_ignored_sql|
|
32
|
+
ignored_sql.concat db_ignored_sql
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :ignore
|
36
|
+
|
37
|
+
def initialize(ignore = Regexp.union(self.class.ignored_sql))
|
38
|
+
@ignore = ignore
|
39
|
+
end
|
40
|
+
|
41
|
+
def call(name, start, finish, message_id, values)
|
42
|
+
sql = values[:sql]
|
43
|
+
|
44
|
+
# FIXME: this seems bad. we should probably have a better way to indicate
|
45
|
+
# the query was cached
|
46
|
+
return if 'CACHE' == values[:name]
|
47
|
+
|
48
|
+
self.class.log_all << sql
|
49
|
+
self.class.log << sql unless ignore =~ sql
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)
|
54
|
+
end
|
data/test/config.rb
ADDED
data/test/config.yml
ADDED
data/test/models/book.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
class Book < ActiveRecord::Base
|
2
|
+
extend ActiveRecord::StringEnum
|
3
|
+
|
4
|
+
str_enum status: [:proposed, :written, :published]
|
5
|
+
str_enum read_status: [:unread, :reading, :read]
|
6
|
+
str_enum nullable_status: [:single, :married]
|
7
|
+
|
8
|
+
def published!
|
9
|
+
super
|
10
|
+
"do publish work..."
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erubis'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module ARTest
|
7
|
+
class << self
|
8
|
+
def config
|
9
|
+
@config ||= read_config
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def config_file
|
15
|
+
Pathname.new(ENV['ARCONFIG'] || TEST_ROOT + '/config.yml')
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_config
|
19
|
+
expand_config(YAML.load_file(config_file))
|
20
|
+
end
|
21
|
+
|
22
|
+
def expand_config(config)
|
23
|
+
config['connections'].each do |adapter, connection|
|
24
|
+
dbs = [['arunit', 'activerecord_unittest'], ['arunit2', 'activerecord_unittest2']]
|
25
|
+
dbs.each do |name, dbname|
|
26
|
+
connection[name]['database'] ||= dbname
|
27
|
+
connection[name]['adapter'] ||= adapter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
config
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'models/arunit2_model'
|
2
|
+
require 'active_support/logger'
|
3
|
+
|
4
|
+
module ARTest
|
5
|
+
def self.connection_name
|
6
|
+
ENV['ARCONN'] || config['default_connection']
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.connection_config
|
10
|
+
config['connections'][connection_name]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.connect
|
14
|
+
puts "Using #{connection_name}"
|
15
|
+
ActiveRecord::Base.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024)
|
16
|
+
ActiveRecord::Base.configurations = connection_config
|
17
|
+
ActiveRecord::Base.establish_connection :arunit
|
18
|
+
ARUnit2Model.establish_connection :arunit2
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ConnectionHelper
|
2
|
+
def run_without_connection
|
3
|
+
original_connection = ActiveRecord::Base.remove_connection
|
4
|
+
yield original_connection
|
5
|
+
ensure
|
6
|
+
ActiveRecord::Base.establish_connection(original_connection)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Used to drop all cache query plans in tests.
|
10
|
+
def reset_connection
|
11
|
+
original_connection = ActiveRecord::Base.remove_connection
|
12
|
+
ActiveRecord::Base.establish_connection(original_connection)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SchemaDumpingHelper
|
2
|
+
def dump_table_schema(table, connection = ActiveRecord::Base.connection)
|
3
|
+
old_ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
4
|
+
ActiveRecord::SchemaDumper.ignore_tables = connection.tables - [table]
|
5
|
+
stream = StringIO.new
|
6
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
7
|
+
stream.string
|
8
|
+
ensure
|
9
|
+
ActiveRecord::SchemaDumper.ignore_tables = old_ignore_tables
|
10
|
+
end
|
11
|
+
|
12
|
+
def dump_all_table_schema(ignore_tables)
|
13
|
+
old_ignore_tables, ActiveRecord::SchemaDumper.ignore_tables = ActiveRecord::SchemaDumper.ignore_tables, ignore_tables
|
14
|
+
stream = StringIO.new
|
15
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
16
|
+
stream.string
|
17
|
+
ensure
|
18
|
+
ActiveRecord::SchemaDumper.ignore_tables = old_ignore_tables
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-string-enum
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tinco Andringa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 4.2.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 4.2.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activerecord
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 4.2.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 4.2.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: erubis
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: Make ActiveRecord 4's Enum store as strings instead of integers.
|
126
|
+
email:
|
127
|
+
- tinco@phusion.nl
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- LICENSE.txt
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- activerecord-string-enum.gemspec
|
138
|
+
- lib/active_record/string_enum.rb
|
139
|
+
- lib/active_record/string_enum/version.rb
|
140
|
+
- test/cases/helper.rb
|
141
|
+
- test/cases/str_enum_test.rb
|
142
|
+
- test/cases/test_case.rb
|
143
|
+
- test/config.rb
|
144
|
+
- test/config.yml
|
145
|
+
- test/fixtures/books.yml
|
146
|
+
- test/models/arunit2_model.rb
|
147
|
+
- test/models/book.rb
|
148
|
+
- test/schema/schema.rb
|
149
|
+
- test/support/config.rb
|
150
|
+
- test/support/connection.rb
|
151
|
+
- test/support/connection_helper.rb
|
152
|
+
- test/support/ddl_helper.rb
|
153
|
+
- test/support/schema_dumping_helper.rb
|
154
|
+
homepage: https://github.com/phusion/activerecord-string-enum
|
155
|
+
licenses:
|
156
|
+
- MIT
|
157
|
+
metadata: {}
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
require_paths:
|
161
|
+
- lib
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
requirements: []
|
173
|
+
rubyforge_project:
|
174
|
+
rubygems_version: 2.2.2
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: Make ActiveRecord 4's Enum store as strings instead of integers.
|
178
|
+
test_files:
|
179
|
+
- test/cases/helper.rb
|
180
|
+
- test/cases/str_enum_test.rb
|
181
|
+
- test/cases/test_case.rb
|
182
|
+
- test/config.rb
|
183
|
+
- test/config.yml
|
184
|
+
- test/fixtures/books.yml
|
185
|
+
- test/models/arunit2_model.rb
|
186
|
+
- test/models/book.rb
|
187
|
+
- test/schema/schema.rb
|
188
|
+
- test/support/config.rb
|
189
|
+
- test/support/connection.rb
|
190
|
+
- test/support/connection_helper.rb
|
191
|
+
- test/support/ddl_helper.rb
|
192
|
+
- test/support/schema_dumping_helper.rb
|
193
|
+
has_rdoc:
|