tl;dr Yes, you /can/ even if Colin's advice is good (AND I agree with him!)
customer = Customer.new(other_attributes_here) {|c| c.id = user.id }
customer.save
I'm migrating the tables with existing data
I've users table and all other tables contains the user_id column and
now i need seperate the users into two (users & customers) tables
So i need to migrate the new customers table with existing users records
where the user type with customer
I need to create a customers table and set the id of users records with
user type as customer,
which will be easy instead of migrating many of other tables(which is
used only by customers) by checking every record with user's user type
and assign the new id of customers table.
My tables should looks like
users table:
id | name | ...
------------------------------
1 | aaa | ...
2 | bbb | ...
4 | ddd | ...
6 | fff | ...
customers table
id | name | ...
-------------------------------
3 | ccc | ...
5 | eee | ...
7 | ggg | ...
When i'm migrating users existing data, I can't assign the id of user as
customer's primary id
Well, what you can't do is use "mass assigment" to set the id of an ActiveRecord model.
You can, however, set the id on a new record and it will be honored if the database doesn't forbid it. (For example, if that primary key value already existed.)
In my migration file
def up
create_table(:customers) do |t|
t.string :name
end
User.joins(:user_type).where(:user_type => {:type_name =>
'customer'}).find_in_batches(:batch_size => 100){ |users|
users.each {|user|
customer = Customer.new
customer.id = user.id
customer.name = user.name
customer.save(:validate => false)
}
}
end
Also tried
Customer.create!(:id => user.id) instead of save method
And
INSERT INTO customers(id, name) VALUES("#{user.id}", "#{user.name}")
Finally all ended with same error
Error: Called id for nil, which would mistakenly be 4 -- if you really
wanted
the id of nil, use object_id
Is this correct?
Is there any way to assign the primary id ?
Please anyone explain how to do this?
There's even a block form of ActiveRecord.new that passes in the newly initialized object.
customer = Customer.new(:name => user.name) {|c| c.id = user.id }
customer.save(:validate => false)
Since you already have a "user_type", it seems like you're at least halfway to being STI (Single-Table Inheritance) anyway.
Couldn't you have:
class Customer < User
end
Then you'd have a `type` attribute (column) in the users table which would hold the class name represented by that row of data. (which could be "User" or could be "Customer")
Then you can say:
r = User.find_by_name('ccc')
and r will hold an instance of the Customer class.
-Rob