Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how does activerecord know to perform an insert or update?

Maybe some Ruby experts out there can shed some light on how activerecord know to do an insert or update when calling save(). What is the logic behind it? Does it check to see if the primary key is blank or something and if so does an insert, if not an update?

like image 332
rip747 Avatar asked Nov 05 '09 21:11

rip747


People also ask

What is ActiveRecord implementation?

Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an implementation of the Active Record pattern which itself is a description of an Object Relational Mapping system.

What does ActiveRecord base do?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending. Edit: as Mike points out, in this case ActiveRecord is a module...

What does ActiveRecord where return?

Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments.

Is ActiveRecord an ORM?

ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code.


2 Answers

Whilst it's fine for some people to say "RTFM" I rather the more walk-through-but-still-entirely-useless-when-Rails-3-comes-out-and-changes-everything response:

How it works in Rails 2.3 (aka "today")

save calls create_or_update which looks like this:

def create_or_update
  raise ReadOnlyRecord if readonly?
  result = new_record? ? create : update
  result != false
end

You can ignore the first line of this method as it only raises an error if the record is readonly (it isn't usually, but in the case of joins it may be). What we are interested in here is the second and third lines inside the method.

The second line calls new_record? which is defined as this:

  # Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet; otherwise, returns false.
  def new_record?
    @new_record || false
  end

And the variable @new_record is set when the initialize (new calls initialize, and gives us a new object, some background Ruby-fu here) method is called.

So if this @new_record is true it'll call create and if it's false it'll call update which brings us to what you're after, I think.

Furthermore, when you find a record it does not call initialize and therefore does not set @new_record. If you noticed, the code behind new_record? was @new_record || false, meaning it will return false if @new_record was not set.

Let's say for example you want to find the last Forum record, so you would do Forum.last.

  1. This calls the last method on the Forum class, which inherits from ActiveRecord::Base
  2. last calls the find class method.
  3. find calls find_last
  4. find_last calls find_initial
  5. find_initial calls find_every
  6. find_every calls find_by_sql
  7. and find_by_sql calls instantiate

You'll see here that nowhere along this change is @new_record set and thus any record obtained by find will not be a new record.

Hope this helps you understand.

like image 175
Ryan Bigg Avatar answered Sep 17 '22 13:09

Ryan Bigg


It principaly relies on the new_record? method.
This method returns true if it's a new record and false if it's not.

In fact it's not really hard.

  • When you get an existing record, it's not new. So new_record? can direcly return false.
  • When you create a new record (Model.new), new_record? will return true. It's a new record.
  • When you save that new record, it's not new anymore. The internal variable @new_record gets updated. new_record? won't return true anymore.

To see when it happens, go to ActiveRecord::Base, line 2911

    self.id ||= new_id

    @new_record = false
    id
  end
like image 33
Damien MATHIEU Avatar answered Sep 21 '22 13:09

Damien MATHIEU