Rails field enum as_json : get integer instead of string - ruby-on-rails

In my projet, I have a User model with a gender enum :
class User < ActiveRecord::Base
enum gender: [:female, :male]
end
When I'm calling as_json on one of my object, I get the string "female" or "male". Is there any way to render the integer value instead of the string ?

I would try looking over the docs
http://edgeapi.rubyonrails.org/classes/ActiveRecord/Enum.html
for this, perhaps you could use a hash instead
class User < ActiveRecord::Base
enum gender: { female: 0, male: 1 }
end
hope its of any help

User.genders is an array of your enum and integer value. So, use User.genders[#user.gender].to_json.
If you're not happy with the default, to_json, investigate jBuilder to create the exact JSON you

Related

How to let active model serializer automatically convert enum attribute to integer

class User < ApplicationRecord
enum status: [ :active, :inactive ]
end
By default the active model serializer serializes User object's status attribute to a string, either "active" or "inactive", but I would like it to be integer 0 or 1. To accomplish so, I have to do this manually:
class UserSerializer < ActiveModel::Serializer
attributes :status
def status
object.status_before_type_cast # get integer
# or User.statuses[object.status], the same thing
end
end
This is a bit ugly because I have to write code for each enum attribute for each active model class. Is there any option to do this once?
you can access the enum index value like a hash
User.statuses[:active]
=> 0
User.statuses[:inactive]
=> 1
I hope this is what you looking for
http://api.rubyonrails.org/v5.1/classes/ActiveRecord/Enum.html
enum status: { active: 0, inactive: 1 }
Model.statuses # Pluralized version of the enum attribute name
That returns a hash like:
=> {"active"=>0, "inactive"=>1}
You can then use the status value from an instance of the Model class to access the integer value for that instance:
my_model = Model.find(123)
Model.statuses[my_model.status] # Returns the integer value
https://www.sitepoint.com/enumerated-types-with-activerecord-and-postgresql/

How to get the int value from my Model enum when I have an record instance?

How can I convert a Model enum to the INT value?
I am trying to do this:
class User < ActiveRecord::Base
enum user_type: [:member, :super]
end
Now say I have a user record, now I want to use the user_type enum value in another query:
u = User.find_by_type(#user.user_type)
def self.find_by_user_type(user_type)
User.where(user_type: user_type).take
end
This doesn't work because the user.user_type is returning "member" or "super" and I need 0 or 1.
Is there a way to get the Int value from my #user instance?
(Rails 4.x)
To get integer equivalent of enum type:
User.user_types[self.user_type] # returns integer value
Replace self with another user instance if necessary.

Ruby on Rails 4.2 enum attributes

I'm trying to use new Enum type, everything works well except one issue. When writing functional tests I usually use structure:
order = Order.new(o_status: :one)
post :create, order: order.attributes
# Error message:
# ArgumentError: '0' is not a valid o_status
It's ok as long as I don't have Enum attribute. The problem with enums is that instead of String value .attributes returns it's Integer value which can't be posted as enum attribute value.
In above example model can look like this:
class Order < ActiveRecord::Base
enum o_status: [:one, :two]
end
I figured out that when I do:
order = Order.new(o_status: :one)
atts = order.attributes
atts[:o_status] = "one" # it must be string "one" not symbol or integer 0
post :create, order: order.attributes
It will work OK.
Is it normal or there is some better solution?
EDIT:
The only workaround which I found looks like this:
order = { o_status: :one.to_s }
post :create, order: order
pros: It is short and neat
cons: I cannot validate order with order.valid? before sending with post
This doesn't solve issue with order.attributes when there is Enum inside.
From the Enum documentation:
You can set the default value from the database declaration, like:
create_table :conversations do |t|
t.column :status, :integer, default: 0
end
Good practice is to let the first declared status be the default.
Best to follow that advice and avoid setting a value for an enum as part of create. Having a default value for a column does work in tests as well.

Using enum in a model, when saving it doesn't like the integer value

Using rails 4.1.1
My model has an enum like:
class Article < ActiveRecord::Base
enum article_status: { published: 1, draft :2 }
Now in my new.html.erb I have:
<%= form.select :article_status, options_for_select(Article.article_statuses) %>
When going to save the model I get this error:
'1' is not a valid article_status
I was thinking it would be able to handle this during an update.
What am I doing wrong?
The update_attributes or new call in your controllers will expect the stringified version of the enum symbol, not the integer. So you need something like:
options_for_select(Article.article_statuses.
collect{|item, val| [item.humanize, item]}, selected: #article.status)
There is a full example in this article.

object.class returns unexpected results in Ruby

I have a descendants method in my Question model to return all objects that inherit from it.
class Question < ActiveRecord::Base
class << self
def descendants
ObjectSpace.each_object(Class).select do |klass|
klass < self
end
end
end
end
When I call Question.descendants I get back an array w/ a single object
[MultipleChoice(id: integer, text: text, scored: boolean, required: boolean, type: string, questionnaire_id: integer, created_at: datetime, updated_at: datetime)]
The problem is that when I call Question.descendants.first.class I get back Class instead of the expected MultipleChoice.
Why is this happening?
The thing is, that you already have a class in the array (the MultipleChoice class). When you ask Question.descendants.first you get that MultipleChoice class.
However, you are asking for Question.descendants.first**.class**. And the class of MultipleChoice is Class.
Getting Class as the class of MultipleChoice is perfectly OK. Have a look at the ruby metamodel as a reference:
image source: http://sermoa.wordpress.com/2011/06/19/ruby-classes-and-superclasses/
You have MultipleChoice class instead of instance in your array returned by descendants method. This is because you used ObjectSpace.each_object with Class parameter, which returns classes, since their class is Class.
[MultipleChoice(id: integer, text: text, scored: boolean, required: boolean, type: string, questionnaire_id: integer, created_at: datetime, updated_at: datetime)]
This is not an array of single object. This is an array in which you have something like [MultipleChoice]. And when you try MultipleChoice.class it will return Class.
There is some issue in your code that creates Question.descendants

Resources