I have an Enrollment model with a status column that is populated by a (poorly formed) seed file. Currently, all of these status values are found in the EnrollmentState column stateId (which contains negative values and is not meant to be the typical index column of a table). Here are the relevant schema tables:
db/schema.rb
create_table "enrollment_states", force: :cascade do |t|
t.integer "stateId", limit: 1, default: 0, null: false
t.string "Name", limit: 20
t.boolean "Display", limit: 1, default: false
end
create_table "enrollments", force: :cascade do |t|
t.integer "status", limit: 1, default: 0
t.integer "project_id", limit: 2, default: 0, null: false
t.integer "subjId", limit: 4, null: false
t.integer "homeId", limit: 4, null: false
t.datetime "startDate"
t.integer "RAId", limit: 4, default: 0
t.integer "eligibility_state_id", limit: 1, default: 0, null: false
t.integer "secondary", limit: 1, default: 0, null: false
t.integer "idx", limit: 4, default: 0, null: false
t.integer "enrollment_state_id", limit: 4
end
I have created the enrollment_state_id column in the Enrollment model to create an association and was hoping to populate it with the Enrollment_State id that corresponds to the status column.
I have tried to do this with the following migration:
class UpdateColumnValues < ActiveRecord::Migration
def change
Enrollment.connection.schema_cache.clear!
Enrollment.reset_column_information
Enrollment.all.each do |e|
e.update_attribute(enrollment_state_id: EnrollmentState.find_by(stateId: e.status).id)
end
end
end
However, the migration file cannot find the Enrollment data in the database! I get this error in my console after running rake db:migrate:
rake aborted!
StandardError: An error has occurred, all later migrations canceled:
Mysql2::Error: Table 'enrollment.enrollment' doesn't exist: SELECT `enrollment`.* FROM `enrollment`/Users/ben/Desktop/enrollment_app/db/migrate/20150711175101_update_column_values.rb:6:in `change'
ActiveRecord::StatementInvalid: Mysql2::Error: Table 'enrollment.enrollment' doesn't exist: SELECT `enrollment`.* FROM `enrollment`
/Users/ben/Desktop/enrollment_app/db/migrate/20150711175101_update_column_values.rb:6:in `change'
Mysql2::Error: Table 'enrollment.enrollment' doesn't exist
/Users/ben/Desktop/enrollment_app/db/migrate/20150711175101_update_column_values.rb:6:in `change'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
Any ideas why my migration file can't access my Enrollment or EnrollmentState models? Or how to do this another way maybe?
Rails can find the model fine but it is looking in the wrong table for your enrollments. As you already have discovered this is due setting the table_name of your Enrollment model.
Rails is built around strong conventions, follow them and everything tends to go pretty smoothly. Break them and you end up like a drag queen in a nazi convention.
The ActiveRecord convention is that models have a singular name (User) which corresponds to a table in the plural users. Columns which end with _id are foreign keys.
Since Rails is so strongly built on convention than the first step if you have to use an existing database structure from somewhere else should be writing migrations to beat the database into conformity. Rename columns to snake_case. Make sure any columns that reference other tables have indexes and foreign keys. This avoid stupid time consuming errors because you have done ’status_id’ (which is correct) instead of statusId.
And you will be able to pass your work to other developers without feeling ashamed.
Related
i am a newbie trying to learn ruby on rails by following the Lynda video series using ROR version 5.0 and mysql 8.02. after creating my table entries in DB>migrate>model.rb file and running "rails db:migrate" i get an error in the terminal which does not make a lot of sense to. iv using a different user and grating it mysql privileges and searching on the web but no luck.
=============================
class CreateUsers < ActiveRecord::Migration[5.0]
def up
create_table :users do |t|
t.column "first_name", :string, :limit => 25
t.string "last_name", :limit => 50
t.string "email", :default => '', :null => false
t.string "password", :limit => 40
t.timestamps
end
end
def down
drop_table :users
end
end
MBP:simple_cms $ rails db:migrate
rails aborted!
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown collation: 'utf8_0900_ai_ci': CREATE TABLE schema_migrations (version varchar(255) COLLATE utf8_0900_ai_ci PRIMARY KEY) ENGINE=InnoDB
/Users/.rvm/gems/ruby-2.3.0/gems/mysql2-0.4.9/lib/mysql2/client.rb:120:in _query'
/Users/.rvm/gems/ruby-2.3.0/gems/mysql2-0.4.9/lib/mysql2/client.rb:120:inblock in query'
/Users/.rvm/gems/ruby-2.3.0/gems/mysql2-0.4.9/lib/mysql2/client.rb:119:in handle_interrupt'
/Users/.rvm/gems/ruby-2.3.0/gems/mysql2-0.4.9/lib/mysql2/client.rb:119:inquery'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:218:in block in execute'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract_adapter.rb:590:inblock in log'
/Users/.rvm/gems/ruby-2.3.0/gems/activesupport-5.0.6/lib/active_support/notifications/instrumenter.rb:21:in instrument'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract_adapter.rb:583:inlog'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:218:in execute'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/mysql/database_statements.rb:31:inexecute'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract/schema_statements.rb:278:in create_table'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:423:increate_table'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/schema_migration.rb:27:in create_table'
/Users/.rvm/gems/ruby-2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/abstract/schema_statements.rb:1008:ininitialize_schema_migrations_table'
There was an issue related to your problem : https://github.com/rails/rails/issues/28730
This has been fixed in rails v5.1.0.rc2. Upgrading to the latest version and regenerating schema.rb should eliminate your problem.
Also it's possible to add general collation to your database.yml if utf8_0900_ai_ci doesn't work:
development:
adapter: mysql2
...
encoding: utf8
collation: utf8_general_ci
in my clients table, I have a column named email. But when I made the tests for the clients controller and the model, the tests kept on saying that the clients table has no column named email.
SQLite3::SQLException: table clients has no column named email: CREATE UNIQUE INDEX "index_clients_on_email" ON "clients" ("email")
although I do admit that I didn't initially put that column when I created my table, but I added the column via a separate migration. I ran rake db:migrate and even tried rake db:drop:all, rake db:create:all and then rake db:migrate and it still didn't change anything.
the email column was also added as an index for the clients table.
this is my schema:
ActiveRecord::Schema.define(version: 20161230163248) do
create_table "clients", force: :cascade do |t|
t.string "name", null: false
t.text "email", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "clients", ["email"], name: "index_clients_on_email", unique: true
create_table "projects", force: :cascade do |t|
t.text "project_description", null: false
t.string "project_timescale"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "client_id"
end
add_index "projects", ["client_id"], name: "index_projects_on_client_id"
end
the initial migration for the clients table:
class CreateClients < ActiveRecord::Migration
def change
create_table :clients do |t|
t.string :name, presence: true, null: false
t.timestamps null: false
end
end
end
migration to add email as an index for the client table:
class AddIndexToClient < ActiveRecord::Migration
def change
add_index:clients, :email, unique: true
end
end
migration to add the email column:
class AddEmailToClient < ActiveRecord::Migration
def change
add_column :clients, :email, :text
end
end
the following is my database.yml:
# SQLite version 3.x
# gem install sqlite3
#
# Ensure the SQLite 3 gem is defined in your Gemfile
# gem 'sqlite3'
#
default: &default
adapter: sqlite3
pool: 5
timeout: 5000
development:
<<: *default
database: db/development.sqlite3
# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
database: db/test.sqlite3
production:
<<: *default
database: db/production.sqlite3
Try:
RAILS_ENV=test bundle exec rake db:schema:load
I have a table admin_users. Model named AdminUser.
Schema is
ActiveRecord::Schema.define(version: 20130915031734) do
create_table "admin_users", force: true do |t|
t.string "first_name", limit: 25
t.string "last_name", limit: 50
t.string "email", limit: 100, default: "", null: false
t.string "username", limit: 25
t.datetime "created_at"
t.datetime "updated_at"
t.string "password_digest"
end
add_index "admin_users", ["username"], name: "index_admin_users_on_username", using: :btree
How can I insert values into the table ??
I tried this ( Image below)
Using rails console
It is best to use a db/seeds.rb file and run rake db:seed (or similar mechanism) to populate a database.
Within a migration you have access to the full application environment. That means you can use your model classes, but since models can change over time it is not very safe to reference them within migrations. In migrations you may also execute arbitrary SQL using the execute method.
With the file db/seeds.rb, the Rails have given us a way of feeding default values easily and quickly to a fresh installation. This is a normal Ruby program within the Rails environment. You have full access to all classes and methods of your application.
So you do not need to enter everything manually with rails console in order to make the records created in the section called “create” available in a new Rails application, but you can simply use the following file db/seeds.rb:
Sample Code.
Country.create(name: 'Germany', population: 81831000)
Country.create(name: 'France', population: 65447374)
Country.create(name: 'Belgium', population: 10839905)
Country.create(name: 'Netherlands', population: 16680000)
Other than Seeds, you can use migration file for the same.
ActiveRecord::Schema.define(version: 20130915031734) do
create_table "admin_users", force: true do |t|
t.string "first_name", limit: 25
t.string "last_name", limit: 50
t.string "email", limit: 100, default: "", null: false
t.string "username", limit: 25
t.datetime "created_at"
t.datetime "updated_at"
t.string "password_digest"
end
add_index "admin_users", ["username"], name: "index_admin_users_on_username", using: :btree
/*Add your script here to insert some predifined value.*/
AdminUsers.create(first_name: 'Nair', email: 'nair#gmail.com', username: 'nairg' )
AdminUsers.create(first_name: 'Nair1', email: 'nair1#gmail.com', username: 'nairg1' )
AdminUsers.create(first_name: 'Nair2', email: 'nair2#gmail.com', username: 'nairg2' )
/* ... So on as per your requirement */
end
To Generate Seed file : Generating Seeds Blog
you can make create method in controller to save data,
def create
#admin_user = Admin_user.new(admin_users_params)
if #admin_user.save
redirect_to :action => "index"
else
render action: 'new'
end
end
def admin_users_params
params.require(:admin_user).permit(:first_name, :last_name, :email, :username)
end
I have an MS SQL Server 2012 instance with managment studio and I have schema.rb file which contains the following:
# This file is auto-generated from the current state of the database.
# Note that this schema.rb definition is the authoritative source for your database schema.
ActiveRecord::Schema.define(:version => 20120525100324) do
create_table "academic_details", :force => true do |t|
t.integer "registration_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "additional_exam_groups", ["school_id"], :name => "index_additional_exam_groups_on_school_id", :limit => {"school_id"=>nil}
create_table "additional_exam_scores", :force => true do |t|
t.integer "student_id"
t.integer "additional_exam_id"
t.decimal "marks", :precision => 7, :scale => 2
t.integer "grading_level_id"
t.string "remarks"
t.boolean "is_failed"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "school_id"
end.................etc.
How to generate SQL Server database from that file?
First, is your Rails app properly configured to use MS SQL Server 2012 as its DB?
If so, try running rake db:schema:load task.
If that doesn't work, try running the rake db:setup task.
You can find more detailed information about the rake tasks here in this previous Stackoverflow answer: https://stackoverflow.com/a/10302357/631834
I want to add another index column to my index table,but receive an index on table is too long; the limit is 64 characters. Rails 3 and MySQL DB by the way.
The current schema is as follows:
create_table "admin_users_projects", :force => true do |t|
t.integer "admin_user_id"
t.integer "project_id"
end
add_index "admin_users_projects", ["admin_user_id", "project_id"], :name => "index_admin_users_projects_on_admin_user_id_and_project_id"
I am trying to run the following migration to add the index:
class AddIndexToAdminUsersProjects < ActiveRecord::Migration
def change
add_index :index_admin_users_projects_on_admin_user_id_and_project_id, :admin_users_project_id
end
end
But get the following when attempting the rake (in short):
Larrys-MacBook-Pro:scrumtool larrydavid$ rake db:migrate
== AddIndexToAdminUsersProjects: migrating ===================================
-- add_index(:index_admin_users_projects_on_admin_user_id_and_project_id, :admin_users_project_id)
rake aborted!
An error has occurred, all later migrations canceled:
Index name 'index_index_admin_users_projects_on_admin_user_id_and_project_id_on_admin_users_project_id' on table 'index_admin_users_projects_on_admin_user_id_and_project_id' is too long; the limit is 64 characters
[...]
Try this
class AddIndexToAdminUsersProjects < ActiveRecord::Migration
def change
add_index :admin_users_project, [:admin_users_id, :project_id], :name => 'index_admin_projects_on_admin_and_project'
end
end