Ruby, how to fetch origin object by its memory address or by object_id?
I do not know a way to "get" the Object by memory address (i.e. your 0x007f6f2b587b30
),
but you can "get" the Object by object_id
using ObjectSpace._id2ref(OBJECT_ID)
:
Solution:
Important: this still has inherit issues: see my recommendations below why.
app/controllers/gyms_controller.rb:
class GymsController < ApplicationController
@@gyms = Array.new
def private_page
...
gym = @page
@@gyms << gym
cookies.permanent[:gyms_object_ids] = gym.object_id
end
end
your view file:
- content_for :title, "History"
- breadcrumb :history
= stylesheet_link_tag 'application'
.outer
main.privacy-index
.content-wrapper
h1.headline2 History一覧
- cookies.permanent[:gyms_object_ids]).reverse.each do |gym_object_id|
- gym = ObjectSpace._id2ref(gym_object_id.to_i)
= gym.title
= gym.images
br
Recommendations:
use "class instance-variable"
@gyms
instead of "class class-variable"@@gyms
. See why here.if your
@page
variable above in your controller, is not a record (being that it does not correspond to any of the models you have, and thus is not saved in the DB), then create a model for it, so that you can save it into the DB, and retrieve these data in your views above through the model's recordid
, and therefore no longer byobject_id
.This would allow you to solve the following issues of my Solution
above:Objects reside in memory, and are subject to garbage collection. Therefore using
ObjectSpace._id2ref(OBJECT_ID)
is probably gonna fail at times if the Object is already garbage-collected. (see this SO), becauseObjectSpace._id2ref
above in my solution code runs at different code of execution than where the object is originally defined:- one is in the controller where
@page
object is defined (some request1 / say thread1), - the other one is in the view file where
ObjectSpace._id2ref()
tries to get that object (some request2 / say thread2),
- one is in the controller where
in your code, you are using
@@gyms = Array.new
, which means that@@gyms
(being stored in-memory) is not gonna be accessible to other rails processes because memory is not shared between these processes, and to put simply means that@@gyms
would have DIFFERENT! values for each of the following processes:- rails server #1 (say... unicorn-1 in server1)
- rails server #2 (say... unicorn-2 in server1)
- rails server #3 (say... unicorn-3 in server2)
- background worker process #1 (say... sidekiq-1)
- background worker process #2 (say... sidekiq-2)
- etc...
...whereas if you instead save the
gyms
(if possible and if necessary only) into a model and that these gym records belong to a user, then I would imagine doing something like below instead (which will solve these potential differing values above, and will no longer require you to use cookies):class Gym < ApplicationRecord
has_many :gyms_users
has_many :users, through: :gyms_users
end
class GymsUser < ApplicationRecord
belongs_to :gym
belongs_to :user
validates :user, uniqueness: { scope: :gym }
end
class User < ApplicationRecord
has_many :gyms_users
has_many :gyms, through: :gyms_users
end
How to print the memory location of a Ruby object
I don't know why would you want such a feature, and this is very implementation-specific, but on MRI 1.9 you can (ab)use object_id
:
ruby-1.9.2-p180 :022 > class A; end
=> nil
ruby-1.9.2-p180 :023 > a = A.new
=> #<A:0xa2b72e4>
ruby-1.9.2-p180 :024 > a.object_id.to_s(16)
=> "515b972"
ruby-1.9.2-p180 :025 > (a.object_id << 1).to_s(16)
=> "a2b72e4"
For an explanation of why does it work, check out the relevant lines in MRI gc.c
.
Note that this will not work on other implementations (JRuby, Rubinius), and may very well break in future versions of Ruby. Also, there may be no way at all to get the address in some implementations (I suspect that you cannot in JRuby; I'm not sure, through).
Object address in Ruby
You can get the address using object_id and multiplying it by 2* and display it in hex using sprintf
(aka %
):
"#<Thing:0x%08x>" % (object_id * 2)
Of course, as long as you only need the number to be unique and don't care that it's the actual address, you can just leave out the * 2
.
* For reasons that you don't need to understand (meaning: I don't understand them), object_id
returns half the object's memory address, so you need to multiply by 2 to get the actual address.
ruby : can't understand memory address
You might be confused specifically because you're using integers. Integers in Ruby are singletons: their integer value determines their object id.
x = 3
y = 3
x.object_id == y.object_id # true
x = "a"
y = "a"
x.object_id == y.object_id # false
However this is only true for integers up to a certain size.
x = 11111111111111111111111111111111
y = 11111111111111111111111111111111
x.object_id == y.object_id # false
This is because Ruby actually stores the integer value in the object id if it is small enough. If the number is too big it has to allocate a new object.
Print memory address for Ruby array
Use the method Object#object_id
.
Returns an integer identifier for obj. The same number will be returned on all calls to id for a given object, and no two active objects will share an id.
#object_id
is a different concept from the:name
notation, which returns the symbol id of name.
Example :-
Arup-iMac:arup_ruby $ irb
2.1.2 :001 > s = "I am a string"
=> "I am a string"
2.1.2 :002 > obj_id = s.object_id
=> 2156122060
2.1.2 :003 > ObjectSpace._id2ref obj_id
=> "I am a string"
2.1.2 :004 >
Rails convert memory address to object
I think you should pass an object_id instead of whole object to your worker.
Call worker:
NotifySubscriberWorker.perform_async(@incident.id)
Then change in your worker:
SubscriberMailer.notify_subscriber(subscriber, incident_id)
and then in mailer:
def notify_subscriber(subscriber, incident_id)
@incident = Incident.find(incident_id)
mail to: subscriber.email, subject: "There is an update to #{@@app_name}'s status.'"
end
Related Topics
I Have a Gem Installed But Require 'Gemname' Does Not Work. Why
Put Haml Tags Inside Link_To Helper
How to Check Whether a Value in a String Is an Ip Address
Why Does Accessing a Ssl Site with Mechanize on Windows Fail, But on MAC Work
Fast Way to Get Remote Image Dimensions
Install Any Version of Ruby with Rvm on Mavericks
How to Remove Ruby from Ubuntu
Making Multiple Http Requests Asynchronously
Empty Attribute with Ruby Haml
Can Bundler Show Me Which Gems in Gemfile Have Newer Versions (Eg. Dry-Run of Bundle Update)
Hot Deploy on Heroku with No Downtime
Is Inject the Same Thing as Reduce in Ruby
How to Check If a Class Is Defined