EDIT: This is not a dupe of Can't migrate after scaffold in Hartl's tutorial! I have Arel updated in my Gemfile just in case, but it makes no difference. Also, this is POST-migration, the rake finished just fine. However after the rake, when I try to query the association via the console, that is when I get the error!
I have two models with a simple one-to-many association between them. After adding the second model and raking the db, I opened rails console to test some stuff out, and I get an error every time I try to use the association in a query.
Here are the classes:
class Startup < ActiveRecord::Base
has_many :reqs
end
class Req < ActiveRecord::Base
belongs_to :startup
end
This is the migration for the Reqs table:
class CreateReqs < ActiveRecord::Migration
def change
create_table :reqs do |t|
t.string :title
t.text :desc
t.integer :sort
t.references :startup, index: true
t.timestamps null: false
end
end
end
And here is the simple test I'm trying to test in the console afterwards:
> startup = Startup.first
> startup.reqs ## Generates ArgumentError
> startup.reqs.build ## Generates same error
And here is the beginning of the error:
ArgumentError: wrong number of arguments (1 for 0)
from /usr/local/rvm/gems/ruby-2.1.4#rails4/gems/activerecord-4.2.0.beta4/lib/active_record/connection_adapters/abstract_adapter.rb:271:in
`initialize'
from /usr/local/rvm/gems/ruby-2.1.4#rails4/gems/activerecord-4.2.0.beta4/lib/active_record/connection_adapters/abstract_adapter.rb:271:in
I'm still getting the hang of a lot of the details of RoR, so please hang with me! But from what I thought I knew, this association seems so basic that I have no idea where to start fixing it. Thanks for your help!
I think this may have been some sort of fluke or bug in Rails. I tried again this morning and the rails console was still giving me the same error. Then just for kicks I tried adding another model that was the same, just with a different name:
class CreateSkills < ActiveRecord::Migration
def change
create_table :skills do |t|
t.string :title
t.text :desc
t.integer :sort
t.references :startup, index: true
t.timestamps
end
end
end
After adding the has_many skills to Startup.rb, I went back into Rails console and now BOTH of the associations (Startup.skills and Startup.reqs) work just fine. Out of curiosity, I did a db:rollback and destroyed the Skill model and then went back into the console. Startup.reqs still works fine even though Skill is not there anymore.
I have no idea why this would make a difference, but wanted to post what worked for me in case someone else runs into a similar issue. Try generating another model to kind of "reset" the db and then you can roll it back and everything may work for you.
Related
So I'm working with a colleague who added some additional migration files and per normal procedure once I pulled their version I ran rails db:migrate. I end up getting the following errors:
Index name 'index_authorizations_on_user_id' on table 'authorizations' already exists
ArgumentError: Index name 'index_authorizations_on_user_id' on table 'authorizations' already exists
So I went and checked the schema and the table is already present. So why is it failing? Typically in the past it only generates new table entries/updates when doing a migration so why isn't it just ignoring it?
I've tried doing a rollback and get:
This migration uses remove_columns, which is not automatically reversible.
I've tried doing bin/rails db:migrate RAILS_ENV=development and I get the same errors.
I've done a db:reset, db:drop, and it all comes back to an issue with pending migrations that I cannot get to run. What am I doing wrong?
They added the following migration: 20171024074328_create_authorizations.rb
class CreateAuthorizations < ActiveRecord::Migration[5.1]
def change
create_table :authorizations do |t|
t.string :provider
t.string :uid
t.references :user, foreign_key: true
t.timestamps
add_index :authorizations, :user_id
add_index :authorizations, [:provider, :uid], unique: true
end
end
end
This:
t.references :user, foreign_key: true
adds an index on authorizations.user_id for you. If you check the references documentation it will point you at add_reference and that says:
:index
Add an appropriate index. Defaults to true. [...]
So index: true is the default when you call t.references :user and that creates the same index that add_index :authorizations, :user_id creates.
So the only thing that I've found that "worked" was to actually delete the migration files then run rails db:migrate. Didn't catch on anything, no errors.
Not a fan of the fact that this worked.
Check if it's a table or a changed table, most times you need to drop the table or delete the column then run the migration again and it'll be good to go
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.integer :link_id
t.text :body
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
add_index :comments, :link_id
end
end
I was deploying my app to heroku and had to redo the database in Pg insteand of sqlite 3. When I migrate my database I am gettting this
NameError: uninitialized constant CreateCommments
I have been search SO all day and tried many of the solutions but to no avail. I have searched spelling errors, dropped, recreated the database. My database.yml is up to date and gem and gemlock are clean of sqlite, but it will not stop yelling at me. Thank you in advance.
The error is because the filename is incorrect. It has to be a timestamp with the class name then in snake case, like
20170602175844_create_comments.rb
You can of course do this manually and just change the filename, or run in the console and get a new migration
rails g migration create_comments
Note:
It doesn't have to be a timestamp though, that's just the way the rails rake task does it. You can also use a numerical sequence like if you create your files manually. This is just done to be able to see what migrations have already run and to be able to rollback to a specific version. Also so that the migrations run in a specific order.
1_create_comments.rb
Good afternoon,
First post here. I have done a bit of research into this error and not finding anything helpful to me, and because stackoverflow community is my number 1 place to find a answer. I thought why not ask here.
I have created a new rails app, and have created a relation between the order and order_item model.
app/models/order.rb
class Order < ActiveRecord::Base
belongs_to :customer, foreign_key: 'customer_id'
belongs_to :shop
has_many :order_items, dependent: :destroy
end
app/models/order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :order
end
The relationship between customer and order is working because I have created a record for both.
eg
Customer.create(:customer_attributes).orders.create
but when I try to access or create a order item
Customer.first.orders.first.order_items.first || Customer.first.orders.first.order_items.create
I get the following error
ActiveRecord::StatementInvalid: Could not find table 'order_order_items'
my question is, why is it looking for the table name with the prefix twice?
below is what my migration files look like for both models
db/migrate/orders
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.integer :shop_id
t.integer :customer_id
t.string :status
t.string :additional_info
t.timestamps null: false
end
end
end
db/migrate/order_items
class CreateOrderItems < ActiveRecord::Migration
def change
create_table :order_items do |t|
t.integer :order_id
t.integer :menu_item_id
t.timestamps null: false
end
end
end
Any help will be greatly appreciated. New to ruby and rails, so please excuse my lack of knowledge.
Cheers
EDITED
Hey guys! Thank for fast replies, I figured out what the problem was. Earlier in the project I had tried to implement namespacing into the models and this is what was causing the trouble. Once i moved all models directly under the app/models dir and restarted the console all worked 100%. So im guessing I dont understand enough yet of how rails handles the namespacing, but im going to try the namespacing at later stage. For now I just need a quick prototype up an running to demo to a few clients.
Once again thanks for the fast replies.
First
ruby script/generate model Buyer id:integer name:string
after generating Buyer model, I did
rake db:migrate
it was working fine.
After 1 day I have executed below command
ruby script/generate model Seller id:integer seller_name:string
after generating Seller model, I did
rake db:migrate
I got an error, that Buyer table is already exists. why? we have different timestamp file.
class CreateBuyer < ActiveRecord::Migration
def self.up
create_table :buyer do |t|
t.string :name
t.text :description
t.decimal :price
t.integer :seller_id
t.string :email
t.string :img_url
t.timestamps
end
end
def self.down
drop_table :ads
end
end
and another one is
class CreateSellers < ActiveRecord::Migration
def self.up
create_table :sellers do |t|
t.integer :nos
t.decimal :tsv
t.decimal :avg_price
t.timestamps
end
end
def self.down
drop_table :sellers
end
end
I used Rails 2.3.11 and rake 0.8.7
Are you sure there were no errors generated when you ran the first migration? If an error is encountered while running a migration, the parts that were already run will still be in the database, but schema_migrations won't be updated with the migration timestamp. Therefore, the next time you try to run migrations, it'll try to re-run the first part of the failed migration, which will generate errors since it's already been run.
Updated: If you look in the error output you added (by the way, please add to the question rather than a comment, so it's formatted and the whole thing is included) you can see that the first Execute db:migrate is running the migration CreateBuyer. This confirms that your migration did not complete the first time you ran it or has since been unsuccessfully rolled back. To fix this, manually drop the buyer table, then rerun your migrations.
As a note, there's at least a couple issues in your CreateBuyers migration:
The table name should be buyers (plural) rather than buyer (singular)
The down part of the migration is dropping the table ads instead of buyers
The second problem there could explain why you're having trouble running migrations now, actually. If you rolled back the CreateBuyers migration, it would have dropped your ads table and left buyers in place.
I created a simple example as a sanity check and still can not seem to destroy an item on either side of a has_and_belongs_to_many relationship in rails.
Whenever I try to delete an object from either table, I get the dreaded NameError / "uninitialized constant" error message.
To demonstrate, I created a sample rails app with a Boy class and Dog class. I used the basic scaffold for each and created a linking table called boys_dogs. I then added a simple before_save routine to create a new 'dog' any time a boy was created and establish a relationship, just to get things setup easily.
dog.rb
class Dog < ActiveRecord::Base
has_and_belongs_to_many :Boys
end
boy.rb
class Boy < ActiveRecord::Base
has_and_belongs_to_many :Dogs
def before_save
self.Dogs.build( :name => "Rover" )
end
end
schema.rb
ActiveRecord::Schema.define(:version => 20100118034401) do
create_table "boys", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "boys_dogs", :id => false, :force => true do |t|
t.integer "boy_id"
t.integer "dog_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "dogs", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
I've seen lots of posts here and elsewhere about similar problems, but the solutions are normally using belongs_to and the plural/singular class names being confused. I don't think that is the case here, but I tried switching the habtm statement to use the singular name just to see if it helped (with no luck). I seem to be missing something simple here.
The actual error message is:
NameError in BoysController#destroy
uninitialized constant Boy::Dogs
The trace looks like:
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/dependencies.rb:105:in const_missing'
(eval):3:indestroy_without_callbacks'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/callbacks.rb:337:in destroy_without_transactions'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:229:insend'
...
Thanks.
I don't see your destroy callback, but I do see a couple of problems. First, your associations need to be lowercase. So dog.rb should be:
class Dog < ActiveRecord::Base
has_and_belongs_to_many :boys
end
and boy.rb should be:
class Boy < ActiveRecord::Base
has_and_belongs_to_many :dogs
def before_save
self.dogs.build( :name => "Rover" )
end
end
Second, I believe you want to use self.dogs.create instead of self.dogs.build above, since build won't actually save the new dog object.
The accepted answer here solved my problem, only to create another one.
Here are my model objects:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities
end
class Amenity < ActiveRecord::Base
set_table_name "Amenities"
set_primary_key "AmenityID"
end
Rails uses the name of the association as the table name when creating the select query. My application runs on Unix against a legacy MySQL database and my table names are case-sensitive and don't conform to Rails conventions. Whenever my app actually tried to load the association, I would get an exception that MySQL couldn't find table amenities:
SELECT * FROM `amenities`
INNER JOIN `ComplexAmenities` ON `amenities`.AmenityID = `ComplexAmenities`.AmenityID
WHERE (`ComplexAmenities`.ComplexID = 147 )
I searched and searched and could not find a way to tell Rails to use the correct case for the table name. Out of desperation, I tried passing a :table_name option to habtm and it worked. My new Complex model looks like this:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities, :table_name => 'Amenities'
end
This works under Rails 2.3.5.
This option is not mentioned in the Ruby on Rails docs.