I want to prefill my database with the db/seeds.rb but got an error during execution.
The schema is loaded and setup perfectly. But when I will prefill the database with rake db:seed i got this error:
uninitialized constant Clients_courses
I have got the Table clients_courses in my database schema. So I've tried to prefill it like this:
Clients_courses.create(:client_id => 6, :course_id => 2)
What's wrong with this?
I've tried it with some other tables as well for example with the users table. But theres the same problem.
You should have corresponding model to manipulate data like this. For users table you usually have User model. In your case you either have ClientsCourses or ClientsCourse model, or, assuming you have :has_and_belongs_to_many association there is no such model.
And in this case, the only way to do what you want is to use existing ones(Client and Course):
Client.find(6).courses << Course.find(2)
Create a model ClientsCourse
ie in app/model/clients_course.rb
Inside the file add line below and save
class ClientsCourse < ActiveRecord::Base
end
Correct the line as below
ClientsCourse.create(:client_id => 6, :course_id => 2)
Hope that helps
your model name should be client_course.rb and a table named client_courses
Related
Right now my approach is to list every table one at a time and call .delete_all on it. Which is repetitive:
Example:
#app/db/seeds.rb
Blog.delete_all
Person.delete_all
Post.delete_all
User.delete_all
Author.delete_all
Book.delete_all
# ... on and on for all the tables
And then of course run rake db:seed which would clear out all the records for those above tables.
Is there a command that does exactly what I want:
deletes all the records from all the tables without deleting the tables themselves?
Or, is there a way to iterate through all my tables and .delete_all on each table?
Is there a command that does exactly what I want: deletes all the
records from all the tables?
bundle exec rake db:reset
This is functionally equivalent to rake db:drop db:setup.
Don't want delete the tables?
#app/db/seeds.rb
[Blog, Person, Post, User, Author, Book].each do |table|
ActiveRecord::Base.connection.execute("TRUNCATE #{table.table_name}")
end
SQL-TRUNCATE
As the OP has asked to delete all the record in all the tables, and not all the tables. So you can get all the tables by: ActiveRecord::Base.connection.tables, it will give you all you tables in the database.
puts ActiveRecord::Base.connection.tables
ActiveRecord::Base.connection.tables.each do |table|
next if table.match(/\Aschema_migrations\Z/)
klass = table.singularize.camelize.constantize
klass.delete_all
end
Edit:
If you do want id to start again from 1, when you create a new instance after emptying the table, you have to destroy the table, and re-create it.
ActiveRecord::Migration.drop_table(:users)
ActiveRecord::Migration.create_table(:users)
And now if you create a new instance of model User, it will start generating ids right from 1. Please note that you need to send the name of the table in drop_table, and create_table functions, while the code that I've written above gives you the name of the class, in this case User. You can get the table name if you have the name of the model:
User.table_name # it will give you "users"
# in above code, you can do:
ActiveRecord::Migration.drop_table(klass.table_name)
# string and symbol: both type of arguments work here!
If you really want to write ruby code to do this, try using ObjectSpace to get every instance of a Class, then select classes which inherit from ActiveRecord::Base
models = ObjectSpace.each_object(Class).select { |klass| klass < ActiveRecord::Base }
models.each{|m|m.delete_all}
However, the answers suggesting different rake tasks, instead of including this in seeds.rb are probably a better solution to your problem.
If you force rails to load all your models you can then iterate over them
Rails.application.eager_load!
# This only gets direct subclasses, since we are just deleting
# No reason to get their subclasses
models = ActiveRecord::Base.subclasses
models.each(&:delete_all)
I added those lines to my seeds.rb file. With this code, you don't have to bother with referencing manually your models and/or with foreign key constraints (thanks to disable_referential_integrity).
Rails.application.eager_load!
ActiveRecord::Base.connection.disable_referential_integrity do
ApplicationRecord.descendants.each do |model|
model.delete_all
end
end
NB : ApplicationRecord.descendants returns only true application models unlike ActiveRecord::Base.descendants (no more ApplicationRecord, schema_migrations and ar_internal_metadata).
I would like to know why I am getting an error when I am building a record using FactoryGirl.
Comment model belongs to user and commentable through polymorphic association.
My factory looks like this:
FactoryGirl.define do
factory :comment do
text "Some text"
user_id 1
association :commentable, factory: :feedback
end
end
When I'm build a comment record using FactoryGirl, I get:
ActiveModel::MissingAttributeError:
can't write unknown attribute `commentable_type'
I have no problem creating and manipulating Comment object in console. I can set and save commentable_type attribute freely. Also, commentable_type already exists in the comments table.
Any thoughts on why the error occurs?
I ran all my migrations again using rake db:reset and now the error has disappeared. Before that, I have tried to rollback the related migration and migrate again, but that did not make any change.
I still do not know what caused this error, but for now, it is fixed.
I am having a hard time extending an existing model to include two references to a single table.
My current model is called Order and I need two references (payment_state and delivery_state) to the State table.
It is my understanding that I should run the following command:
rails g migration AddStatesToOrder payment_state:references delivery_state:references
However, the following line comes up in my schema.rb after running rake db:migrate:
# Could not dump table "orders" because of following NoMethodError
# undefined method `[]' for nil:NilClass
Any help would be greatly appreciated. Thanks!
You should do like this:
rails g migration AddStatesToOrder payment_state_id:integer delivery_state_id:integer
And define the relation like this in the model:
belongs_to :payment_state, class_name: State.model_name
belongs_to :delivery_state, class_name: State.model_name
Why using :integer instead of :references? Because the thing you want to do is not "conventional", it is a customized double-relation to the same model, and Rails cannot guess it for you.
I am new to RoR. I used "rails generate model ServiceConfigs" command to generate a table.
so may commands are as below
rails generate model ServiceConfigs configs:string
rake db:migrate
-- can see app/db/service_config.rb created.
Now edited service_config.rb file to add 2 columns and which has a foreign key relation to service table. So here is code
class ServiceConfigs < ActiveRecord::Base
belongs_to :service, :dependent => :destroy
validates_presence_of :configs
end
Now when I login to underline database, and look at the table I don't see foreign key relation in table schema. Whats wrong/more I need to do?
highly appreciate your time and help
Krishna
So a few notes for you as you're getting started here: Firstly, I'd name your model in the singular form, as though you are describing a single instance of it: ServiceConfig and in the case where it belongs to a service, you may want to think of a different name all together.
Secondly validates_presence_of suggests that you have that field, so firstly, I'd remove the validation until you know that your DB has that column and that the migration worked. You can make sure by looking at your migration file and confirming that the column is being created.
You can define the relationship the "rails way" in your migration too:
http://guides.rubyonrails.org/association_basics.html
create_table :service_configs do |t|
t.string :configs
t.references :service
t.timestamps
end
Update
If you want to rerun a particular migration run:
rake db:migrate:redo VERSION=20100421175455
You can take a look in your schema to see what migration you are currently at as well. And you can also take a look at the schema to see what your DB is expected to look like as well.
I have a user model that checks to see if a value has changed before_save (by running User.zipcode_changed?). The idea is that this will queue up a delayed job if it has.
Problem is, when I migrate the app from scratch I get an error:
An error has occurred, all later migrations canceled:
undefined method `postcode_changed?' for #<User:0x105db6158>
Therefore, where should I be putting these? Is the model the wrong place?
When you checkout a new project from scratch, you shouldn't use migrations to build the database.
You should use rake db:schema:load instead.
Let me show you why.
Let's assume you create a new Post model with a post table on migration 10.
On migration 11, you execute some special elaborations on the Post model.
After a while, you decide to drop the Post model and the post table because no longer required.
Six month later, you checkout the project from scratch. If you try to run rake db:migrate the migration 11 will fail complaining about missing model. It's true, the model has been removed many month before and it's no longer available.
Instead, if you run rake db:schema:load you'll initialize the database with the right schema version.
Talking about migrations, if you just created the postcode method and you are trying to use the _changed? magic method in the same migration, you need to reload the schema before.
class MigrationFile < ...
self.up
add_column :user, :postcode, :string
User.all.each { |user| puts user.postcode_changed? } # will fail
User.reset_column_information
User.all.each { |user| puts user.postcode_changed? } # now it works
end
...
end
You say both zipcode_changed? and postcode_changed? in your question. What's the actual column name in your database - zipcode or postcode? ActiveRecord will only create the _changed? convenience method for the actual column name.
What you are doing is reasonable model code, but not so good in a migration.
Using model code in your migrations is problematic because of problems like this. I recommend sticking with SQL-oriented code.