Wednesday, February 01, 2006

find, find_by_name and ActiveRecord::RecordNotFound

Given a User with 'has_many' messages:

message = user.messages.find do {|m| m.subject == messageSubject}

errors out with RecordNotFound exception if no such record exists; while

message = user.messages.find_by_subject(messageSubject)

doesn't error out with an exception, but it returns a nil object, which can then be tested for nil.

Passing an object to the block intialization autoamtically sets up association

If Obj A belongs_to Object B, then passing an object B in the block intialization of object B will automatically set up the database connections, i.e. user.note_id = note.id.

Consider a user.
class User < ActiveRecord::Base
....
belongs_to :note
end

A Note model
class Note < ActiveRecord::Base
end

The ddl is:
create_table users (
`id` int not null,
`note_id` int default NULL
)

create_table notes (
`id` int not null,
`note` text
)


Now consider the following code:

params[:user] contains intialization for the attributes of the user class.

params[:user][:note] = Note.new(:note => "ffo bar")
user = User.new(params[:user])

This will automatically insert the note into the database and then create the user record with note_id set to the id of this new note record.

Assigning to has_one or has_many association automatically saves object

Assigning to has_one or has_many association automatically saves object however assigning to a belongs_to association doesnt save the object.

A User has_many messages

controller:
u = User.find(session[:user_id])

messageSubject = params[:msgSub] || "No Subject"
message = u.messages.find_by_subject(messageSubject)
if message.nil?
u.messages << subject =""> messageSubject)
message = u.messages.last
end

development.log:
User Columns (0.000000) SHOW FIELDS FROM users
Message Columns (0.016000) SHOW FIELDS FROM messages
Message Load (0.000000) SELECT * FROM messages WHERE (messages.user_id = 1) AND (messages.`subject1 = 'No Subject' ) LIMIT 1
Couldn't find a message with name No Subject. Creating a new message.
Message Load (0.000000) SELECT * FROM messages WHERE (messages.user_id = 1) ORDER BY position
SQL (0.000000) BEGIN
Message Load (0.000000) SELECT * FROM messages WHERE (subject = 'No Subject') LIMIT 1
Message Load (0.000000) SELECT * FROM messages WHERE (user_id = 1) ORDER BY position DESC LIMIT 1
SQL (0.000000) INSERT INTO messages (`subject`, `updated_at`, `user_id`, `position`, `created_at`) VALUES('No Subject', '2006-02-01 12:41:48', 1, 1, '2006-02-01 12:41:48')
SQL (0.000000) COMMIT

Note that the reverse is not true...
If I do
pod = Pod.new(:name => podname)
pod.user = u

this will not save the pod until explictly saved!! Since Pod "belongs_to" a user, assigning to a "belongs_to" association doesn't automatically save either of the objects to the db.

Unncessary SQL generated by ActiveRecord

I have a user model which has_many messages.

So in my controller I did

u = User.find(session[:user_id])

messageSubject = params[:msgSub] || "No Subject"
message = u.messages.find_by_subject(messageSubject)
if message.nil?
u.messages << subject =""> messageSubject)
message = u.messages.last
end

Here is the output in development.log
User Columns (0.000000) SHOW FIELDS FROM users
Message Columns (0.016000) SHOW FIELDS FROM messages
Message Load (0.000000) SELECT * FROM messages WHERE (messages.user_id = 1) AND (messages.`subject1 = 'No Subject' ) LIMIT 1
Couldn't find a message with name No Subject. Creating a new message.
Message Load (0.000000) SELECT * FROM messages WHERE (messages.user_id = 1) ORDER BY position
SQL (0.000000) BEGIN
Message Load (0.000000) SELECT * FROM messages WHERE (subject = 'No Subject') LIMIT 1
Message Load (0.000000) SELECT * FROM messages WHERE (user_id = 1) ORDER BY position DESC LIMIT 1
SQL (0.000000) INSERT INTO messages (`subject`, `updated_at`, `user_id`, `position`, `created_at`) VALUES('No Subject', '2006-02-01 12:41:48', 1, 1, '2006-02-01 12:41:48')
SQL (0.000000) COMMIT


Why is ActiveRecord issuing a SELECT * FROM messages WHERE (subject = 'No Subject') LIMIT 1 command?

Control characters in development.log

The control characters in the development.log were driving me crazy. After tracking down the source in the code, I found an attribute called colorize_logging which can be set to false to disable these control characters

For more detail see:
http://wiki.rubyonrails.com/rails/pages/HowtoConfigureLogging/versions/30