mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #41328 from kamipo/avoid-leading-_-from-reserved-options
Allow new syntax for `enum` to avoid leading `_` from reserved options
This commit is contained in:
commit
ee7cf8cf75
4 changed files with 101 additions and 24 deletions
|
@ -1,3 +1,25 @@
|
|||
* Allow new syntax for `enum` to avoid leading `_` from reserved options.
|
||||
|
||||
Before:
|
||||
|
||||
```ruby
|
||||
class Book < ActiveRecord::Base
|
||||
enum status: [ :proposed, :written ], _prefix: true, _scopes: false
|
||||
enum cover: [ :hard, :soft ], _suffix: true, _default: :hard
|
||||
end
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```ruby
|
||||
class Book < ActiveRecord::Base
|
||||
enum :status, [ :proposed, :written ], prefix: true, scopes: false
|
||||
enum :cover, [ :hard, :soft ], suffix: true, default: :hard
|
||||
end
|
||||
```
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Add `ActiveRecord::Relation#load_async`.
|
||||
|
||||
This method schedules the query to be performed asynchronously from a thread pool.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "active_support/core_ext/hash/slice"
|
||||
require "active_support/core_ext/object/deep_dup"
|
||||
|
||||
module ActiveRecord
|
||||
|
@ -7,7 +8,7 @@ module ActiveRecord
|
|||
# but can be queried by name. Example:
|
||||
#
|
||||
# class Conversation < ActiveRecord::Base
|
||||
# enum status: [ :active, :archived ]
|
||||
# enum :status, [ :active, :archived ]
|
||||
# end
|
||||
#
|
||||
# # conversation.update! status: 0
|
||||
|
@ -41,16 +42,16 @@ module ActiveRecord
|
|||
# Conversation.where(status: [:active, :archived])
|
||||
# Conversation.where.not(status: :active)
|
||||
#
|
||||
# Defining scopes can be disabled by setting +:_scopes+ to +false+.
|
||||
# Defining scopes can be disabled by setting +:scopes+ to +false+.
|
||||
#
|
||||
# class Conversation < ActiveRecord::Base
|
||||
# enum status: [ :active, :archived ], _scopes: false
|
||||
# enum :status, [ :active, :archived ], scopes: false
|
||||
# end
|
||||
#
|
||||
# You can set the default enum value by setting +:_default+, like:
|
||||
# You can set the default enum value by setting +:default+, like:
|
||||
#
|
||||
# class Conversation < ActiveRecord::Base
|
||||
# enum status: [ :active, :archived ], _default: "active"
|
||||
# enum :status, [ :active, :archived ], default: :active
|
||||
# end
|
||||
#
|
||||
# conversation = Conversation.new
|
||||
|
@ -60,7 +61,7 @@ module ActiveRecord
|
|||
# database integer with a hash:
|
||||
#
|
||||
# class Conversation < ActiveRecord::Base
|
||||
# enum status: { active: 0, archived: 1 }
|
||||
# enum :status, active: 0, archived: 1
|
||||
# end
|
||||
#
|
||||
# Note that when an array is used, the implicit mapping from the values to database
|
||||
|
@ -85,14 +86,14 @@ module ActiveRecord
|
|||
#
|
||||
# Conversation.where("status <> ?", Conversation.statuses[:archived])
|
||||
#
|
||||
# You can use the +:_prefix+ or +:_suffix+ options when you need to define
|
||||
# You can use the +:prefix+ or +:suffix+ options when you need to define
|
||||
# multiple enums with same values. If the passed value is +true+, the methods
|
||||
# are prefixed/suffixed with the name of the enum. It is also possible to
|
||||
# supply a custom value:
|
||||
#
|
||||
# class Conversation < ActiveRecord::Base
|
||||
# enum status: [:active, :archived], _suffix: true
|
||||
# enum comments_status: [:active, :inactive], _prefix: :comments
|
||||
# enum :status, [ :active, :archived ], suffix: true
|
||||
# enum :comments_status, [ :active, :inactive ], prefix: :comments
|
||||
# end
|
||||
#
|
||||
# With the above example, the bang and predicate methods along with the
|
||||
|
@ -158,17 +159,16 @@ module ActiveRecord
|
|||
attr_reader :name, :mapping
|
||||
end
|
||||
|
||||
def enum(definitions)
|
||||
prefix = definitions.delete(:_prefix)
|
||||
suffix = definitions.delete(:_suffix)
|
||||
scopes = definitions.delete(:_scopes) != false
|
||||
|
||||
default = {}
|
||||
default[:default] = definitions.delete(:_default) if definitions.key?(:_default)
|
||||
|
||||
definitions.each do |name, values|
|
||||
_enum(name, values, prefix: prefix, suffix: suffix, scopes: scopes, **default)
|
||||
def enum(name = nil, values = nil, **options)
|
||||
if name
|
||||
values, options = options, {} unless values
|
||||
return _enum(name, values, **options)
|
||||
end
|
||||
|
||||
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
|
||||
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
||||
|
||||
definitions.each { |name, values| _enum(name, values, **options) }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -639,7 +639,7 @@ class EnumTest < ActiveRecord::TestCase
|
|||
assert_equal "published", klass.new.status
|
||||
end
|
||||
|
||||
test "overloaded default" do
|
||||
test "overloaded default by :_default" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum status: [:proposed, :written, :published], _default: :published
|
||||
|
@ -648,7 +648,7 @@ class EnumTest < ActiveRecord::TestCase
|
|||
assert_equal "published", klass.new.status
|
||||
end
|
||||
|
||||
test "scopes can be disabled" do
|
||||
test "scopes can be disabled by :_scopes" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum status: [:proposed, :written], _scopes: false
|
||||
|
@ -657,6 +657,61 @@ class EnumTest < ActiveRecord::TestCase
|
|||
assert_raises(NoMethodError) { klass.proposed }
|
||||
end
|
||||
|
||||
test "overloaded default by :default" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum :status, [:proposed, :written, :published], default: :published
|
||||
end
|
||||
|
||||
assert_equal "published", klass.new.status
|
||||
end
|
||||
|
||||
test "scopes can be disabled by :scopes" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum :status, [:proposed, :written], scopes: false
|
||||
end
|
||||
|
||||
assert_raises(NoMethodError) { klass.proposed }
|
||||
end
|
||||
|
||||
test "query state by predicate with :prefix" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum :status, { proposed: 0, written: 1 }, prefix: true
|
||||
enum :last_read, { unread: 0, reading: 1, read: 2 }, prefix: :being
|
||||
end
|
||||
|
||||
book = klass.new
|
||||
assert_respond_to book, :status_proposed?
|
||||
assert_respond_to book, :being_unread?
|
||||
end
|
||||
|
||||
test "query state by predicate with :suffix" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum :cover, { hard: 0, soft: 1 }, suffix: true
|
||||
enum :difficulty, { easy: 0, medium: 1, hard: 2 }, suffix: :to_read
|
||||
end
|
||||
|
||||
book = klass.new
|
||||
assert_respond_to book, :hard_cover?
|
||||
assert_respond_to book, :easy_to_read?
|
||||
end
|
||||
|
||||
test "option names can be used as label" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "books"
|
||||
enum :status, default: 0, scopes: 1, prefix: 2, suffix: 3
|
||||
end
|
||||
|
||||
book = klass.new
|
||||
assert_predicate book, :default?
|
||||
assert_not_predicate book, :scopes?
|
||||
assert_not_predicate book, :prefix?
|
||||
assert_not_predicate book, :suffix?
|
||||
end
|
||||
|
||||
test "scopes are named like methods" do
|
||||
klass = Class.new(ActiveRecord::Base) do
|
||||
self.table_name = "cats"
|
||||
|
|
|
@ -62,7 +62,7 @@ class Order < ApplicationRecord
|
|||
belongs_to :customer
|
||||
has_and_belongs_to_many :books, join_table: 'books_orders'
|
||||
|
||||
enum status: [:shipped, :being_packed, :complete, :cancelled]
|
||||
enum :status, [:shipped, :being_packed, :complete, :cancelled]
|
||||
|
||||
scope :created_before, ->(time) { where('created_at < ?', time) }
|
||||
end
|
||||
|
@ -73,7 +73,7 @@ class Review < ApplicationRecord
|
|||
belongs_to :customer
|
||||
belongs_to :book
|
||||
|
||||
enum state: [:not_reviewed, :published, :hidden]
|
||||
enum :state, [:not_reviewed, :published, :hidden]
|
||||
end
|
||||
```
|
||||
|
||||
|
@ -1769,7 +1769,7 @@ For example, given this [`enum`][] declaration:
|
|||
|
||||
```ruby
|
||||
class Order < ApplicationRecord
|
||||
enum status: [:shipped, :being_packaged, :complete, :cancelled]
|
||||
enum :status, [:shipped, :being_packaged, :complete, :cancelled]
|
||||
end
|
||||
```
|
||||
|
||||
|
|
Loading…
Reference in a new issue