Can I or SHOULD I find an object by the object_id attribute in ruby?
Yes, you can:
irb(main):002:0> s1 = "foo"
#=> "foo"
irb(main):003:0> s2 = ObjectSpace._id2ref(s1.object_id)
#=> "foo"
irb(main):004:0> s2.object_id == s1.object_id
#=> true
irb(main):005:0> s2[0] = "z"
#=> "z"
irb(main):006:0> s1
#=> "zoo"
Should you do this? I'll leave that up to you. There are less geeky ways to store an object with a serializable id
(e.g. in an Array and returning the index). One problem you may run into is that if the only 'reference' you keep to an object is the object_id
, the object can be collected by GC when you're not looking.
Can we access the objects we created in ruby using their object _ids in ruby?
How an object ID is “assigned” depends on the Ruby implementation and other factors like the OS bitness. For example, in CRuby nil.object_id
returns 4
on 32-bit and 8
on 64-bit.
Additionally nil
is a so called immediate value. true
, false
, fixnums (small integers) and sometimes even floats are other immediate values. They have fixed IDs for the following reasons:
- they're passed by value and not by reference like the other (dynamically allocated) objects
- there's only one
nil
, onetrue
, one19
, etc. however there can be two different arrays
See the documentation of BasicObject#object_id
. You can also click to toggle the source to get a look at the CRuby implementation.
Call ObjectSpace._id2ref
to retrieve an object by ID:
id = nil.object_id
ObjectSpace._id2ref(id) # => nil
In some implementations that method may not be implemented or really slow. According to matz it was originally a hack needed to implement weakref
but current versions don't call it anymore.
Ruby Object#id warnings and Active Record
I'm assuming you're doing mocking / stubbing (because you mentioned specs).
In my case, I run into these warnings when I stub an ActiveRecord object and access its ID attribute.
In cases where you expect to access the ID of your ActiveRecord object, I'd recommend you do the following:
mock("MyActiveRecordObject", :id => 1001)
Ruby object to_s what is the encoding of the object id?
Think of the object_id
, or __id__
as the "pointer" for the object. It is not technically a pointer, but does contain a unique value that can be used to retrieve the internal C VALUE
.
There are patterns to the value it has for some data types, as you can see with its hexadecimal representation with to_s
. I am will not go into all the details, as there are already numerous answers on SO explaining, and already linked from comments, but integers (up to a FIXNUM_MAX
, have predictable values, and special constants like true
, false
, and nil
will always have the same object_id
in every run.
To put simply, it is nothing more than a number, and shown as a hexadecimal (base 16) value, not any actual "encoding" or cypher.
Going to expand upon this a bit more in light of your latest edits to the question. As you posted, the hexadecimal number you see in to_s
is the value of the internal C VALUE
of the object. VALUE
is a C data type (unsigned, pointer size number) that every Ruby object is represented as in C code. As @Stefan pointed out in a comment, for non-integer types (I speak only for MRI version), it is twice the value of the object_id
. Not that you probably care, but you can shift the bits of an integer to predict the value for those.
Therefore, using you example.
A value of 0x00007fac5eb6afc8
is simple hexadecimal notation for a number. It uses a base 16 counting system as opposed to the base 10 decimal system we are more used to in everyday life. It is simply a different way of looking at the same number.
So, using that logic.
a = 0x00007fac5eb6afc8
#=> 140378300133320 # Decimal representation
a /= 2 # Remember, non-integers are half of this value
#=> 70189150066660 # Your object_id
Rails - include? with object or object id
There's really no difference between the two. Both are very inefficient and won't work if your Company table is large. They load all the Company records into memory, and furthermore call c.owners
which fires an additional query on each of the records. This is called an N+1 query. You can address the N+1 part by using Company.all.includes(:owners)
, but you'd still have the issue of loading everything into memory.
It's hard to give you exact code since you haven't shared your model definition (specifically, how the Company#owners
association is defined). But I'll assume you have a CompanysOwners join table. In which case I would recommend the following code:
companies = CompanysOwners.where(owner: current_user).includes(:company).map(&:company)
This only fires off a single query, and doesn't load more records into memory than are needed. You could get rid of the includes(:company)
part and it would still work, but be slower.
If your Company#owners
association is defined differently than this, feel free to leave a comment and I can show you how to modify this for your needs.
By the way, to address your original question more directly ... under the hood, c.owners.include?(current_user)
uses ==
to compare the records. And ActiveRecord::Core#==
is comparing the IDs under the hood. You can see the source code here for proof of that: https://api.rubyonrails.org/v6.1.3.1/classes/ActiveRecord/Core.html#method-i-3D-3D. So they really are doing the same thing.
Rails primary key and object id
It sounds like the object you've called .id
on is not actually an ActiveRecord model. You should only see that warning for Ruby objects where .id
is the soon-to-be deprecated version of Object#object_id
.
However, another way to access the primary key for the field with an ActiveRecord model is model.attributes['id']
so you could try that.
Mongodb change ObjectID or _id attribute for a document?
MongoDB won't let you update the _id
field of a document, but you can delete the document and reinsert it with a new _id
value.
How can I get the parent object id inside the child model? Nested form
Solved it using a before_save
callback and self.campaign.id
to get the parent id inside a method to manipulate the info my user typed.
Related Topics
Differences Between Proc and Lambda
Failed to Build Gem Native Extension
Rvm Ruby Installation Errors - MAC
Ruby Dsl (Domain Specific Language) Repositories, Examples
How to Wrap the Invocation of a Ruby Method by Including a Module
Rails 3. How to Add a Helper That Activeadmin Will Use
How to Replace the Unicode Gem on Ruby 1.9
Subtract N Hours from a Datetime in Ruby
Rake Assets:Precompile Attempting to Connect to Database
Error Installing Debugger: Failed to Build Gem Native Extension with Ruby-1.9.3-P362
Param Is Missing or the Value Is Empty: User Rails 4