class AddAttachmentAvatarToLists < ActiveRecord::Migration[7.0]
def change
create_table :lists do |t|
t.attachment :avatar
t.timestamps
end
end
end
The error is as follows and I cannot figure out how to fix it - any more experienced people know what I am doing wrong?
Paperclip doesn't seem to work on Rails 7. There's a fork that might work for you - see reported issue at https://github.com/thoughtbot/paperclip/issues/2698
Related
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.
I have what I think is a pretty simple migration. For some reason I get an IrreversibleMigration error when I try to db:rollback or db:migrate:redo.
The migration runs smoothly, but I'd rather keep it reversible. I can't figure out why it's not as written. Any ideas?
Here's the migration:
class AddWhyHypAndWhyHypeToStatements < ActiveRecord::Migration
def change
change_table :statements do |t|
t.rename :description, :why_hypocritical
t.text :why_hypothetical
end
end
end
If it matters, "description" column is a text column. I'm using Rails 3.1/Ruby 1.9.2/PostgreSQL. Thanks for any help.
Looks like Rails has troubles reverting change_table method. Try doing it that way instead:
class AddWhyHypAndWhyHypeToStatements < ActiveRecord::Migration
def change
rename_column :statements, :description, :why_hypocritical
add_column :statements, :why_hypothetical, :text
end
end
You can see the list of commands that can be inverted in the docs or in Rails Guides.
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
when you generate a model in rails, and it creates a skeleton migration file.
in has
create_table :model_names do |t|
t.string :name
t.string :address
t.timestamps
end
What object is being passed in as t.
When I read this part of the book I wondered what t was, but it never explained. Then later I learned in the form_for helper which passes an |f| into its block, that the f was a FormBuilder object, and this made me come here and ask. I mean, it obviously isn't important, but it bugs me when knowledge is missing.
the answer is ActiveRecord::ConnectionAdapters::TableDefinition
how do I know?
class CreateFoos < ActiveRecord::Migration
def change
create_table :foos do |t|
puts "the answer is: " + t.class.to_s
t.string :foo
t.timestamps
end
end
end
Playing with pry (or the ruby debugger) is a fun, easy way to explore.
class CreateFoos < ActiveRecord::Migration
def change
create_table :foos do |t|
binding.pry
end
end
end
Things like the apidock docs often provide answers in actual text. When they don't, viewing the source often leads to the answer in relatively short order (it does, in this case).
Let's say I'm starting out with this model:
class Location < ActiveRecord::Base
attr_accessible :company_name, :location_name
end
Now I want to refactor one of the values into an associated model.
class CreateCompanies < ActiveRecord::Migration
def self.up
create_table :companies do |t|
t.string :name, :null => false
t.timestamps
end
add_column :locations, :company_id, :integer, :null => false
end
def self.down
drop_table :companies
remove_column :locations, :company_id
end
end
class Location < ActiveRecord::Base
attr_accessible :location_name
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :locations
end
This all works fine during development, since I'm doing everything a step at a time; but if I try deploying this to my staging environment, I run into trouble.
The problem is that since my code has already changed to reflect the migration, it causes the environment to crash when it attempts to run the migration.
Has anyone else dealt with this problem? Am I resigned to splitting my deployment up into multiple steps?
UPDATE It appears I am mistaken; when migrating a coworker's environment we ran into trouble, but staging updated without issue. Mea Culpa. I'll mark #noodl's reply as the answer to bury this, his post is good advice anyway.
I think the solution here is to not write migrations which have any external dependencies. Your migrations should not depend on the past or current state of your model in order to execute.
That doesn't mean that you can't use your model objects, just that you shouldn't use the versions found in whatever version of your code happens to be installed when you run a particular migration.
Instead consider redefining your model objects within your migration file. In most cases I find that an empty model class extending ActiveRecord::Base or a very stripped down version of the model class I was using at the time I wrote the migration allows me to write a reliable, future proof, migration without needing to convert ruby logic into SQL.
#20110111193815_stop_writing_fragile_migrations.rb
class StopWritingFragileMigrations < ActiveRecord::Migration
class ModelInNeedOfMigrating < ActiveRecord::Base
def matches_business_rule?
#logic copied from model when I created the migration
end
end
def self.up
add_column :model_in_need_of_migrating, :fancy_flag, :boolean, :default => false
#do some transform which would be difficult for me to do in SQL
ModelInNeedOfMigrating.all.each do |model|
model.update_attributes! :fancy_flag => true if model.created_at.cwday == 1 && model.matches_business_rule?
#...
end
end
def self.down
#undo that transformation as necessary
#...
end
end
What error are you getting when you run the migrations? You should be fine as long as your rake files and migrations don't use your models (and they shouldn't).
You'll also want to switch the order of your drop_table and remove_column lines in the self.down of your migration.