Inserting a column value with null in ruby on rails - ruby-on-rails

I want to customize the value inserted in the column in the controller and i want to insert a null value in it. In this way :
#users.to = null

I believe you want:
#user.to = nil
You may have to run a migration to ensure the column allows NULL values:
change_column :users, :to, :string, :null => true

Related

Rails Migration - Change Integer Column to Array Integer - Postgres

I have a benefit_type integer column in Provider Model Which is a enum column.
Provider.rb
enum: ['abc', 'bcd']
Now I want to migrate to array_enum
Provider.rb
array_enum: {'abc': 0, 'bcd': 1}
So, to accommodate this change I want to change my column to array of integer. In my migration I have,
change_column :providers, :benefit_type, :integer, array: true, default: {}, using: "(string_to_array(benefit_type, ','))"
Error:
Caused by:
PG::UndefinedFunction: ERROR: function string_to_array(integer, unknown) does not exist
LINE 1: ...ALTER COLUMN "benefit_type" TYPE integer[] USING (string_to_...
^
HINT: No function matches the given name and argument types. You might need to add explicit
type casts.
Also tried:
change_column :providers, :benefit_type, :integer, array: true, default: []
Error:
Caused by:
ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR: column "benefit_type" cannot
be cast automatically to type integer[]
HINT: You might need to specify "USING benefit_type::integer[]".
: ALTER TABLE "providers" ALTER COLUMN "benefit_type" TYPE integer[], ALTER COLUMN
"benefit_type" SET DEFAULT '{}'
You need to specify integer array with column name in using keyword.
change_column :providers, :benefit_type, :integer, array: true, default: [], using: 'ARRAY[benefit_type]::INTEGER[]'
Initially you have to remove column defaults if you have and You need to specify integer array with column name that your'e needed and it defaults whenever it required.
change_column_default :table_name, :column_name, from: default_value, to: [default_value]
change_column :providers, :benefit_type, :integer, array: true, default: [], using: 'ARRAY[benefit_type]::INTEGER[]'
You can use this to convert existing column with integer type to an integer array
change_column :providers, :benefit_type, 'integer[] USING ARRAY[benefit_type]::INTEGER[]', array: true, null: false, default: []

Rails change existing text column to array

Using the Postgres database, added a text field staff_ids to branches table:
add_column :branches, :staff_ids, :text
In controller added this field to branch_params list:
:staff_ids => []
Data has been saved in this column like ["","32","52"]. When querying this field I got an error saying staff_ids should be an array
Branch.where("? = ANY(staff_ids)", '20')
ActiveRecord::StatementInvalid: PG::WrongObjectType: ERROR: op ANY/ALL (array) requires array on right side
Actually, I forgot to add array: true option in the migration when adding staff_ids field.
Now added another migration to change this column and tried to add array: true option:
change_column :branches, :staff_ids, :text, array: true
But the migration failed with an error:
PG::DatatypeMismatch: ERROR: column "staff_ids" cannot be cast automatically to type text[]
Now either I want to update the where clause so that it filters the branches based on staff_ids without adding the array: true or fix the migration mentioned above.
Any suggestion / idea ?
You can add the following in your migration,
def up
change_column :branches, :staff_ids, :text, array: true, default: [], using: "(string_to_array(staff_ids, ','))"
end
def down
change_column :branches, :staff_ids, :text, array: false, default: nil, using: "(array_to_string(staff_ids, ','))"
end
Defining up and down methods will help to reverse your migration at any time, if the change to an array was not required.

Hash Table Column Values as Integer

I have followed this tutorial to have a hash column on my model which works great.
When I work out codes in the rails console, it becomes different within my controller code. In the console:
Foo.update_attributes(bar: {"a" => 1, "b" => 2})
My values are shown as an integer, in the console. In my controller, if I'm doing calculations, I have to add .to_i or .to_f and it becomes messy. My values will forever be a number. Can I simple add an int or float for the column?
add_column :foos, :bar, :hstore, :integer, default: {}, null: false
The above does not work.
You can use a hook on your model:
before_save -> r { r.bar.each{|k, v| r.bar[k] = v.to_i} }

Rails Migration changing column to use Postgres arrays

I am trying to change a column in my database so that it can use the Postgres array data type.
Currently the table column is of type string.
I am using the following migration to convert it:
def change
change_column :table, :dummy_column, :text, array: true, default: []
end
But I get the following error:
bundle exec rake db:migrate
rake aborted!
An error has occurred, this and all later migrations canceled:
PG::Error: ERROR: column "dummy_column" cannot be cast automatically to type character varying[]
HINT: Specify a USING expression to perform the conversion.
: ALTER TABLE "table" ALTER COLUMN "dummy_column" TYPE character varying(255)
Tasks: TOP => db:migrate
PostgreSQL doesn't know how to automatically convert a column of varchar into an array of varchar. It doesn't know what you might intend, because it has no way to know what format you think the current values are in.
So you need to tell it; that's what the USING clause is for.
ActiveRecord doesn't seem to explicitly support the USING clause (not surprising, as it barely supports even the most basic database features). You can specify your own SQL text for the migration, though.
Assuming your strings are comma separated and may not themselves contain commas, for example:
def change
change_column :table, :dummy_column, "varchar[] USING (string_to_array(dummy_column, ','))"
end
(I don't use Rails myself and haven't tested this, but it's consistent with the syntax used in examples elsewhere).
Using Rails 4.2 on postgresql 9.4 I was looking to do this and preserve my pre-existing string data as the first element in one element arrays.
It turns out that postgresql cannot coerce a string into a text array without a USING expression to tell it how.
After much fiddling with delicate postgres syntax, I found a good middle way with active record:
def change
change_column :users, :event_location, :text, array: true, default: [], using: "(string_to_array(event_location, ','))"
end
The only direct postgresql there is the (string_to_array() ) function call. Here are the docs on that--note that you have to supply a delimiter.
Using Rails 4.2 on postgresql 9.4 with a down and a up, base on lrrthomas response.
Note: your starting column should have a default of nil
class ChangeEmailAndNumberColumnForContact < ActiveRecord::Migration
def up
change_column :contacts, :mobile_number, :text, array: true, default: [], using: "(string_to_array(mobile_number, ','))"
change_column :contacts, :email, :text, array: true, default: [], using: "(string_to_array(email, ','))"
end
def down
change_column :contacts, :mobile_number, :text, array: false, default: nil, using: "(array_to_string(mobile_number, ','))"
change_column :contacts, :email, :text, array: false, default: nil, using: "(array_to_string(email, ','))"
end
end
def change
change_column :table, :dummy_column, :string, array: true, default: '{}'
end
Notice:
it's specified as data type :string with array: true to default the column to an empty array ( [] ), you use default: '{}'
It can be done like below:
change_column :table, :column, :string, array: true, default: {}, using: "(string_to_array(column, ','))"
add_column :table, :dummy_column, :string, array: true
change_column_default :table, :dummy_column, []
This fixed it for me.

Rails 3.1: Problem saving record with not-null boolean mysql column (false saves as NULL)

Using Rails 3.1rc5 and devise 1.4.2. I have the following column on the users table
add_column :users, :has_dummy_password, :boolean, :default => false, :null => false
Without the :null => false clause if I do the following with an existing user record...
user.has_dummy_password = false
user.save
... then then in mysql the column has a value of NULL.
With the :null => false clause I (not surprisingly) get the following mysql error:
Column 'has_dummy_password' cannot be null
I can get around this by doing
user.has_dummy_password = 0
user.save
because "under the hood" booleans are implemented as tinyint in mysql. That seems a bit unfortunate though.
Is it possible to actually set boolean column values with true/false in Rails 3.1 instead of 1/0?

Resources