views:

223

answers:

1

I have a simple Customer model which has id, firstName, lastName, address_id columns.

In the method I have the following method to add data to the database:

  def self.add_customer(firstname, lastname)
    @cust = Customer.new(:firstName => firstname, :lastName => lastname, :address_id => self.id)
    @cust.save
  end

This is giving me error

undefined method `id'

I'm using rails 2.3.5 I've seen this code working in many books. My Customer table does have an ID column. I've verified in actual DB.

+4  A: 

self.add_customer is class method, not instance method, and you have id method only in instances.

Edit:
Let assume that you have:

class Customer < ActiveRecord::Base
  belongs_to :address
end

Class Address < ActiveRecord::Base
  has_many :customers
end

Then you can:

@address.customers.create(:first_name => first_name, :last_name => last_name)

and it will automatically associate new customer with @address.

Alternatively you can remove self from method definition and

def add_customer(firstname, lastname)
  @cust = Customer.new(:firstName => firstname, :lastName => lastname, :address_id => self.id)
  @cust.save
end

should just work. It works because if you declare add_customer as instance method (without self or class name like Address.add_customer) then it has access to self.id

MBO
so, is there a way to get access to the id? I was trying to mimick what I saw in another answer on SO: http://stackoverflow.com/questions/1673433/how-to-insert-into-multiple-tables-in-rails/1673442#1673442
Omnipresent
Thanks but I had tried that. If I remove self from add_customer then when I call this method from my controller by writing Customer.add_customer then it fails saying undefined method add_customer..
Omnipresent
@omnipresent Why do you call `Customer.add_customer` from controller? You can easily call `Customer.create(:first_name => first_name, :last_name => last_name, :address => @address)` and whole parameters list can be given from form, so: `Customer.create(params[:customer])` should work too
MBO
If this is a method from the Customer model, why are you trying to assign the id of the customer (which hasn't been created yet) to the address_id attribute?
Tomas Markauskas
ok i think a callback is what I need. so I've added after_save in my customer method. after saving to customer, I will always add record to Address with self.id. But still simple question: Are we not allowed to call methods of model from outside of the model if they are not prefixed with `self.`?
Omnipresent
@omnipresent Methods prefixed with `self` are class methods (like static methods in C++/C#/Java). You can call them with only Class name, so `Customer.add_customer` works with `def self.add_customer`. Methods without `self` are instance methods (non static methods from C++/C#/Java), so you need object of that type `@customer = Customer.new` (or `build`, or `create`), and then you can call `@customer.id`.
MBO
thanks. coming from java background ..that explained it much better.
Omnipresent