Alter existing model with a Redmine plugin - ruby-on-rails

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

Related

Renaming model with migration

I have an existing model 'micropost' and I found out that there is better name for the model to suit my application. What would be the better approach to rename 'micropost' model to 'story' model without affecting its indexes? I am working on Rails 5.0.0.rc1. The migration snippet is:
class CreateMicroposts < ActiveRecord::Migration
def change
create_table :microposts do |t|
t.text :content
t.references :user, index: true
t.timestamps null: false
end
add_index :microposts, [:user_id, :created_at]
end
end
1 .Make migration to change the database table name from micropost to story.
class RenameOldTableToNewTable< ActiveRecord::Migration
def change
rename_table :old_table_name, :new_table_name
end
end
2 .Change manually the Active Record model class into Story
Run command on console:
$ rails g migration RenameMicropostToStory
Edit migration file:
class RenameMicropostToStory < ActiveRecord::Migration
def change
rename_table :microposts, :stories
end
end
then,
$ rake db:migrate

Change the column in table in ruby on rails

I have a migration file called [timestamp]_create_posts.rb.
I found that I made the column with a wrong data type. I need to make t.text :content instead of t.string :content.
I include the code from the above file:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.string :content
t.timestamps null: false
end
end
end
I kinda know that I should not directly change the file but rollback migration and change the schema and do the migration again. But I wasn't sure whether that's a right way to do it. It would be really nice if someone can guide me through this. I'm not really familiar with Rails.
You should not rollback anything. You should create a new migration, that will change a column with following content:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def change
change_column :posts, :content, :text, limit: 60000 # or whatever
end
end
or, even better, to supply the reasonable rollback of this migration:
class UpdatePostsChangeContentColumn < ActiveRecord::Migration
def up
change_column :posts, :content, :text, limit: 60000 # or whatever
end
# back to previous version
def down
change_column :posts, :content, :string
end
end
The other option if you are just in the development is just to Drop you database and recreate it. Then you can modify that file, but THIS IS NOT ADVISED. I have done this again in development where i didn't care about recreating my database
rake db:drop
rake db:create
rake db:migrate
There are two ways to change the column in table:
You can use rake db:rollback VERSION=file_version and then after that you can change datatype manually.
Generate another migration file. e.g rails g migration RemoveColumnToPost and the you can add following codes:
def up
change_column :posts, :content, :text
end
def down
change_column :posts, :content, :string
end
And then use rake db:migrate

Changing column names with paperclip gem

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.

Undefined add_column in Rails 3

I am trying to run a migration in Rails 3, I wish to add a column to a table, the code looks like this:
class AddConstAdr < ActiveRecord::Migration
def change
change_table: constants do |t|
t.add_column :home_address, :string
end
end
end
When I do rake db:migrate I get an error saying undefined method 'add_column'. I am confused as to why this is happening, can anyone help?
You seem to be mixing two different ways of doing a migration. You probably want this:
def change
change_table :constants do |t|
t.string :home_address
end
end
or this:
def change
add_column :constants, :home_address, :string
end
Both forms should do the same thing: add a home_address string column to the constants table.
I'm also assuming that your change_table: constants is just a typo that should have been change_table :constants.
Further information may be found in the Migrations Guide.
You should do as below:
def change
add_column :constants, :home_address, :string
end

Rails won't let me change records during migration

This must be something simple but it's driving me nuts!
I have a migration where I want to update a record afterward
class SubjectsTextField < ActiveRecord::Migration
def self.up
add_column :users, :subjects, :text
User.find(39).update_attribute :subjects, "hey there"
end
def self.down
remove_column :users, :subjects
end
end
The column gets created but when I go to check record 39, it's subjects field is null and doesn't say "hey there". No errors are thrown during the migration and the update_attribute line returns true as if it had worked.
This line works perfectly in the console and has the expected effect:
User.find(39).update_attribute :subjects, "hey there"
I tried putting the update_attribute line in a second migration. If I blow through both of them in one "rake db:migrate" all the way to current, it still doesn't work.
But here is the weird part. If I run two separate migrations, say "rake db:migrate VERSION=10" to only create the column and then the second one with "rake db:migrate" to update the attribute IT WORKS!
What the heck is going on...how do I modify a record during a migration? I seem to remember doing this quite often in the past. Maybe it is something different with Rails 2.3.2?
Thanks!
Brian
You need to call reset_column_information on the model you changed before you can use the new column. Add this between the add_column and update:
User.reset_column_information
See "Using a model after changing its table" on the ActiveRecord::Migration page.
This syntax is much clear...try with change_table
class AddReceiveNewsletterToUsers < ActiveRecord::Migration
def self.up
change_table :users do |t|
add_column :users, :subjects, :text
end
User.find(39).update_attribute "subjects", "hey there"
end
def self.down
remove_column :users, :receive_newsletter
end
end
If you combine the two in your initial migration like this, does that work?
class SubjectsTextField < ActiveRecord::Migration
def self.up
add_column :users, :subjects, :text
User.find(39).update_attribute "subjects", "hey there"
end
def self.down
remove_column :users, :subjects
end
end

Resources