brainspec / enumerize Goto Github PK
View Code? Open in Web Editor NEWEnumerated attributes with I18n and ActiveRecord/Mongoid support
License: MIT License
Enumerated attributes with I18n and ActiveRecord/Mongoid support
License: MIT License
I've got two models using enumerize, one includes it via extend FooEnumeration
and one has it directly on the class.
I have specs for both that check that it validates the content of the enumerized column to be in the specified set of values. The one that gets the enumeration via the module fails this spec consistently. I can get it to pass by adding validate :_validate_enumerized_attributes
in addition to including the FooEnumeration
module.
Is there something about this approach that causes the model to not get the validations?
Think about public API:
I try to use enumerize but get error
undefined method enumerize for #<Class>
I created this app to demonstrate error
I'm trying to use enumerize within an engine, but the scopes don't get generated. Everything else appears to work as expected.
If I add gem "enumerize", "~> 0.5.1"
to the gemfile of the app using the engine the scopes are then generated.
Am I missing something?
The Rails version is 4 RC1.
The Ruby version is 1.9.3.
I have spec.add_dependency("enumerize", "~> 0.5.1")
in the gemspec for the engine.
In a model in the engine:
extend Enumerize
enumerize :privacy_level, in: { public: 1, restricted: 2, private: 3 }, default: :public, predicates: true, scope: true
I also have require 'enumerize'
in the engine.
Thanks
When I include enumerize and I have an Hstore attribute, it breaks because the hstore gem (https://github.com/engageis/activerecord-postgres-hstore) requires the following in the model:
serialize :attribute, ActiveRecord::Coders::Hstore.
Enumerize doesn't recognize this data type and raises an error
uninitialized constant Enumerize::ActiveRecord::Coders
Any advice on how to workaround this conflict?
Hi!
given a model like this
class Photo < ActiveRecord::Base
extend Enumerize
enumerize :status, :in => {:public => 1, :private => 2}, :default => :public, :scope => true
default_scope with_status(:public)
end
and doing Photo.new.status you get nil instead of 'public'.
class User < ActiveRecord::Base
extend Enumerize
enumerize :state, in: { active: 1, inactive: 2 }, predicates: true
end
Given the above class, is there a way to access enumeration values from class methods? so something like this
User.active
# or
User.state_active
Given the following setup ...
class User
enumerize :roles, in: [:admin, :editor], multiple: true, predicates: true
end
.. are predicates supported?
user.admin?
user.roles.admin?
Both result in the following:
NoMethodError: undefined method `admin?' for #<Enumerize::Set {}>
I know the gem sets the value to nil if it isn't in the list but I think it really should be using validates_inclusion_of :status, :in => %w()
, I'm adding it in and will do a pull request soon.
I tried to use this gem. In development it works great, but in production it return error
Model:
class Order < ActiveRecord::Base
extend Enumerize
belongs_to :admin_user
has_many :packages, :order => 'id DESC'
attr_accessible :address, :city, :country, :email, :first_name, :last_name, :region, :status, :zip
enumerize :status, in: [:pending, :unpaid, :processing, :sent]
enumerize :payment_type, in: [:card, :paypal]
end
Error:
E, [2013-02-09T18:07:38.495705 #8655] ERROR -- : uninitialized constant Order::Enumerize (NameError)
/home/site_on_rails/site/releases/20130209134612/app/models/order.rb:2:in <class:Order>' /home/site_on_rails/site/releases/20130209134612/app/models/order.rb:1:in
<top (required)>'
/home/site_on_rails/site/releases/20130209134612/app/admin/orders.rb:1:in <top (required)>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/application.rb:190:in
block in load!'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/application.rb:190:in each' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/application.rb:190:in
load!'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/application.rb:213:in routes' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin.rb:79:in
routes'
/home/site_on_rails/site/releases/20130209134612/config/routes.rb:2:in block in <top (required)>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/routing/route_set.rb:282:in
instance_exec'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/routing/route_set.rb:282:in eval_block' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/routing/route_set.rb:260:in
draw'
/home/site_on_rails/site/releases/20130209134612/config/routes.rb:1:in <top (required)>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application/routes_reloader.rb:40:in
block in load_paths'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application/routes_reloader.rb:40:in each' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application/routes_reloader.rb:40:in
load_paths'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application/routes_reloader.rb:16:in reload!' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application.rb:108:in
reload_routes!'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/reloader.rb:34:in reload!' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activeadmin-0.5.1/lib/active_admin/reloader.rb:61:in
block in attach!'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:429:in _run__1832084183846158708__prepare__147990969946457657__callbacks' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:405:in
__run_callback'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:385:in _run_prepare_callbacks' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/callbacks.rb:81:in
run_callbacks'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/reloader.rb:74:in prepare!' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/actionpack-3.2.11/lib/action_dispatch/middleware/reloader.rb:48:in
prepare!'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application/finisher.rb:47:in block in <module:Finisher>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/initializable.rb:30:in
instance_exec'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/initializable.rb:30:in run' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/initializable.rb:55:in
block in run_initializers'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/initializable.rb:54:in each' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/initializable.rb:54:in
run_initializers'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/application.rb:136:in initialize!' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/railtie/configurable.rb:30:in
method_missing'
/home/site_on_rails/site/releases/20130209134612/config/environment.rb:4:in <top (required)>' config.ru:4:in
require'
config.ru:4:in block in <main>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/rack-1.4.4/lib/rack/builder.rb:51:in
instance_eval'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/rack-1.4.4/lib/rack/builder.rb:51:in initialize' config.ru:1:in
new'
config.ru:1:in <main>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn.rb:44:in
eval'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn.rb:44:in block in builder' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:700:in
call'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:700:in build_app!' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:573:in
init_worker_process'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:593:in worker_loop' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:491:in
spawn_missing_workers'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:502:in maintain_worker_count' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/lib/unicorn/http_server.rb:276:in
join'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/gems/unicorn-4.4.0/bin/unicorn:121:in <top (required)>' /home/site_on_rails/site/shared/bundle/ruby/1.9.1/bin/unicorn:23:in
load'
/home/site_on_rails/site/shared/bundle/ruby/1.9.1/bin/unicorn:23:in `
I'm not sure if it is intended, but I expected values of enumerized attributes to be casted to symbols in their getters (so it is consistent with the way how we define "in" values).
I think it's reasonable to add matchers for rspec out of the box
This isn't actually a bug in Enumerize, but are you aware of this?
# Reimplementation of ActiveRecord::Store to be compatible with Enumerize.
# Explanation:
# Enumerize defines it's accessors on some module that is then included into the class. This works well
# for i.e. AR because Enumerize accessors are in the method search path before AR attributes.
# ActiveRecord::Store defines accessors directly on the class thus Enumerize accessors are shadowed.
# This implementation defines store accessors on another module instead. As long as this one is mixed in before
# the Enumerize module everything works as expected.
# That means `store` has to be called and set up before `enumerize`. Same goes for the corresponding includes/extends.
module EnumerizeCompatibleStore
extend ActiveSupport::Concern
module ClassMethods
def store(store_attribute, options = {})
include _enumerize_compatible_store_module
serialize store_attribute, Hash
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
end
def store_accessor(store_attribute, *keys)
Array(keys).flatten.each do |key|
_enumerize_compatible_store_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{key}=(value)
self.#{store_attribute}={} unless #{store_attribute}.is_a?(Hash)
#{store_attribute}[:#{key}] = value
#{store_attribute}_will_change!
end
def #{key}
self.#{store_attribute}={} unless #{store_attribute}.is_a?(Hash)
#{store_attribute}[:#{key}]
end
RUBY
end
end
def _enumerize_compatible_store_module
@_enumerize_compatible_store_module ||= Module.new
end
end
end
I have the model called Advert with :price_type column:
:price_type, :string, default: 'total', null: false
When I define
enumerize :price_type, in: %w(total perm)
And do
Advert.new.price_type it's nil until I define default value for enum.
I think, this is behaviour is'nt expected.
Noone of lines with day doesn't work. Day value is invalid.
test/factories/lessons.rb
FactoryGirl.define do
factory :lesson do
#day :monday
#day "monday"
#day Lesson.day.values.first
end
end
app/models/lesson.rb
class Lesson < ActiveRecord::Base
extend Enumerize
attr_accessible :day
enumerize :day, in: [:monday,
:tuesday,
:wednesday,
:thursday,
:friday,
:saturday,
:sunday],
default: :monday, multiple: true
validates :day, presence: true
end
Somewhere in my model I have:
enumerize :pay_type, in: %w( year month day )
validates :pay_type, presence: true, if: :rent?
Than, in some place I do:
puts pay_type.inspect # "month"
puts pay_type.blank? # false
puts read_attribute(:pay_type).inspect # "month"
save
puts errors.inspect # "pay type can not be blank"
puts pay_type.inspect # "month"
puts pay_type.blank? # false
puts read_attribute(:pay_type).inspect # "month"
I have no ideas how to reproduce this with spec, but this behaviour is strong.
require 'enumerize'
require 'enumerize/integrations/rspec'
describe "this" do
it "does that" do
it { should enumerize(:something).in(:this, :that)
end
end
# => require cannot load such file 'enumerize/integrations/rspec'
def space_locale
if model.space.there_places?
"good"
end
if model.space.there_not_places?
"bad"
end
if model.space.group_formed?
"not bad"
end
end
this code from decorator.
regardless of the value model.spaсe none of the units not function returns
Not really much more to say. The problem seems to be in the method writers in attribute.rb, but I'm not motivated enough to fix it myself ATM.
Write up with specs, source, schema and output at https://gist.github.com/2497174
In a nutshell, I can get an enumerated value assigned to a field if and only if I declare it as a default value in the model itself. I cannot assign to that field and have it remain an Enumerized field. Kind of ruins the whole experience...
Hi,
I've been using simple_enum (https://github.com/lwe/simple_enum) for managing my enum fields. I like your gem because it has built in I18n support but it is missing one important feature for me. simple_enum lets you optionally set the integer values for the enum fields. This is important to me because it allows you to add new values to the list in whatever order you like without worrying about changing the integer values associated with them.
Any plans or interest in adding a feature like this?
It is possible to create a model with wrong enum value
Consider common use case:
model = Model.create!(:enumerized_field => "some very wrong value")
Instead of exception model.enumerized_field becomes nil
I have a use case where I need to be able to obtain the enumerized text (stored in a translation file) for a nominal enumerated value without an instance of the class. For example, if I have a sex enumeration with values of 'M' and 'F', I want to be able to find the text for 'M' via a class method, eg. MyModel.sex.text_for('M').
The only way I can see to do this is to create an instance of the entire model, assign it sex of 'M' and check sex_text, for example:
m = MyModel.new(sex: 'M')
m.sex_text
This doesn't sit well with me and has significant overhead in the case of complicated AR models, for instance.
Hello, thanks for fixing #67 so quickly!
I found one more glitch with abstract model classes.
When I use enumerize with scope: true
in an abstract model, it fails with the dreaded:
ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect table name '': SHOW FULL FIELDS FROM ``
I am afraid this is related to current state of rails (I tested on 3.2.12), where this happens on all scopes defined in abstract models, which use where
. If I only use order
, it works.
So probably this is not enumerize bug, but a rails bug. I found some issues in rails about this, but generally it seems no one is interested much in them.
So maybe it would be worth to mention this in the readme...
regards!
Jakub
I tried doing f.input :review_type
but it just outputs an input instead of a select. Anyone else have it working in 2.0?
Writing a active record query using where is throwing error. please help
User.where(:status => :approved)
It is a feature request: it would be nice if enumerize supports multiple values.
e.g.
class Profile
include Enumerize
enumerize :places_lived, :in => [:london :tokyo :minsk :paris :new_york], :multiple => true
end
me.places_lived << :london
me.places_lived << :tokyo
It will be even more awesome if it comes with form_helper implementation (checkbox or multiple selection on selectbox)...
Hi
I think your gem is pretty good and I want to use it in our product.
By the way, Is it possible to add feature that I can get enumerate options by something like below?
class User < ActiveRecord::Base
include Enumerize
enumerize :sex, :in => [:male, :female]
end
User::SEX_ENUM # >> [:male, :female]
User.sex_enum # >> [:male, :female]
Because I want to add constraint in "config/routes.rb" where there is no specific instance of User.
class User
enumerize :sex, in: [:male, :female], default: :male
end
###
User.new.sex #=> 'male'
u = User.create
u.sex #=> nil
I have an abstract class BaseModel. My other models are derived from it.
When I use
extend Enumerize
enumerize :visibility, :in => [:private, :public]
on the abstract class, the 'visibility' field is always empty.
When I move the enumerize call to real submodel (the one having DB table), it works fine.
Hi,
First of all thx for this great gem. I used enumerize before, but seems like its not working with the latest rails version.
Tested it with the user model too. User.last.sex gives me nil, although the query returns sex:0. User.sex.values works fine. Here is the code, test and gemfile:
class User < ActiveRecord::Base
extend Enumerize
attr_accessible :sex
enumerize :sex, :in => [:male, :female]
end
~/code/patoloji[master_]% rails g model User sex:integer
invoke active_record
create db/migrate/20130226093505_create_users.rb
create app/models/user.rb
invoke test_unit
create test/unit/user_test.rb
create test/fixtures/users.yml
~/code/patoloji[master_]% rake db:migrate
== CreateUsers: migrating ====================================================
-- create_table(:users)
-> 0.0588s
== CreateUsers: migrated (0.0589s) ===========================================
~/code/patoloji[master*]% rails c
User.create(:sex => :male)
(0.0ms) begin transaction
SQL (2.9ms) INSERT INTO "users" ("created_at", "sex", "updated_at") VALUES (?, ?, ?) ["created_at", Tue, 26 Feb 2013 09:37:28 UTC +00:00], ["sex", 0], ["updated_at", Tue, 26 Feb 2013 09:37:28 UTC +00:00] commit transaction
=> #<User id: 1, sex: 0, created_at: "2013-02-26 09:37:28", updated_at: "2013-02-26 09:37:28">
User.last.sex
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT 1
=> nil
User.sex.values
=> ["male", "female"]
My gemfile:
source 'https://rubygems.org'
gem 'rails', '3.2.12'
gem 'sqlite3'
gem 'rb-readline'
group :assets do
gem 'sass-rails', '> 3.2.3'> 3.2.1'
gem 'coffee-rails', '
gem 'uglifier', '>= 1.0.3'
gem 'less-rails'
gem 'twitter-bootstrap-rails'
end
gem 'jquery-rails'
gem "therubyracer"
gem 'enumerize'
gem 'simple_form'
On 0.6.0 I get this error:
Enumerized attribute title is already defined (ArgumentError)
I'm using a standard Rails app with ActiveRecord::Base. Example of a model:
class AnswerInfluence < ActiveRecord::Base
extend Enumerize
enumerize :condition, in: %w(eq gt lt), default: :eq
end
I have enumerizations in multiple models. When I comment out some of them, it seems the Exception is caused at different points. Almost as if the different Enumerizes clash which each other.
Any ideas?
@user.sex
returns nil, not enumerized value object.
I think it is better if gem allow user to access value_hash. User also need to reverse string to integer, right?
Example:
class User
include Enumerize
enumerize :sex, :in => [:male, :female], :methods => true
enumerize :role, :in => [:user, :admin], :methods => 'role_'
end
user.sex = 'male'
user.male? # false
user.female? # true
user.role = :admin
user.role_user? # false
user.role_admin? # true
Currently trying to set the enumerized attribute to an invalid value gives a vague error message:
...for the field Foo
it would give:
Validation failed: Foo is invalid
...vs the standard activerecord inclusion validator would give:
Validation failed: Foo is not included in the list
I want some things like when i define these attributes
enumerize :status, in: {:private => 0, :public => 1}, default: :private
and i read row from db, it convert back integer to string
User.create!
=> User id: 1, status: 0
render json: User.first
// to return json from ajax call
{"id" =>, "status" => "private"}
Is it possible in enumerize?
Hi!
I've created rspec matcher for enumerize.
You can check it here: https://gist.github.com/2318858
It a not cleaniest solution ever (uses instance_variable_get because you have not exposed any getters on
Enumerize::AttributeMap), but it works and I use it in production.
If you would like to merge it, i can write some tests for it so it is covered.
Have a nice day!:]
If I have a model that accepts a multiple enumeration, I am unable to get the text labels for the selected values. For a non-multiple enumeration, I can access the method text which returns the display label. Multiple enumerations return an array of the values as strings.
This seems like a gap in functionality for multiple enumerations, but maybe I'm just doing something incorrectly! Thanks!
en.yml
en:
enumerize:
profile:
languages:
c_language: "C"
c_plus_plus_language: "C++"
java_language: "Java"
ruby_language: "Ruby"
Profile
LANGUAGES = [ :c_language, :c_plus_plus_language, :java_language, :ruby_language] enumerize :languages, in: LANGUAGES, multiple: true
enumerize :one_language, in: LANGUAGES
Repro
## Set the enumeration ##
user.profile.languages = [:ruby_language, :java_language]
user.profile.one_language = :ruby_language
## Get the values ##
user.profile.one_language
# "ruby_language"
user.profile.languages
# [:ruby_language, :java_language]
user.profile.one_language.text
# "Ruby"
user.profile.languages.text
# NoMethodError: undefined method `text' for #<Array:0x007fe77e31ef30> ....
class User < ActiveRecord::Base
extend Enumerize
enumerize :role, in: {:user => 1, :admin => 2}
end
user = User.new
user.role = :user
user.role #=> 'user'
user.role_value #=> 1
Where it says user.role_value, i can only use user.role.value.
I'm using Rails 3. Here is the info about my ENV:
Ruby version 1.9.3 (x86_64-darwin12.4.0)
RubyGems version 2.0.4
Rack version 1.4
Rails version 3.2.12
JavaScript Runtime Node.js (V8)
class User
include Enumerize
enumerize :sex, :in => [:male, :female], :methods => true
end
user.male!
user.male? # true
user.female? # false
user.sex # :male
what do you think?
I prefer to use keywords instead of string where it make sense whenever its possible, like the follwing spec:
describe '#kind' do
it { role.kind.should == :manager }
end
So I've monkey patched Enumerize::Value to be comparable with anything like this:
module Enumerize
class Value < String
def ==(other_object)
super(other_object.to_s)
end
end
end
Do you think it would be a worthy feature?
add SimpleForm integration so f.input :sex
will generate select with enumerated options
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.