I am having an issue with Heroku in regards to adding an integer column to an existing table.
Here is how I setup my migration file:
class AddFieldsToNetwork < ActiveRecord::Migration
def self.up
add_column :networks, :phone, :integer, :limit => 10
add_column :networks, :contact, :string
end
def self.down
remove_column :networks, :phone
remove_column :networks, :contact
end
end
Now this works locally, but when I push to Heroku, I get what most people get:
!!! Caught Server Exception
HTTP CODE: 500
Taps Server Error: PGError: ERROR: integer out of range
If I change :integer to :string, then adding the columns works and functions great on Heroku. If I leave it under :integer, the :network model crashes when I create new "network".
Can anyone tell me what I might be doing wrong?
:limit - Requests a maximum column length. This is number of characters for :string and :text columns and number of bytes for :binary and :integer columns.
For phone you definitely use strings, reason is you mean 10 characters. Not bytes for numbers
Related
I have a table 'users' with column 'email'. It used to be unique (with index), but a new requirement is to allow nils there.
Is there a better solution than:
remove_index :users, :email
add_index :users, :email
?
Initially it was added with option unique:
add_index :users, :email, :unique => true
I would say that you have the correct solution there as the index will need to be regenerated, hence why there is no update_index.
Hey here is a migration I just wrote up that works pretty well. I have a table 'scraped_episodes' with a column that is varchar(255) 'enclosureUrl'. I need to make this longer to long urls so this is what I used (Rails 3.2.13)
class ExpandEnclosureUrl < ActiveRecord::Migration
def up
# remove index cuz we need to
remove_index :scraped_episodes, :enclosureUrl
# change length to 2048 characters
change_column :scraped_episodes, :enclosureUrl, :text, :limit=>2048
# redo this index to only index the first 255 chars
add_index :scraped_episodes, :enclosureUrl, :length => 255
end
def down
# remove index cuz we need to
remove_index :scraped_episodes, :enclosureUrl
# use the same settings at when i first created this field
change_column :scraped_episodes, :enclosureUrl, :string, :limit=>nil
# use the same settings as when i first added this index
add_index :scraped_episodes, :enclosureUrl
end
end
I am trying to add :price, :location, and :product to the columns for my microposts table. I have already done a bunch of other migrations and I have heard that rolling back all of migrations and redoing them is error prone. So I guess the other option is the schema file? I have heard that the schema file is just to be read and not edited. I have been looking at http://guides.rubyonrails.org/migrations.html but can't find the right info. They briefly talk about change_table which I think could be useful but it doesn't go into depth. Is this what I am looking for?
Just create a new standalone migration:
rails g migration add_price_location_and_product_to_microposts
It will create a file in the db/migrate folder, edit it:
def change
add_column :microposts, :price, :float # dont forget to change the type to the columns
add_column :microposts, :location, :string
add_column :microposts, :product, :integer
end
(You can define the change method, instead of up and down because add_column is a reversible command.)
And then, run rake db:migrate
I want my ActiveRecord class User to contain options (a bunch of string key-values), so I wrote:
rails generate migration AddOptionsToUser options:Hash
It generated:
class AddOptionsToUser < ActiveRecord::Migration
def self.up
add_column :users, :options, :Hash
end
def self.down
remove_column :users, :options
end
end
I also added this line to my class User:
serialize :options, Hash
But the migration fails:
Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Hash' at line 1: ALTER TABLE `users` ADD `options` Hash
I am new to Rails, what is the usual way to store a bunch of string key-values in an ActiveRecord class?
Rails serializes things in to a (YAML) string. So in your database, the type should be string (or text).
class AddOptionsToUser < ActiveRecord::Migration
def self.up
add_column :assessments, :options, :string
end
def self.down
remove_column :assessments, :options
end
end
To have ruby object as an attribute of the ActiveRecord model you should use serialize method inside your class for that attribute link
I am currently trying to run this migration:
class AddDroppedProjectsCountToUser < ActiveRecord::Migration
def self.up
add_column :users, :dropped_projects, :integer, {:default=>0, :required=>true}
end
def self.down
remove_column :users, :dropped_projects
end
end
The column is added correctly, but none of the old records are populated with 0. They are nil. I have tried using default=>'0' as well, to no avail. Any idea why this might be happening? (Rails 3.0.3)
Edited to add: When I create a new user it works fine, and everything looks correct. It's just the old users that still have nil for that value in the table.
What happens if you say:
def self.up
add_column :users, :dropped_projects, :integer, :null => false, :default => 0
end
instead? Without the :null=>false you're still allowing NULL in dropped_projects so there's no reason for PostgreSQL to make them 0. Also, I don't think :required is a valid option for add_column; since the options are just a simple Hash and add_column only looks for options it knows about, your stray :required option is silently ignored.
you could do this:
(taken from http://apidock.com/rails/ActiveRecord/Migration)
Using a model after changing its table
Sometimes you’ll want to add a column in a migration and populate it
immediately after. In that case, you’ll need to make a call to
Base#reset_column_information in order to ensure that the model has
the latest column data from after the new column was added. Example:
class AddPeopleSalary < ActiveRecord::Migration
def up
add_column :people, :salary, :integer
Person.reset_column_information
Person.all.each do |p|
p.update_column :salary, SalaryCalculator.compute(p)
end
end
end
I believe this is due to the fact that you are changing the old migration, instead of creating a new.
In this case, the solution is to check the schema file (schema.rb). It does not change automatically, and add
t.integer "dropped_projects", default: 0, null: false
class CreateScrapes < ActiveRecord::Migration
def self.up
create_table :scrapes do |t|
t.text :saved_characters
t.text :sanitized_characters
t.string :href
t.timestamps
end
end
def self.down
drop_table :scrapes
end
end
I'm about to rake db:migrate and I'm think about the attribute type if I should be using text or string. Since saved_characters and sanitized_characters will be arrays with thousands of unicode values, its basically comma delimited data, I'm not sure if `:text' is really the right way to go here. What would you do?
Assuming you're on MySQL, the real difference between :string and :text is length. Rails uses the varchar column type for :string columns, and sets a 255 character limit on :string columns. :text, usuprisingly, uses the text column.
To me, this suggests that :string would be a really bad choice for your columns, as they are likely to exceed 255 characters.
:string is only 255 characters. you probably want :text since you mention thousands.