I imported data into Rails using a .sql file, to discover that most of the column titles have a period "." in them. This is clearly an issue and after attempting to run a migration that changes the column names, the period is still throwing it off. Any workarounds to speak of?
class FixColumnNames < ActiveRecord::Migration
def change
change_table :my_table do |t|
t.rename :p1.address, :'p1_address'
end
end
end
You can also use a string:
t.rename "p1.address", "p1_address"
The following syntax is also valid:
t.rename :"p1.address", :"p1_address"
Related
Basically my question is as the topic. My further purpose want to say how to go deeper in ROR.
I just find 'ruby on rails' document is not sufficient enough. Is there some material very comprehensively given all the command? How can I know how many other key words exist except 'rename' and 'rename_column'? How many kinds of commands exist?
class FixColumnNames < ActiveRecord::Migration
def change
change_table :table_name do |t|
t.rename :old_column1, :new_column1
t.rename :old_column2, :new_column2
...
end
end
end
I have a Rails 3.2 app that stores zip codes in a user_profiles table. I originally used integer as the data type for zip codes; however, this is obviously wrong since you can't use numbers that start with zero (and some US zip codes do start with zero). Therefore, I need to convert the zip code column AND my production data to string instead. I think this is done with a simple change_column migration, but I don't know the exact code to use when using Postgres. Any help would be much appreciated! My original migration to add the zip code column is below:
class AddZipCodeToUserProfiles < ActiveRecord::Migration
def change
add_column :user_profiles, :zip_code, :integer
end
end
class ChangeZipCodeToString < ActiveRecord::Migration
def change
change_column :user_profiles, :zip_code, :string
end
end
Have you tried that?
In my app I have teams and each team has a game time every week. I want the game times to be set to 'now' as a default. My table is set up like so
create_table "teams", force: true do |t|
t.datetime "wk1_time"
end
I created a migration and it looks like this:
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column :teams, :wk1_time, :default => DateTime.now
end
end
When I run rake db:migrate I get an error. Is my syntax wrong or am I missing something else?
Since Rails 5 you can make a migration like this:
change_column_default :users, :wk1_time, -> { 'CURRENT_TIMESTAMP' }
In my mind this is the best option because it not database specific answer.
Yes, you are missing the type :
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column :teams, :wk1_time, :datetime, :default => DateTime.now
end
end
But, you need the below not the above one, because you just want to change the default.
class ChangeDateTimeDefault < ActiveRecord::Migration
def change
change_column_default :teams, :wk1_time, DateTime.now
end
end
But none of these are correct approach for your task. The reason is DateTime.now will be evaluated based upon when you ran the migration, instead when the record is created. You need look to into this answer to know how to set the default time.
EDIT: For Rails 5+ there are better answers, like this one: https://stackoverflow.com/a/55357711/252799, though the below still works.
The way I found, was to do a migration on an existing datetime column, like this:
#migration
execute("ALTER TABLE teams ALTER COLUMN wk1_time SET DEFAULT CURRENT_TIMESTAMP")
that produces a schema.rb entry shown like this:
#schema.rb
t.datetime "wk1_time", default: "now()", null: false
The "now()" is a string sent to postgresql and evaluated at runtime, upon each insert.
You're going to run into problems settings the default date time in the migration. This is because DateTime.now will be evaluated based upon when the migrate runs, not when the record is created!
To fix that you'll need to create an ActiveRecord callback in order to set wk1_time like so:
before_create :set_default_wk1_datetime
def set_default_wk1_datetime
self.wk1_time = DateTime.now
end
for Postgresql :
add_column :users, :msgs_seen_at, 'TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP'
but you'll have to use user.reload after user = User.create in order to "see" msgs_seen_at
New to rails and having some Heroku troubles. I created a table and with it an index. I needed to change a field name, and naturally the index goes with. So I created three migrations, one to remove the field, the next to remove the index, and the last to add both. My computer has no issues handling this migration, but Heroku fails.
I have tried merging migrations #1 and #2 into one migration, but had no luck with that.
Index name 'index_updateresults_on_env_id_and_created_at' on table 'updateresults' does not exist/app/vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/schema_statements.rb:825:in `index_name_for_remove'
Edit:
May as well add my migrations.
class CreateUpdateresults < ActiveRecord::Migration
def change
create_table :updateresults do |t|
t.string :content
t.integer :env_id
t.timestamps
end
add_index :updateresults, [:env_id, :created_at]
end
end
class RemoveEnvIdFromUpdateresults < ActiveRecord::Migration
def change
remove_column :updateresults, :env_id, :string
remove_index :updateresults, [:env_id, :created_at]
end
end
class AddEnvNameToUpdateresults < ActiveRecord::Migration
def change
add_column :updateresults, :env_name, :string
add_index :updateresults, [:env_name, :created_at]
end
end
Edit 2
I'm at a loss. It seems as though in Postgre, removing a field also removes any indexes on that field. This may not happen in SqlLite, hence why my local environment works but Heroku breaks (just a guess). I've tried deleting the migration that removes the index to hopefully avoid this issue, I've committed the change, and pushed it to Heroku. Yet I'm still getting the same error, and when I clone the repo the migration still exists. Maybe this is something Git related and less Rails related.
Found a lot of information at this other question. I ended up being right in that it was git related. Completely unsure why my commits that were deleting the file, weren't taking place on Heroku. I ultimately did a git rm commitname, then heroku push -f to my repository. It finally took at this point.
Updated (to show code)
I'd like to mimic ActiveRecord's automatic timestamps directly in the database, but without explicitly adding this logic after every migration's create_table() call.
Here's what I do now:
class StatusQuo < My::Migration::Subclass
def self.up
create_table :tbl do |t|
... some columns ...
t.timestamps
end
add_default_now(:tbl, :created_at) # ALTER COLUMN ... DEFAULT NOW()
add_default_now(:tbl, :updated_at) # ALTER COLUMN ... DEFAULT NOW()
add_updated_at_trigger(:tbl) # BEFORE UPDATE ON ... trg_updated_at()
end
end
By contrast, here's what I'd like to do:
class Druthers < My::Migration::Subclass
def self.up
create_table :tbl do |t|
... some columns ...
t.timestamps
end
end
end
Is there an easy or recommended way to accomplish this? Using activerecord 3, postgresql 8.4.
Here's the best I could come up with so far, full source here:
In config/environment.rb check to see if our connection adapter is PostgreSQL. If so, require a file that does the following:
Wrap ColumnDefinition#to_sql to force defaults
Force "created_at" and "updated_at" to have DEFAULT CURRENT_TIMESTAMP
Wrap create_table to conditionally apply the trigger
If the newly created table has an "updated_at" column, install a trigger referencing a database FUNCTION assumed to exist.
Not pretty (need to have maintain a FUNCTION definition outside of this code) and not complete (change_table won't handle introducing timestamps properly), but good enough.