Im trying to set up my app to work with authlogic.. the thing is, other than the fields authlogic is supposed to use I want to keep in my database other attributes
Like Name, Last Name, PIN, etc... is there a way to do this?
You say "keep" - do you mean you have an existing database of users and you want to keep this info as you migrate to AuthLogic, or do you mean you just want to store this additional info?
Either way is possible but I'm going to assume you mean that you just want to store additional information - all you have to do is script/generate migration AddFieldsToUser then edit the migration:
class AddFieldsToUser < ActiveRecord::Migration
def self.up
add_column :users, :name, :string
add_column :users, :last_name, :string
add_column :users, :pin, :integer
end
def self.down
remove_column :users, :name
remove_column :users, :last_name
remove_column :users, :pin
end
end
Then run rake db:migrate
Related
I read RoR guide and I don't understand the next line:
If you wish for a migration to do something that Active Record doesn't know how to reverse, you can use reversible
What does it mean "doesn't know how to reverse"? How to distinguish what Active Record can reverse and what cannot?
It's simply, there are two kinds of operations in AR migrations:
1) Rails automatically knows how to rollback (revert) those operations in migrations, for example:
def change
add_column :users, :age, :integer
end
migration means add column age, rollback means remove column age. Or create_table, reverse operation is drop_table. This operations you can put into change method in migration and rails knows what to do when rollback / reverse those migrations.
2) Rails needs to help how to process migration and rollback process, usually it is operations which somehow modifies data.
def self.up
add_column :users, :name, :string
add_column :users, :surname, :string
say_with_time 'Split username into name and surname' do
Users.select(:username).all.each do |user|
user.name = user.username.split(/ /)[0]
user.surname = user.username.split(/ /)[1]
user.save!
end
end
remove_column :users, :username
end
As you can see, this operation is quite complicated. Rails does not know how to reverse this operation, so you have to write reverse operation code in self.down:
def self.down
add_column :users, :username, :string
say_with_time 'Join name and surname into username' do
User.all.each do |user|
user.update_attributes(username: "#{user.name} #{user.surname}")
end
end
remove_column :users, :name
remove_column :users, :surname
end
and thats all...
Is there a way to change the column names that paperclip uses when generating its database migration? For example, currently a paperclip migration looks like this:
class AddAvatarColumnsToUsers < ActiveRecord::Migration
def self.up
add_attachment :users, :avatar
end
def self.down
remove_attachment :users, :avatar
end
end
And it generates the following in the database:
avatar_file_name
avatar_file_size
avatar_content_type
avatar_updated_at
Ideally I'd like to change the avatar_file_name to correspond to a column in the database called "content". Is this possible?
Renaming columns, to something else than <attachment>_<attribute> will not work in Paperclip.
It mandatorily needs the following 4 attributes for each attachment in the model:
<attachment>_file_name
<attachment>_file_size
<attachment>_content_type
<attachment>_updated_at
Check this post out for a debate on why following a <attachment>_url approach might be better than having a separate model for attachment (<attachment>.url): Paperclip and Inheritance (STI)
For users that leverage S3 or Google Cloud Storage, you may need to move your files to a new directory following on paperclip's file naming scheme. Here is a sample migration to point you in the right direction:
class MovePaperclipAssets < ActiveRecord::Migration
def up
storage = Fog::Storage::Google.new google_storage_access_key_id: ENV["GOOGLE_ACCESS_KEY_ID"],
google_storage_secret_access_key: ENV["GOOGLE_SECRET_ACCESS_KEY"]
bucket = storage.directories.get('bucket-name')
bucket.files.each do |file|
if file.key.starts_with?("original/directory")
newfile = file.key.gsub("original/directory","new/directory")
file.copy('bucket-name', newfile)
file.destroy
end
end
end
def down
storage = Fog::Storage::Google.new google_storage_access_key_id: ENV["GOOGLE_ACCESS_KEY_ID"],
google_storage_secret_access_key: ENV["GOOGLE_SECRET_ACCESS_KEY"]
bucket = storage.directories.get('bucket-name')
bucket.files.each do |file|
if file.key.starts_with?("new/directory")
newfile = file.key.gsub("new/directory","original/directory")
file.copy('bucket-name', newfile)
file.destroy
end
end
end
end
ruby script/generate migration RenameDatabaseColumn
class RenameDatabaseColumn < ActiveRecord::Migration
def self.up
rename_column :user, :avatar_file_name, :user_file_name
rename_column :user, :avatar_file_size, :user_file_size
rename_column :user, :avatar_content_type, :user_content_type
rename_column :user, :avatar_updated_at, :user_updated_at
end
def self.down
# rename back if you need or do something else or do nothing
end
end
Just try the migration may be it will work for you. add column name whatever corresponding column name.
When you run the rails g migration add_avatar_columns_to_users, you can write as you wrote. But if you want to change the column names, go to the migration file and change them as you want as following. Please don't migrate it untill and unless you change the columns.
class AddAvatarColumnsToUsers < ActiveRecord::Migration
def self.up
add_column :users, :your_file_name,:string
add_column :users, :your_content_type, :string
add_column :users, :your_file_size,:integer
add_column :users, :yourfile_updated_at,:datetime
end
def self.down
remove_column :users, :your_file_name
remove_column :users, :your_content_type
remove_column :users, :your_file_size
remove_column :users, :yourfile_updated_at
end
end
Now run rake db:migrate
The above will work for sure. And add your attachments accordinbly.
Hi I have got a rails migration problem:
When I run a migration like this:
class RenameColumn < ActiveRecord::Migration
def change
rename_column :users, :hotel_stars, :rating_stars
rename_column :users, :restaurant_stars, :price_stars
end
end
and do a rake db:migrate it works fine. The columns are renamed and the data of those columns is in there. But when I then do a rake db:drop, create, migrate the columns are renamed and the data of those columns is gone... (One of my migration files fills the data base and it also fills those two columns before they get renamed)
What's the problem here?
Another question: I know its not a good idea to change former migration files, but is that ok when I run rake db:drop db:create and db:migrate afterwards - or will that cause problems?
The order of my migration files is the following:
add_devise_to_users -> creates a table users
add_columns_to_default_user -> adds columns and updates the whole table
class AddColumnsToDefaultUser < ActiveRecord::Migration
def change
add_column :users, :name, :string
add_column :users, :dob, :date
add_column :users, :address, :string
add_column :users, :hotel_stars, :integer
add_column :users, :restaurant_stars, :integer
add_column :users, :profile_picture_url, :string
add_column :users, :selected_car, :integer
User.reset_column_information
User.find(1).update_attributes!( :name => 'Alexander MacDonald', :dob => '1984-08-20', :address => '900 Highschool Way, Mountain View, CA 94041', :hotel_stars => '3', :restaurant_stars => '2', :profile_picture_url => 'user1.png', :selected_car => 1)
end
end
and then rename_column
class RenameColumn < ActiveRecord::Migration
def change
rename_column :users, :hotel_stars, :rating_stars
rename_column :users, :restaurant_stars, :price_stars
end
end
When you do db:drop you're erasing your DB.
So, when you do that the data is wiped. That data isn't going into a temporary place to be re-inserted. If you want to retain the data that's in the DB before/after a db:drop you need to store it somewhere and re-insert it yourself.
When you're changing structure only, unless you have a specific reason to remove the data that's in there already, all you need to do is the db:migrate.
Alternatively you can use something like populator in order to empty/fill you DB with test data following a migration.
I am trying to rake the db:migrations into my heorku instance and I get an error. The FAQ described my error as below:
Cannot change column type
Example: PGError: ERROR: column
“verified_at” cannot be cast to type
“date”
Cause: PostgreSQL doesn’t know how to
cast all the rows in that table to the
specified type. Most likely it means
you have an integer or a string in
that column.
Solution: Inspect your records and
make sure they can be converted to the
new type. Sometimes it’s easier to
just avoid using change_column,
renaming/creating a new column
instead.
How do I change this migration now. This is the problem that I have. For my Contacts table, I created the following:
t.string :date_entered
In a later migration, I do the following:
change_column :contacts, :date_entered, :date
This change_column appears to be the problem.
Should I...change by hand that migration? Is there a way I can clean the data in my tables (I didn't know Heroku would recognize the data in the table because I'm doing a rake).
I obviously need to change this value and it is used throughout my application. Thanks.
This is what I am trying...thoughts?
def self.up
#change_column :contacts, :date_entered, :date
#this fails in postgres, so trying the same outcome
rename_column :contacts, :date_entered, :date_entered_old
add_column :contacts, :date_entered, :date
remove_column :contacts, :date_entered_old
end
def self.down
add_column :contacts, :date_entered_old
remove_column :contacts, :date_entered
rename_column :contacts, :date_entered_old, :date_entered
end
Do the following:
rename the column A
create the new column B as date
move the data from A to B
remove A
In other words
def self.up
rename_column :contacts, :date_entered, :date_entered_string
add_column :contacts, :date_entered, :date
Contact.reset_column_information
Contact.find_each { |c| c.update_attribute(:date_entered, c.date_entered_string) }
remove_column :contacts, :date_entered_string
end
This is a modified and tested version of Simone Carletti's solution
class ModifyContacts < ActiveRecord::Migration
def self.up
rename_column :contacts, :date_entered, :date_entered_string
add_column :contacts, :date_entered, :date
Contact.reset_column_information
Contact.find(:all).each { |contact| contact.update_attribute(:date_entered, contact.date_entered_string) }
remove_column :contacts, :date_entered_string
end
end
The Redmine plugin tutorials explain how to wrap core models but what I need is to add another column to the journals table.
I need a boolean field inserted in the journals model. Creating another model with a 'belongs_to :journal' relation seems like an overkill.
Can this be done with a plugin?
I should note that I am a rails newbie.
You just have to create the appropriate migration.
In your plugin's directory, create the file db/migrate/update_journal.rb with the following :
class UpdateJournal < ActiveRecord::Migration
def self.up
change_table :journal do |t|
t.column :my_bool, :boolean
end
end
def self.down
change_table :journal do |t|
t.remove :my_bool
end
end
end
Then you can execute the task rake db:migrate_plugins RAILS_ENV=production to update your database with the new field.
After executing the migration, your journal database will have the my_bool field that you'll be able to call like every other field.
I was able to extend the existing user model using the following code:
class UpdateUsers < ActiveRecord::Migration
def up
add_column :users, :your_new_column, :string, :default => ''
add_column :users, :your_other_new_column, :string, :default => ''
end
def down
remove_column :users, :your_new_column
remove_column :users, :your_other_new_column
end
end
Also I needed to name the migration file in way that it began with a number eg. myplugin/db/migrate/001_update_user.rb