Ruby on Rails Thursday, January 31, 2013

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

On Jan 31, 2013, at 11:01 AM, Nishan T. wrote:

> 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

--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

No comments:

Post a Comment