How can I add a database to my SQLite3 database?
I always get this error.
ActiveRecord::StatementInvalid in Timespans#index
Showing C:/xampp/htdocs/fluxcapacitor/app/views/timespans/index.html.erb where line #19 raised:
SQLite3::SQLException: no such table: timespans: SELECT "timespans".* FROM "timespans"
I tried adding my table to myschema.rb, but it doesn't work. It is always overwritten, when I run
rake db:migrate RAILS_ENV=development
You should generate migration:
bundle exec rails g migration create_timespans
And in the migration, you should have:
class CreateTimespans < ActiveRecord::Migration
def change
create_table :timespans
t.string :column1
t.string :column2
# ...
end
end
end
And run it with bundle exec rake db:migrate.
This is the proper way to make changes in your DB schema in Rails application.
You want to use migrations to make changes to your database. See the Active Record Migrations
guide for the details.
Generally speaking, the process is something like:
rails generate migration create_timespans generates an empty migration for you.
Edit the created migration to setup the table like you want it to. This should be pretty similar to what you've already added in schema.rb.
rake db:migrate then applies those changes to the database.
Related
I'm new to rails so maybe the record id is not updated on destroy.
I used rails scaffold to generate my MVC for a products page. When I add an entry to my data base through my products/new page it adds an id number to the entry. When in a browser if I rollover the show/edit/destroy links on my index view it will give me a url link of localhost:3000/products/1. Now if I remove the entry by using the destroy link it removes the entry correctly, but now when I add another entry it shows the id as 2 not 1. Why does it remove the entry from the database but not reset the id back to 1.
This is for the build in server in rails app sqlite3.
Sqlite is using a sequence to determine the next available integer to use for the primary id. Sequences don't "go back" even if you destroy the record with the latest one. They keep incrementing. Some databases will restart at zero once they reach a maximum, some will error.
Some databases tie a sequence to the table. However in some, sequences are their own thing. You could (if you wanted to) use a sequence to get unique ID's for several different tables.
Check sqlite's documentation for details...
The command rake db:schema:dump Dumps the current environment’s schema to db/schema.rb.
To reset it back or delete all and migrate it again you should use the command rake db:setup Which runs rake db:schema:load and rake db:seed.
Some of the other important commands are;
rake db:schema:load This command loads the schema into the current environment’s database.
rake db:schema:dump This command dumps the current environment’s schema to db/schema.rb.
rake db:setup This command runs rake db:schema:load and rake db:seed.
rake db:reset This command runs rake db:drop and rake db:setup.
rake db:migrate:reset This command runs rake db:drop then rake db:create and rake db:migrate.
you would have to rake db:drop your database (which deletes it) and then rake db:migrate to create your tables again.
How we did this in rails2 was: For a job class we set a bunch of attr_accessor methods for the job object and enqueue the object into delayed_jobs table and those accessor values are stored in the table as well. (we were using delayed_job 2.0.3)
But in rails3 even though we follow the same procedure as in rails2, the attr_accessor values are not stored into the table. Can anybody tell me how we persist the accessor values into the table with the new delayed_job gem(3.0.3)?
Found out that the problem is with the psych parser which takes into consideration only the database attributes for a model object and doesn't take into consideration instance and class variables. Here's a more precise answer for the question: YAML, delayed_job : Psych vs Syck. How to make pysch read attr_accessors for a ruby object
I'm writing a Rails system that ingests data from external sources by spawning multiple processes to fetch the data and updating a single db table. I want to write RSpec tests that spawn multiple processes that emulate the fetch/write process to look for concurrency issues.
short question
How can I initialize a table in an RSpec test so that an external process can see the contents of the table? (At least, I think that's the right question. Read on for details...)
longer form
The general structure of my RSpec test is:
it 'external task should update the correct records' do
initialize_my_model_table_with_some_records
spawn_external_tasks_to_update_records
# wait for spawned processes to complete
Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
validate_results
end
But the external process always sees the model table as empty (verified by debug printing). Subsequently, attempts to update the table fail.
I'm pretty sure this is because RSpec is holding the table under a lock so it can do a rollback after the test completes.
So (to repeat the short question): How can I initialize a table in an RSpec test so that an external process can see the initialized contents of the table?
edit #2
I notice that upon entry to a subsequent test, the table is in the state that the previous (external) processes left it. This makes sense: RSpec can only roll back the table to the state that it 'knows' about, so and changes made by external processes will persist.
This suggests a solution: It appears that it works to use a before(:all) to explicitly initialize the table. But is this is the cleanest approach?
environment
Ruby version 1.9.3 (x86_64-darwin10.8.0)
pg (0.13.2)
rails (3.2.1)
rspec (2.9.0)
rspec-rails (2.9.0)
When RSpec runs a test, it locks the database under a transaction so that it can be rolled back after the test. As a result, any external process won't see changes that RSpec makes to the database. And correspondingly, any changes that an external process makes to the database won't be rolled back after the RSpec test.
One exception to this is inside before(:all) and after(:all) blocks: any changes that RSpec makes will be visible to external processes.
So the example in the OP can be made to work like this:
describe 'with external tasks' do
before(:all)
initialize_my_model_table_with_some_records
end
after(:all)
reinitialize_my_model_table
end
it 'should update the correct records' do
spawn_external_tasks_to_update_records
# wait for spawned processes to complete
Process.waitall.each {|pid, status| status.exitstatus.should == 0 }
validate_results
end
end
If I create a table with rails generate migration, I can add an extra column to it later by creating a new migration. I could also rollback the original migration and then edit it to include the extra column.
Method 1: New Migration
//Create the model including the migration
$ rails generate model Foo bar:string
//Perform the migration
$ rake db:migrate
//Create the add column migration
$ rails generate migration add_foobar_to_foos foobar:string
//Perform the new migration
$ rake db:migrate
Method 2: Rollback
//Create the model including the migration
$ rails generate model Foo bar:string
//Perform the migration
$ rake db:migrate
//Rollback the migration
$ rake db:rollback
//Edit the original migration file
//Perform the new migration
$ rake db:migrate
What is the correct/best way to accomplish this task and why?
Ill go with method 1. why? because if other developers/machines are working with this environment you can get an inconstant state due to the fact that they might need to rollback at the right time in order to maintain correct db structure.
I am trying to setup seed data for my Rails app and am counting on the id of each model being a certain value. How can I tell the table to, after MyModel.destroy_all to start counting from 0 again instead of where it left off?
The best way is probably to drop the whole table, recreate it and then seed it. You can do this with custom rake tasks.
Try something like this to drop your table:
desc "Drop MyModel table"
task :drop_my_model => :environment do
connection = ActiveRecord::Base.connection
connection.execute("drop table my_models")
end
end
then you can rake
$ rake drop_my_model
$ rake db:migrate:up VERSION=my_version