Created migration using
rails generate migration add_table_defaults
class AddTableDefaults < ActiveRecord::Migration
def up
create_table :table_defaults do |t|
t.string :table_name, null: false, uniq: true
t.jsonb :default_values
end
TableDefault.create(
table_name: 'test',
default_values: [{name:test}]
)
end
def down
drop_table :table_defaults
end
end
Getting the error saying uninitialized constant AddTableDefaults::TableDefault while doing
rake db:migrate
This is straight forward not sure where i am doing wrong, any help is appreciated. Thanks
I'm pretty sure #mr_sudaca's solution works - however if it definitely doesn't, just define the class inside the migration:
class AddTableDefaults < ActiveRecord::Migration
class TableDefault < ActiveRecord::Base; end
def up
create_table :table_defaults do |t|
t.string :table_name, null: false, uniq: true
t.jsonb :default_values
end
TableDefault.create(
table_name: 'test',
default_values: [
{name:test}
]
)
end
def down
drop_table :table_defaults
end
end
Don't name a column on your table table_name. self.table_name is the attribute used by ActiveRecord models to keep track of the track of which table the model reads/writes from and is thus a really bad choice.
Problem Here was model was not available and i was trying to feed the data into the table
Related
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
Disclaimer: I don't know ruby.
I've been trying to setup this ruby application. I'm trying to debug why I get an uninitialized constant error:
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
uninitialized constant CreateSyncsTable::Syncs/var/rails/cycs/cycs/db/migrate/20100818122117_create_syncs_table.rb:8:in `up'
Below is the file contents of 20100818122117_create_syncs_table.rb.
class CreateSyncsTable < ActiveRecord::Migration
def self.up
create_table :syncs do |t|
t.timestamps
t.integer :remedy_query_low
t.integer :remedy_query_high
end
Sync.create :remedy_query_low => 0, :remedy_query_high => 0
end
def self.down
drop_table :syncs
end
end
To my understanding, line 8 is trying to create a new entry into the syncs table. I don't know exactly why the syntax for doing so is as follows:
Sync.create :remedy_query_low => 0, :remedy_query_high => 0
Nor do I understand why or where "Sync" comes from. Moreover, I don't know what constant is uninitialized.
Any help to debug this is appreciated. For the record, I am using centOS 7, Maria DB and ActiveRecord version 3.2.18.
I reviewed the API to see if that would help. Since I don't know ruby, I don't find it of much help.
Try adding in a call to ActiveRecord::ModelSchema.reset_column_information as it "resets all the cached information about columns, which will cause them to be reloaded on the next request", allowing you to create Sync entries immediately after creating the table in the migration:
class CreateSyncsTable < ActiveRecord::Migration
def self.up
create_table :syncs do |t|
t.timestamps
t.integer :remedy_query_low
t.integer :remedy_query_high
end
Sync.reset_column_information
Sync.create :remedy_query_low => 0, :remedy_query_high => 0
end
def self.down
drop_table :syncs
end
end
Personally, I would recommend removing the Sync.create :remedy_query_low => 0, :remedy_query_high => 0 statement altogether since I think Rails migrations are best used for schema migrations only, and data migrations are best put in rake tasks (a great reason why can be found here).
In this case, Sync is referring to a model. You should have a file in app/models/ called sync.rb, which is the model definition for the Sync class. This is a Rails convention for defining models.
You can use models in your migrations (you've been looking at a migration). However, it's generally not recommended to use your app's models in the migration, because you can end up with conflicts.
What's recommended is to define a proxy model in your migration, which takes the place of the app model for the purposes of the migration. You declare the proxy model at the top of your migration file, so that it's local to the migration.
Try this code:
class Sync < ActiveRecord::Base
end
class CreateSyncsTable < ActiveRecord::Migration
def self.up
create_table :syncs do |t|
t.timestamps
t.integer :remedy_query_low
t.integer :remedy_query_high
end
# Reset ActiveRecord cache of Sync details
Sync.reset_column_information
Sync.create :remedy_query_low => 0, :remedy_query_high => 0
end
def self.down
drop_table :syncs
end
end
The additional call to Sync.reset_column_information tells Rails to reset the cache of information about the model because the table structure has changed. This will prevent issues, such as trying to access the new columns added in the migration.
I have three tables in my Rails 4 app -- one for Game, Category, and Topic. Both Category and Topic have a column for :name, while Game includes information like starts_at for when a game begins.
In my PagesController, I can show data from both Game and Topic by using find_by with the params value:
topic = Topic.find_by_name(params[:topic])
#games = Game.for_topic(topic).upcoming.order(:starts_at)
This works fine.
What's weird is that when I use the same reasoning but with Category instead of Topic, like so:
category = Category.find_by_name(params[:category])
#games = Game.for_category(category).upcoming.order(:starts_at)
I receive an error message:
undefined method `for_category'
This is confusing to me since I am definitely defining category and the using it in my for_ expression. Am I making an error in my thinking?
Additional
CreateCategories Migration
class CreateCategories < ActiveRecord::Migration
def change
create_table :categories do |t|
t.belongs_to :topic, index: true
t.string :name, :null => false
t.timestamps
end
end
end
CreateTopics Migration
class CreateTopics < ActiveRecord::Migration
def change
create_table :topics do |t|
t.string :name, :null => false
t.timestamps
end
end
end
I think you setup the named scope for_topic in the Game model. But is missing the for_category, which is why it is failing.
Try setting the named scope for_category in Game model.
I'm reading Rails 3 in Action and following the commands verbatim. However, when I run the commands
rails new things_i_bought
cd things_i_bought
bundle install
rails generate scaffold purchase name:string cost:float
The book says I should get this code:
class CreatePurchases < ActiveRecord::Migration
def self.up #not created in my code
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
def self.down # not created in my code
drop_table :purchases
end
end
I get this code instead:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end
Why are the class methods up and down not being created for me? I'm using
rails 3.1.1 and ruby 1.9.2.
thanks for reading my book!
As JacobM and dbalatero have already explained, this is a new feature in Rails 3.1. This particular feature was added by Aaron Patterson as a way to simplify the migration syntax. In earlier versions of Rails, you would have to do as the book shows:
class CreatePurchases < ActiveRecord::Migration
def self.up
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
def self.down
drop_table :purchases
end
end
But that's kind of repeating yourself. Aaron created a migration syntax that looks good and is simpler, calling only the methods necessary for migrating forward, but also allowing the migrations backwards (known as a "rollback") too. The same migration written with the Rails 3.1 syntax is this:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases do |t|
t.string :name
t.float :cost
t.timestamps
end
end
end
So when this migration runs "forwards", Rails will create the purchases table with the fields. When you roll it back (or run it "backwards") then Rails will know to drop the table.
This syntax isn't entirely perfect however, and you'll run into problems with methods such as change_column. When that happens, it's best to stick with defining both the def up and def down methods in the migrations:
class CreatePurchases < ActiveRecord::Migration
def up
change_column :purchases, :cost, :integer
end
def down
change_column :purchases, :cost, :float
end
end
That's because in this example Rails won't know how to switch it back to the previous type. I hope this explains it better!
This is a new feature in Rails 3.1. For changes that Rails can figure out how to reverse, such as creating a table, you simply create a "change" method with the code that would have gone in "up", and it figures out how to do "down" on it's own.
You can also define "up" and "down" methods yourself -- for some changes (such as dropping a column) Rails won't be able to figure it out -- but the syntax is a bit different; it's not just def up instead of def self.up (they're now instance methods instead of class methods).
I believe in the new Rails 3.1, the database migration methods are self-aware about how to run an up/down migration.
Therefore, if you define a def change method, it will try to use those self-aware methods: in this case, create_table knows to do DROP TABLE in a down context, and CREATE TABLE in an up context.
If you want the old style, you can probably keep using it and define your own self.down and self.up methods as the book describes.
Edit: here's a link to the blog post on this, called "Reversible Migrations": http://www.edgerails.info/articles/what-s-new-in-edge-rails/2011/05/06/reversible-migrations/index.html
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