Rails migrations: Drop table and change references - ruby

Help me please create a correct migration for next needs
Drop table "hiring_question_groups"
Change references (:group) in "hiring_questions" to references(:company)
I have this migration before:
class CreateHiringQuestionsAndGroups < ActiveRecord::Migration
def change
create_table :hiring_questions do |t|
t.references :group
t.string :title
t.text :description
t.boolean :is_active, default: true
t.timestamps
end
create_table :hiring_question_groups do |t|
t.references :company
t.string :title
t.boolean :is_active, default: true
t.timestamps
end
end
end
Table which should be dropped:
class Hiring::QuestionGroup < ActiveRecord::Base
belongs_to :company
has_many :questions, class_name: 'Hiring::Question', dependent: :destroy, foreign_key: 'group_id'
This table should be changed:
class Hiring::Question < ActiveRecord::Base
belongs_to :group, class_name: 'Hiring::QuestionGroup'
to:
class Hiring::Question < ActiveRecord::Base
belongs_to :company, class_name: ???
How I can do this with One migration?

That's very simple!
def change
remove_reference :hiring_questions, :group
drop_table :hiring_question_groups
add_reference :hiring_questions, :company
end
Sorry!)

Related

Active Admin Tag Collection with joined table

I have a problem to display the correct values in the Active Admin Tag collection.
enter image description here
To build many to many relationships I created a joined table:
create_table "profession_allocations", force: :cascade do |t|
t.integer "master_id"
t.integer "slave_id"
t.index ["master_id"], name: "index_profession_allocations_on_master_id", using: :btree
t.index ["slave_id"], name: "index_profession_allocations_on_slave_id", using: :btree
end
and a model:
class ProfessionAllocation < ApplicationRecord
has_and_belongs_to_many :master, :class_name => 'Profession'
has_and_belongs_to_many :slave, :class_name => 'Profession'
end
to build relationships with my profession table:
create_table "professions", force: :cascade do |t|
t.string "kind", null: false
t.string "list", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "summary_de", default: "summary german", null: false
t.string "summary_en", default: "summary english", null: false
end
and the model:
class Profession < ApplicationRecord
validates_presence_of :kind, :list
validates :kind, presence: true, uniqueness: true
validates :list, presence: true
validates :summary_de, presence: true
validates :summary_en, presence: true
has_many :master_profession_allocations, :class_name => 'ProfessionAllocation', :foreign_key => 'master_id'
has_many :slave_profession_allocations, :class_name => 'ProfessionAllocation', :foreign_key => 'slave_id'
end
Inside Active Admin I use the gem activeadmin_addons to use tags, but I guess this does not madder for this issue.
if f.object&.persisted?
f.input :master_profession_allocations, as: :tags, collection: Profession.where.not(id: f.object.id).order('summary_en ASC'), display_name: :summary_en
else
f.input :master_profession_allocations, as: :tags, collection: Profession.all.order('summary_en ASC'), display_name: :summary_en
end
end
While creating the ProfessionAllocation works fine with the Tag collection, the edit view makes problems, because it displays the ProfessionAllocations and not the related Professions.
My question is, how can I display the related Profession in the Tag Collection?
Best
Alex
I solved it by create a subsection. This allows me also to store addtional data in the allocation:
f.inputs do
f.has_many :master_profession_allocations, heading: 'Slaves', allow_destroy: true, new_record: true do |pa|
if f.object&.persisted?
pa.input :level, as: :select, collection: ProfessionAllocation::LEVELS
pa.input :slave_id, as: :select, collection: Profession.joins('LEFT JOIN profession_allocations pa on professions.id = pa.master_id WHERE professions.id !=' + f.object.id.to_s).map { |pa| [pa.summary_en, pa.id] }
else
pa.input :level, as: :select, collection: ProfessionAllocation::LEVELS
pa.input :slave_id, as: :select, collection: Profession.joins('LEFT JOIN profession_allocations pa on professions.id = pa.master_id').map { |pa| [pa.summary_en, pa.id] }
end
end
end

Ruby ActiveModel::MissingAttributeError

I'm trying to learn on my own ruby database relations.
I have a relation of 1 "Category" to many "Products" and I'm trying to add a product to the remote database (heroku server).
TIMESTAMP_create_products.rb
class CreateProducts < ActiveRecord::Migration
def up
create_table :products, primary_key: 'product_id' do |p|
p.index :product_id
p.string :name
p.decimal :price
p.references :categories, index: true
end
end
def down
drop_table :products
end
end
TIMETSTAMP_create_categories.rb
class CreateCategories < ActiveRecord::Migration
def up
create_table :categories, primary_key: 'category_id' do |c|
c.index :category_id
c.string :name
c.integer :parentId
end
end
def down
drop_table :categories
end
end
model.rb
class Products < ActiveRecord::Base
self.primary_key = "product_id"
validates :name, presence: true, uniqueness: true
belongs_to :categories, class_name: "Categories", foreign_key: 'category_id'
end
class Categories < ActiveRecord::Base
self.primary_key = "category_id"
validates :name, presence: true, uniqueness: true
has_many :products, class_name: "Products"
end
I add manually a category to the database and every time I try to execute the code:
Products.create(name: "name1", price: "1.1", categories: Categories.find(1))
It gives me the output:
ActiveModel::MissingAttributeError can't write unknown attribute category_id
Is there anything missing here? I don't understand why this is not working.
You may have a problem with singular / plural.
In your migration, to create the table products, you have the line:
p.references :categories, index: true
This should add to your table the column categories_id.
However, in the Products model, the foreign key is set to category_id. So when you try to attach a category to a production, it's trying to write the ID of the category to the column category_id of the table categories, which doesn't exists.
By changing the reference name in the products migration, everything should work fine:
create_table :products, primary_key: 'product_id' do |p|
p.index :product_id
p.string :name
p.decimal :price
p.references :category, index: true
end

Create table if not present in existing database using Rails 3

I have a doubt.Suppose i have already created model(i.e-User) in Rails 3 application.Now i will connect my app to other database(lets say SQL Server) instead of my DB(where i have created this model before).That Database where i am going to connect has no "User" table and my app has already User.rb file.Here i need when i will connect to my app to that DB,it will automatically execute the query and create table in that DB.Please check my User migration file given below.
20150419131135_create_users.rb:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :contact_name
t.string :login_id
t.string :password_hash
t.string :password_salt
t.string :phone
t.string :address
t.timestamps
end
end
end
User.rb:
class User < ActiveRecord::Base
attr_accessible :address, :contact_name, :login_id, :password_hash, :password_salt, :phone,:password, :password_confirmation
attr_accessor :password
before_save :encrypt_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates :contact_name, :presence => true, :length => { :minimum => 5 }
validates :login_id, :presence => true
validates_uniqueness_of :login_id
def encrypt_password
if password.present?
self.password_salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
end
end
def self.authenticate(username, password)
user = find_by_login_id(username)
if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
end
When user will connect to any other DB,The table should auto created.Please help me.
Change your migration file to check before creating/destroying users
class CreateUsers < ActiveRecord::Migration
def self.up
if !table_exists? :users
create_table :users do |t|
t.string :contact_name
t.string :login_id
t.string :password_hash
t.string :password_salt
t.string :phone
t.string :address
t.timestamps
end
end
end
def self.down
drop_table :users if !table_exists?(:users)
end
end

How to use unique key as foreign key

I have an N:N relationship between 2 tables, users and titles. These tables link using a third table purchases which should have the id of each of the others table. The problem is that for the titles I do not require the title_id on the purchases table, but a different column named item_id which is UNIQUE and NOT NULL on the titles table.
Currently I have the following migration, but it is not working. I might be missing something:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases, :id => false do |t|
t.belongs_to :title, foreign_key: 'item_id'
t.belongs_to :user, :null => false
end
end
end
How can I get my purchases table to reference the titles table using that item_id key on the titles table rather than title_id ?
Migration:
class CreatePurchases < ActiveRecord::Migration
def change
create_table :purchases, :id => false do |t|
t.integer :item_id
t.integer :user_id, :null => false
end
end
end
In your models:
# app/models/title.rb
class Title < ActiveRecord::Base
# ...
has_and_belongs_to_many :users,
class_name: "User",
foreign_key: "item_id",
association_foreign_key: "user_id",
join_table: "purchases"
# ...
end
# app/models/user.rb
class User < ActiveRecord::Base
# ...
has_and_belongs_to_many :titles,
class_name: "Title",
foreign_key: "user_id",
association_foreign_key: "item_id",
join_table: "purchases"
# ...
end
Don't forger add indexes to migration if its need.

How can two user instances have the same account

In my rails app I want to create a shared account (later with different access levels). I want two instances of the User to have the same account.
My User Model has_many :accounts and my Account belongs_to :user
In the rails console when I do, e.g:
account = Account.first
account.user_id = [1, 2]
account.save
it returns true but when I check it again account.user_id = nil
How should I go on about it, then?
EDIT:
The Account Model:
class Account < ActiveRecord::Base
belongs_to :user
has_many :products
validates_presence_of :title
end
and the User model:
class User < ActiveRecord::Base
has_many :accounts
has_many :products, through: :accounts
accepts_nested_attributes_for :accounts
validates_presence_of :name
before_save do
self.email = email.downcase unless :guest?
end
validates :name, presence: true, length: { maximum: 50 }, unless: :guest?
end
EDIT 2:
I've updated the models relationship so the new Account model is:
class Account < ActiveRecord::Base
has_and_belongs_to_many :users
validates_presence_of :title
end
and the new User model is:
class User < ActiveRecord::Base
has_and_belongs_to_many :accounts
belongs_to :account
has_many :products, through: :accounts
accepts_nested_attributes_for :accounts
validates_presence_of :name
before_save do
self.email = email.downcase unless :guest?
end
validates :name, presence: true, length: { maximum: 50 }, unless: :guest?
end
I also created a new migration, a accounts_users table
class CreateAccountsUsersJoinTable < ActiveRecord::Migration
def change
create_join_table :users, :accounts do |t|
## Not sure if this is necessary
##t.index [:user_id, :account_id]
##t.index [:account_id, :user_id]
t.belongs_to :user
t.belongs_to :account
end
end
end
Still I can't have a account with multiple users

Resources