Q: object.id is deprecated. How to mock?

In Rails, the primary key, by default ‘id’, is used all over the
place. However, Ruby now deprecates the use of constructs like:

@post = Post.find(:first)
@post_id = @post.id

I buy the rationale, as the Object#id is something of a reserved
method. However, changing all references to use [:id], while seemingly
the correct approach, also has the unwanted side-effect of breaking
every mock created using mock_model that references the id that way.

Sure, I can go in and stub [] to return self[:id] for each mock
object, but that ActiveRecord objects behave more as a hash than as an
object (IMO), so there are things like:

@post[:body_text]

peppered throughout the codebase, and a big hammer like a stub of the
method would also break specs. So the conundrum is how to make
mock_model respond only to the method with an argument of :id to
return self[:id].

Questions:

  1. Is there something bogus in my assumption that using @post[:id] is
    preferred to @post.id?
  2. Has anyone solved this problem and if so what worked?

BTW: I am aware that :to_param returns the id, but it seems counter-
intuitive to read code that takes advantage of this quirk.

Thanks,

Steve

On Tue, Nov 25, 2008 at 2:04 PM, s.ross [email protected] wrote:

In Rails, the primary key, by default ‘id’, is used all over the
place. However, Ruby now deprecates the use of constructs like:

@post = Post.find(:first)
@post_id = @post.id

I think you’ve got the wrong end of the stick there. Object#id (which
returns a unique id for the Ruby object) was deprecated in favor of
Object#object_id, mostly because ActiveRecord overrides it to return
the primary key. #id seemed in retrospect too common to be reserved
for an implementation detail. You should use model.id to get the
primary key.

If you’re getting that warning, you’re calling #id on something that
doesn’t decend from ActiveRecord::Base. #id is one of the few things
that nil responds to (and issues the deprecation warning); maybe there
are no Posts in your DB? Try checking the value of @post.

Peter

On Tue, Nov 25, 2008 at 11:04 AM, s.ross [email protected] wrote:

In Rails, the primary key, by default ‘id’, is used all over the
place. However, Ruby now deprecates the use of constructs like:

@post = Post.find(:first)
@post_id = @post.id

These are different methods. Object#id is indeed deprecated, but
ActiveRecord::Base#id is perfectly fine.

///ark

“s.ross” [email protected] writes:

Steve


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

I came across this today when I used stub_model. I hadn’t given it an
explicit ID so I got that warning. So if that’s why you’re
encountering, just do something like
@post = stub_model(:id => 123)

As others have said though, only Object#id is deprecated. AR::Base#id
is still valid.

Pat

On 2008-11-25, at 14:04, s.ross wrote:

Steve
Hi Steve. Ruby deprecated Object#id in favour of Object#object_id .
Now it’s possible to obtain the ActiveRecord “id” and Object “id” for
an ActiveRecord object:
@foo = Foo.find :first
@foo.id # => 3
@foo.object_id # => 20613620

I hope that clears up your question. Cheers,
Nick

On Nov 25, 2008, at 12:34 PM, Peter J. wrote:

the primary key. #id seemed in retrospect too common to be reserved
for an implementation detail. You should use model.id to get the
primary key.

If you’re getting that warning, you’re calling #id on something that
doesn’t decend from ActiveRecord::Base. #id is one of the few things
that nil responds to (and issues the deprecation warning); maybe there
are no Posts in your DB? Try checking the value of @post.

Peter

Thanks Peter, Nick, Pat and Mark. I think I have a better handle on
this now. I’m up-migrating what is appearing to me to be an
inconsistent codebase to Rails 2.2 and the issue of indexing versus
member access came up. It appears I was incorrect in my assessment
that using a hash index would be the safer way to go. Thankfully we
have a reasonable number of specs and they will help us find and fix a
many of these issues.

Steve