Ruby on Rails Global Activerecord::Enum

Ruby on Rails Global ActiveRecord::Enum

Use ActiveSupport::Concern this feature created for drying up model codes:

#app/models/concerns/my_enums.rb
module MyEnums
extend ActiveSupport::Concern

included do
enum status: [:active, :inactive, :deleted]
end
end

# app/models/my_model.rb
class MyModel < ActiveRecord::Base
include MyEnums
end

# app/models/other_model.rb
class OtherModel
include MyEnums
end

Read more

Rails global enums?

It may be less likely that I need to
access it in my model, but definitely
within the controller and view.

Are you sure? When you talk about database and schema, you are talking about the Model part of your application.
I think the best place to store these variables would be the model that uses them.

If these variables belongs to a single model you can store them directly in the model itself:

class Item < ActiveRecord::Base
STATUS_UNKNOWN = 0
STATUS_MEDICAL = 3
end

Then you can reference the values inside and outside the model scope

class Item
def my_method
STATUS_UNKNOWN
end
end

Item::STATUS_UNKNOWN # => 0
Item.new.my_method # => 0

When there is an enumeration of values, Rubyists often use hashes or arrays.

class Item
AVAILABLE_STATUSES = { :unkwnown => 0, :medical => 3 }

def self.statuses
self.AVAILABLE_STATUSES.keys.sort
end

def self.status_value(key)
self.AVAILABLE_STATUSES[:key]
end

end

Item::AVAILABLE_STATUS # => { :unkwnown => 0, :medical => 3 }
Item.statuses # => [:medical, :unkwnown]
Item.status_value(:medical) # => 3

If more than one model share the same logic, you can put it in a Module and mix the module in all Models that requires it.

Proper storage of enumeration models in Rails

Check out the ruby gem I've been working on called classy_enum. I'm pretty sure it does exactly what you're looking for. The README has some example usage, but the premise is that it lets you define multiple enum members as classes that can have different properties.

How to build dynamic enums in Rails 6 model concerns?

There are cleaner ways to do what I'm about to present, but it will accomplish what you're trying to do. Mind the brevity (I removed your associations to do a quick spot-check on my machine):

module Bookable
extend ActiveSupport::Concern
included do
STAGES = {
confirmed: 0,
completed: 1,
cancelled: 2,
issue_raised: 3
}.freeze
end
end

class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true

def self.acts_as_bookable_with(extra_stages = {})
include Bookable

enum stage: self::STAGES.merge(extra_stages)
end
end

class Mission < ApplicationRecord
acts_as_bookable_with({
awaiting_estimate: 4,
awaiting_payment: 5,
awaiting_report: 6,
report_sent: 7
})
end

If you want to define these on the class, it would look like this:

module Bookable
extend ActiveSupport::Concern
included do
STAGES = {
confirmed: 0,
completed: 1,
cancelled: 2,
issue_raised: 3
}.freeze
end
end

class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true

def self.acts_as_bookable_with(extra_stages)
include Bookable
if extra_stages.is_a?(Symbol)
extra_stages = self.send(extra_stages)
elsif extra_stages.is_a?(Hash)
# do nothing
else
raise TypeError, "can't find extra_stages from #{extra_stages.inspect}"
end
stages = self::STAGES.merge(extra_stages)
enum stage: stages
end
end

class Comment < ApplicationRecord
def self.extra_stages
{
awaiting_estimate: 4,
awaiting_payment: 5,
awaiting_report: 6,
report_sent: 7
}
end

acts_as_bookable_with(:extra_stages)

end

Note that we're calling acts_as_bookable_with after we define our class method. Otherwise, we'll get undefined method error.

There isn't a whole lot of "bad" in having this in ApplicationRecord. It's not the most ideal way of doing it, but most of these acts_as_* modules follow this exact pattern anyway and inject into ActiveRecord::Base.

Rails: How do I validate uniqueness of certain types in an enum

validates :account_type, uniqueness: true, if: 'account_type == "user"'

The answer was based on @neydroid's answer, although that per se was incorrect, and he didn't respond to my request to fix it.

Ruby on Rails: get variable from include do

You cannot include this module into your controller. You could however try:

module MyEnums
extend ActiveSupport::Concern
Statuses = [:active, :inactive, :deleted]

included do
enum status: Statuses
end

end

And then in the controller:

MyEnums::Statuses


Related Topics



Leave a reply



Submit