facing issues in enum field in rails4 - ruby-on-rails

Hi I have generated a migration to add_column rails g migration AddColumnToEmployees
class AddColumnToEmployees < ActiveRecord::Migration
def change
add_column :employees, :role, "enum('SUPER-ADMIN', 'HR','ADMIN','INVENTORY','EMPLOYEE')", :default => 'EMPLOYEE'
end
end
run rake db:migrate
Now I want to access role in my view for this I have written this:
<%=f.select :role, :collection => Employee.roles %>
But its not accessing it. It gives error
undefined method 'roles' for #<Class:0xc2acd88>
Please guide how to solve this. Thanks in advance!

I was under the impression you represented the enum as an integer in the DB, so your migration should be:
class AddColumnToEmployees < ActiveRecord::Migration
def change
# Assuming Employee is the first value in your enum list
add_column :employees, :role, :integer, default: 0
end
end
and your select should be:
<%= f.select :role, :collection => Employee.roles.keys.to_a %>
See Saving enum from select in Rails 4.1
Your model:
class Employee
enum role: [:employee, :inventory, :admin, :hr, :superadmin]
end
Rails does automatically provide you with all potential values through a class method with the pluralized attribute name.

your migration is fine. after your migration to access it in view like that
<%=f.select :role, :collection => Employee.roles.keys.to_a %>
and define enum field in model employee.rb
enum role: {
super_admin: 1,
hr: 2,
admin: 3,
inventory: 4,
employee: 5
}
convert in enum role of model into hash. and assign the value. and run it.i will try my best hope it will help you!!

Try following code, I hope this will help you.
in AddColumnToEmployees migration file.
class AddColumnToEmployees < ActiveRecord::Migration
def change
add_column :employees, :role, :integer, default: 0
end
end
in Employee Model.
class Employee
enum role: [ :super_admin, :hr, :admin, :inventory, :employee ]
end
and finally in view file.
<%= f.select :role, options_for_select(Employee.roles.collect { |e| [e[0].humanize, e[0]] }) %>

Related

Remove boolean and add list in ruby on rails

I would like to modify gender field,
Initially i have declared gender field as boolean true or false. but now i want it to be changed as list (Male, Female, Other).
class AddExtraFieldsToUser < ActiveRecord::Migration
def change
add_column :users, :phone_number, :string
add_column :users, :date_of_birth, :datetime
add_column :users, :gender, :boolean, default: false
add_column :users, :live_in, :string
add_column :users, :description, :text
end
end
Can i modify as following.... please let me know the correct way...
i thought of doing rails g migration RemovegenderFromUsers gender:boolean
then rake db:migrate followed by creating new one
rails g migration AddGenderToUsers gender:select
user.rb
GENDER_TYPES = ["Male", "Female", "Other"]
html
<%= f.select :gender, User::GENDER_TYPES %>
Is above mentioned process correct or any other way ?
The answer by Ahmad Hussain is correct . List is not a database field type .
You should generate a migration to change the column type :
**change_column :table_name, :column_name, :type**
Select is not a database field type if you want to do it then do it like this
rails g migration AddGenderToUsers gender:integer
In migration file change it to like this:
change_column :users, :gender, :integer, default: 0
For form page do this:
<%= f.select :gender, User::GENDER_TYPES.each_with_index.map { |gender, index| [gender, index] } %>
And in user model you can define function to get gender name to display
def gender_name
GENDER_TYPES[gender]
end

rails globalization "undefined method for translates" error

after watching rails cast: https://www.youtube.com/watch?v=u6CMY3mUv90
i tried myself to globalize my rails project but i am getting "undefiend method for translates" error
gem 'globalize'
i did a bundle install in my bash terminal and also did bundle updates sucessfully
then i added "translates: title, :content" like below:
class Post < ActiveRecord::Base
belongs_to :admin
has_many :comments
rails_admin do
edit do
field :title
field :content, :ck_editor
field :link_title
field :link
field :admin
end
end
translates: title, :content
end
then i added
class TranslatePosts < ActiveRecord::Migration
def self.up
Post.create_translation_table!({
:title => :string,
:text => :text
}, {
:migrate_data => true
})
end
def self.down
Post.drop_translation_table! :migrate_data => true
end
end
AND i did rake db:migrate
but i am getting the erro still. any idea why it is not working?
Two things to be checked;
- It seems that you missed colon in the translated attributes :title.
- Restart rails server may be helpful.

Rails: Adding migration to add an array (default empty)

I'm trying to add a column called share to one of my resources.
The idea is that users can upload documents and share them with other (specific) users, and the array contains the emails of those that the user wants to share with.
I tried adding a migration with the code
class AddShareToDocuments < ActiveRecord::Migration
def change
add_column :documents, :share, :array, :default => []
end
end
But when I open up rails console in the command prompt, it says that share:nil and user.document.share.class is NilClass.
Creating a new array in the rails console sandbox by typing
newarray = []
says that newarray.class is Array.
Can anyone spot what I'm doing wrong?
Rails 4 the PostgreSQL Array data type
In terminal
$ rails generate migration AddTagsToProduct tags:string
Migration file:
class AddTagsToProduct < ActiveRecord::Migration
def change
add_column :products, :tags, :string, array: true, default: []
end
end
https://coderwall.com/p/sud9ja/rails-4-the-postgresql-array-data-type
if you want support all databases you must serialize the array in a String
class Documents < ActiveRecord::Base
serialize :share
end
class AddShareToDocuments < ActiveRecord::Migration
def change
add_column :documents, :share, :string, :default => []
end
end
In case of Postgresql and array datatype I found https://coderwall.com/p/sud9ja
Arrays are not normally a type to be stored in a database. As michelemina points out, you can serialize them into a string and store them, if the type of the data in the array is simple (strings, int, etc). For your case of emails, you could do this.
If, on the other hand, you want to be able to find all of the User objects that a document was shared with, there are better ways of doing this. You will want a "join table". In your case, the join-table object may be called a Share, and have the following attributes:
class Share
belongs_to :user
belongs_to :document
end
Then, in your Document class,
has_many :shares
has_many :users, :through => :shares
As far as generating the migration, this may be hacky, but you could create a new migration that changes the type to "string" (Edit: correct code):
class AddShareToDocuments < ActiveRecord::Migration
def up
change_column :documents, :share, :string
end
def down
change_column :documents, :share, :array, :default => []
end
end

Mechanize mass assignment error for HABTM join table

The problem is that I get this error:
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: amenity_id
when I run this code:
task import_amenities: :environment do
agent = Mechanize.new
Kindergarten.find_all_by_public(false).each do |k|
p = agent.get(k.uri)
amenities = p.search("td td tr:nth-child(11) td:nth-child(2)").text.split(/(;|,) */)
amenities.each do |a|
am = Amenity.find_or_create_by_name!("#{a}")
k.update_attributes(amenity_id: am.id)
end
end
end
Kindergartens and Amenities are linked through a HABTM relation and are are defined as below:
kindergarten.rb
class Kindergarten < ActiveRecord::Base
attr_accessible :location, :name, :public, :uri, :address, :contact,
:phone, :url, :email, :description,
:password, :password_confirmation, :amenity_ids
has_and_belongs_to_many :amenities
end
amenity.rb
class Amenity < ActiveRecord::Base
attr_accessible :name, :kindergarten_ids
has_and_belongs_to_many :kindergartens
end
and here's the migration for the join table:
class CreateKindergartensAmenitiesJoinTable < ActiveRecord::Migration
def up
create_table :kindergartens_amenities, :id => false do |t|
t.integer :kindergarten_id
t.integer :amenity_id
end
end
end
The error is caused by this line in the rake task:
k.update_attributes(amenity_id: am.id)
Everything seems to work great in the console until I reach the mass assignment. And I think i am really messing something up here since I've never used before HABTM.
Any thoughts?
I couldn't sleep last night because of this bug but I finally found the solution.
there are a few issues in the code and the first one i noticed once i started digging and adding data in the db manually is that the join table is wrongfully named. Fix for that:
class RenameKindergartensAmenitiesTable < ActiveRecord::Migration
def up
rename_table :kindergartens_amenities, :amenities_kindergartens
end
end
apparently the habtm association is has to have stuff put alphabetically in title. source
Second problem is that I assumed that
k.amenity_id = am.id
would add an amenity_id / kindergarten_id for each amenity existing. In fact k.amenity_id does not mean anything (especially in the case of many ids). The solution that worked is this:
amenities.each do |a|
am = Amenity.find_or_create_by_name!("#{a}")
k.update_attributes(amenity_ids: k.amenity_ids.push(am.id))
end
I haven't modified the attr_accessible anywhere

globalize3 configuration I18n.locale variable

take a look into my model and my migration
i only have one attribute to test the globalize3 gem
class Car < ActiveRecord::Base
attr_accessible :name
translates :name
end
my migration looks like the following
class CreateCars < ActiveRecord::Migration
def up
create_table :cars do |t|
t.timestamps
end
Car.create_translation_table! :name => :string
end
def down
Car.drop_translation_table!
drop_table :cars
end
end
and i got the following error while trying to save new car details with the attribute name
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: locale
i think i am missing some declaration/configuration for globalize3 to access the I18n.locale variable.
btw i am using rails 3.2.3 and ruby 1.9.3p125
just found an workaround to my problem by following this Issue
class Car < ActiveRecord::Base
attr_accessible :name
translates :name
class Translation
attr_accessible :locale
end
end
Shouldn't this be like:
class Car < ActiveRecord::Base
attr_accessible :name, :translations_attributes
translates :name
end
See:
Rails 3.2.3: How to mass assign associated models?

Resources