Unable to delete tables in schema.rb from rails app - ruby-on-rails

I use Rails 4.0 and Ruby 2.3.0
I have a small Rails App. At first I wanted to assign different roles to each user based what he/she had signed up for. So i tried out the "Royce" gem from https://github.com/MartinJNash/Royce
I uninstalled it after seeing that it was too complicated for my requirements.
Then I tried the "simple-roles" gem to see how it works from here https://github.com/stanislaw/simple_roles. I uninstalled tat too. I ran db:migrate when I had these 2 gems in my app.
Now I don't want the corresponding tables from these two gems in my schema.rb. Its not exactly interfering with my app, but I would like to delete them.
The following is my schema.rb file
ActiveRecord::Schema.define(version: 20160911213902) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "roles", force: :cascade do |t|
t.string "name"
t.integer "resource_id"
t.string "resource_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree
add_index "roles", ["name"], name: "index_roles_on_name", using: :btree
create_table "royce_connector", force: :cascade do |t|
t.integer "roleable_id", null: false
t.string "roleable_type", null: false
t.integer "role_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "royce_connector", ["role_id"], name: "index_royce_connector_on_role_id", using: :btree
add_index "royce_connector", ["roleable_id", "roleable_type"], name: "index_royce_connector_on_roleable_id_and_roleable_type", using: :btree
create_table "royce_role", force: :cascade do |t|
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "royce_role", ["name"], name: "index_royce_role_on_name", using: :btree
create_table "sessions", force: :cascade do |t|
t.string "session_id", null: false
t.text "data"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", unique: true, using: :btree
add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree
create_table "users", force: :cascade do |t|
t.string "email"
t.string "name"
t.string "login_token"
t.datetime "login_token_valid_until"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users_roles", id: false, force: :cascade do |t|
t.integer "user_id"
t.integer "role_id"
end
add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree
create_table "vendors", force: :cascade do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "visits", force: :cascade do |t|
t.string "country"
t.datetime "visited_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
Even though i have un-installed the 2 roles-gems, everytime I run rake db:migrate, I get the above schema.
I am using only the "sessions" and "vendors" tables in my app.
Any idea what I should do to get rid of these unwanted tables?

Firstly check if the table is present...in rails console...
##to view all tables
ActiveRecord::Base.connection.tables
i use rails console to delete tables directly...
ActiveRecord::Base.connection.execute("drop table table_name")
###========OR===============
ActiveRecord::Migration.drop_table(:table_name)
###=========OR===============
ActiveRecord::Migration.drop_table("table_name")
###=========WITH EXAMPLE===============
ActiveRecord::Base.connection.drop_table :subscriptions
Then,delete the migration file or rename it again by changing timestamp and again run rake db:migrate
Hope it helps :)

Look in your app/db/migrate directory. Find and delete the migrations associated with those gems.
Once the migration files are removed, you can run rake db:migrate again. Then run rake db:schema:dump and check the newly generated schema.rb file to make sure you're not retaining any tables for the gems you removed.

Related

rails eager loading for one-to-many association

I have
class Article < ActiveRecord::Base
has_one :template
end
and
class Template < ActiveRecord::Base
has_many :articles
end
where Template model has got a room property. Now i'd like to build a list of all articles, where the articles template has a certain room value (say "bath").
I thought this is done by eager loading (resp: includes), but if i try
Article.includes(:template)
I get the error
SELECT "templates".* FROM "templates" WHERE "templates"."article_id" IN ('51', '52', '53', '54')
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column templates.article_id does not exist
LINE 1: SELECT "templates".* FROM "templates" WHERE "templates"."art...
What am I doing wrong?
EDIT
here's my schema.rb as asked
# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160913122551) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "articles", force: :cascade do |t|
t.string "title"
t.text "details"
t.integer "value_eur"
t.integer "deposit_eur"
t.integer "location_id"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "picture"
t.float "rate_eur"
t.string "rate_interval"
t.integer "template_id"
t.integer "quality"
end
add_index "articles", ["location_id"], name: "index_articles_on_location_id", using: :btree
add_index "articles", ["template_id"], name: "index_articles_on_template_id", using: :btree
add_index "articles", ["user_id"], name: "index_articles_on_user_id", using: :btree
create_table "locations", force: :cascade do |t|
t.string "street_and_no"
t.string "postcode"
t.string "city"
t.string "country"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "latitude"
t.float "longitude"
end
add_index "locations", ["user_id"], name: "index_locations_on_user_id", using: :btree
create_table "templates", force: :cascade do |t|
t.string "title"
t.text "details_hint"
t.float "rate_eur"
t.string "rate_interval"
t.string "picture"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "room"
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "role"
t.string "nickname"
t.string "firstname"
t.string "lastname"
t.string "phoneno"
t.boolean "showemail"
t.boolean "showphone"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["nickname"], name: "index_users_on_nickname", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_foreign_key "articles", "locations"
add_foreign_key "articles", "templates"
add_foreign_key "articles", "users"
add_foreign_key "locations", "users"
end
Your templates table does not have an article_id column according to the schema.rb you posted so you will need to create that reference.
Change
has_one :template
in the articles model to
belongs_to :template

RoR: Cannot Migrate Database to Heroku

I am having trouble migrating my database to Heroku. I have checked the other issues that address this to no avail. I can really use a second pair of eyes on my code to help me figure this out.
This is the error I get:
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::UndefinedTable: ERROR: relation "props" does not exist
: ALTER TABLE "comments" ADD CONSTRAINT "fk_rails_1d3f70cf04"
FOREIGN KEY ("prop_id")
REFERENCES "props" ("id")
It seems to get caught while migrating this file:
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :commenter
t.text :body
t.references :prop, index: true, foreign_key: true
t.timestamps null: false
end
end
end
This is the migration file where I create the table props:
class CreateProps < ActiveRecord::Migration
def change
create_table :props do |t|
t.string :title
t.text :text
t.references :user, index: true, foreign_key: true
t.timestamps null: false
end
end
end
My schema is here:
ActiveRecord::Schema.define(version: 20160528205746) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "answers", force: :cascade do |t|
t.string "choice"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "created_by"
t.integer "user_id"
t.integer "prop_id"
end
create_table "comments", force: :cascade do |t|
t.string "commenter"
t.text "body"
t.integer "prop_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "comments", ["prop_id"], name: "index_comments_on_prop_id", using: :btree
create_table "props", force: :cascade do |t|
t.string "title"
t.text "text"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "choice"
t.string "answer"
t.integer "answerId"
end
add_index "props", ["user_id"], name: "index_props_on_user_id", using: :btree
create_table "user_answers", force: :cascade do |t|
t.integer "user_id"
t.integer "answer_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: :cascade do |t|
t.string "username"
t.string "email"
t.integer "score", default: 0
t.integer "prop_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "created_by"
t.boolean "admin", default: false
t.integer "answers_id"
t.integer "answer_id"
end
add_index "users", ["answer_id"], name: "index_users_on_answer_id", using: :btree
add_index "users", ["prop_id"], name: "index_users_on_prop_id", using: :btree
create_table "wins", force: :cascade do |t|
t.string "correctAnswer"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "wins", ["user_id"], name: "index_wins_on_user_id", using: :btree
add_foreign_key "users", "answers"
end
The problem is you are creating a reference to a table that is not yet created. Remove the reference from that migration to props, then add the props table and then add a migration implementing the association. If you dont need the data currently in the db I would do a "rake db:drop" and edit the migration files (only if you arent collaborating with others!)
Update:
Do rails g migration add_ref_to_comments
Then edit the migration to have:
def change
add_reference :props, :comment, index: true
end

Add constraint to table from Rails - ActiveRecord

I have two associated models in Rails. User, and Post.
Whilst adding a boolean value column, 'Avatar' to the posts table, I would like to make a true value unique to the user to which it belongs.
In other words users can only have one 'Avatar' post with a value of true. This is because these posts (which are pictures) can be used as a users Avatar.
The posts already belong to users, and users have many posts, so I would like to set the constraint that users only have one post with a value of true for Avatar. Also if a new Avatar is uploaded/selected, then for this action to cancel out and falsify any previous Avatar.
This is my migration file so far:
add_avatar_to_user_profiles.rb
class AddAvatarToUserProfiles < ActiveRecord::Migration
def change
add_column :posts, :avatar, :boolean, default: false
end
end
schema.rb
ActiveRecord::Schema.define(version: 20151018160617) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "comments", force: :cascade do |t|
t.text "comment"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "post_id"
t.integer "user_id"
end
add_index "comments", ["post_id"], name: "index_comments_on_post_id", using: :btree
add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree
create_table "posts", force: :cascade do |t|
t.string "caption"
t.integer "likes"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"
end
add_index "posts", ["user_id"], name: "index_posts_on_user_id", using: :btree
create_table "sessions", force: :cascade do |t|
t.string "session_id", null: false
t.text "data"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", unique: true, using: :btree
add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.string "provider"
t.string "uid"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["provider"], name: "index_users_on_provider", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["uid"], name: "index_users_on_uid", using: :btree
add_foreign_key "comments", "posts"
add_foreign_key "comments", "users"
add_foreign_key "posts", "users"
end
Hoping the above is enough to make sense, I have searched docs to no avail, am thinking the solution should be simple enough.
You can add a custom validator in your Post model like this:
# post.rb
validate :unique_post_avatar
private
def unique_post_avatar
if self.user.posts.select { |p| p.avatar == true }.count > 1
errors.add(:avatar, "only one post avatar for this user can be true")
end
end
which is essentially selecting the user's posts where the avatar is true. If this count is greater than one, then it will throw validation error. I think this is what you are looking for :-)

Rails Confused with refrential integrity

The more i read about foreign keys in rails i am getting more and more confused. In a post i read that its sufficient to add belongs_to and has_many/has_one in respective model file to getting things done. But again in another post I read that the index should be added to reference another table. Suppose There is writers table and book table in dbms while creating Books table we have to add
FOREIGN KEY (writers_Id) REFERENCES Writers(Id)
but in rails we in writer model we add has_many :book an in book model we add belongs_to :writer is both are equivalent ?
If both are equivalent then why we add index such as
add_index :books, :writer_id
I have project on which I am working on it has users has one personal information, academic information, application and rank. Also there is subject_streams which have streams and streams have cutoffs. Finally there is category which is independent. I dont know if i modeled data correctly but in the schema.rb am I doing correctly what i have said ?
ActiveRecord::Schema.define(version: 20140713133617) do
create_table "academics", force: true do |t|
t.integer "user_id"
t.integer "tenth_roll", default: 0
t.integer "tenth_year_pass", default: 2000
t.decimal "tenth_marks_percent", precision: 10, scale: 2, default: 40.0
t.string "tenth_board"
t.integer "hs_roll", default: 0
t.integer "hs_year_pass", default: 2002
t.decimal "hs_marks_percent", precision: 10, scale: 2, default: 40.0
t.string "hs_board"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "calculated_marks"
t.string "sub1"
t.integer "sub1_marks"
t.string "sub2"
t.integer "sub2_marks"
t.string "sub3"
t.integer "sub3_marks"
t.string "sub4"
t.integer "sub4_marks"
t.string "sub5"
t.integer "sub5_marks"
t.string "sub6"
t.integer "sub6_marks"
t.string "sub7"
t.integer "sub7_marks"
t.string "sub8"
t.integer "sub8_marks"
t.string "sub9"
t.integer "sub9_marks"
t.string "sub10"
t.integer "sub10_marks"
t.integer "subject_streams_id"
end
add_index "academics", ["user_id"], name: "index_academics_on_user_id", unique: true, using: :btree
create_table "applications", force: true do |t|
t.integer "user_id"
t.integer "stream_id"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "verified", default: false
end
add_index "applications", ["user_id"], name: "index_applications_on_user_id", unique: true, using: :btree
create_table "categories", force: true do |t|
t.string "category"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "cutoffs", force: true do |t|
t.integer "stream_id"
t.integer "category_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "cutoff_marks"
end
add_index "cutoffs", ["stream_id"], name: "index_cutoffs_on_stream_id", using: :btree
create_table "personals", force: true do |t|
t.integer "user_id"
t.date "date_of_birth"
t.string "gender"
t.string "blood_group"
t.string "fathers_name"
t.string "mothers_name"
t.text "address_present"
t.datetime "created_at"
t.datetime "updated_at"
t.string "first_name"
t.string "middle_name"
t.string "last_name"
t.integer "category_id"
t.string "image"
t.string "avatar"
end
add_index "personals", ["user_id"], name: "index_personals_on_user_id", unique: true, using: :btree
create_table "ranks", force: true do |t|
t.integer "user_id"
t.integer "rank"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "ranks", ["user_id"], name: "index_ranks_on_user_id", unique: true, using: :btree
create_table "registers", force: true do |t|
t.boolean "active"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "simple_captcha_data", force: true do |t|
t.string "key", limit: 40
t.string "value", limit: 6
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "simple_captcha_data", ["key"], name: "idx_key", using: :btree
create_table "streams", force: true do |t|
t.string "stream"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "seats"
t.integer "subject_stream_id"
end
add_index "streams", ["subject_stream_id"], name: "index_streams_on_subject_stream_id", using: :btree
create_table "subject_streams", force: true do |t|
t.string "subject_stream"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "level", default: 1
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
In Ruby on Rails, the code has_many :books and belongs_to :writer is like defining relationships in the code level. It doesnt achieve anything in the database level. For example, if we write belongs_to :writer in the Book model, it just means that if there is a column writer_id in the books table, we can code something like this:
b = Book.first
b_writer = b.writer
#### equivalent to
# b_writer = Writer.find(b.writer_id)
# b_writer = Writer.where(:id => b.writer_id).first
# or b_writer = Writer.find_by_sql("SELECT writers.* from writers where writers.id = #{b.writer_id}")
It assumes that the foreign key is writer_id in books table by convention. If we need to change the foreign key for the queries generated by association, we need to specify it separately:
belongs_to :writer, :foreign_key => 'writerID'
So, in general declaring associations in models, gives us some utility methods to query those associations from database, instead of creating the queries manually. So, all the database related changes needs to be done in the migrations, like adding the column writer_id, adding index for column writer_id, setting writer_id with forieign key constraint etc. Rails does not support foreign_key constraint in migrations by default, as different databases handle foreign_key differently. For PostGre and MySQL database, you can use foreigner gem for adding foreign_key constraint.
Please read more about Rails associations

Unable to Migrate/Seed Database - Postgres Rails

Very odd problem
I am trying to migrate my database but I keep getting:
PG::UndefinedTable: ERROR: relation "users" does not exist
Here is my migration:
class AddRoleToUser < ActiveRecord::Migration
def up
add_column :users, :role_id, :integer
end
def down
remove_column :users, :role_id
end
end
And my schema:
ActiveRecord::Schema.define(version: 20140205191602) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "horseraces", force: true do |t|
t.integer "horse_id"
t.integer "race_id"
t.datetime "entered"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "horses", force: true do |t|
t.string "name"
t.string "gender"
t.date "DOB"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "races", force: true do |t|
t.string "name"
t.integer "race_number"
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "roles", force: true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", force: true do |t|
t.string "first_name"
t.string "last_name"
t.string "user_name"
t.string "address"
t.string "phone_number"
t.string "email", default: ""
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
t.string "last_sign_in_ip"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "role_id"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
end
I have been trying:
rake db:reset
and
rake db:drop
rake db:create
rake db:migrate
And I get met with the same errors each time.
Interesting that this was working, meaning I had run these commands and got it working. I simply tried to just start fresh and now it's throwing these errors.
Worth noting - I did change a model file from users.rb to user.rb & roles.rb to role.rb I don't know if this would effect anything.
Any help would be much appreciated.
You should load the schema first then migrate:
rake db:schema:load
rale db:migrate
The first command will run your schema.rb file and create the users table. The 2nd will then run your migration and it shouldn't fail because now the users table exists.
This sort of thing often happens when you go back and edit your migrations... might not be exactly what went wrong for you - but it's the first thing that I'd suspect. My strongest suspicion would be that you somehow deleted your "create_users" migration.

Resources