Ruby,如何通过其内存地址或object_id获取原始对象?

时间:2018-06-27 10:00:06

标签: ruby-on-rails ruby object memory

例如,地址为“ 0x007f6f0954e820”字符串,如何获取实际对象?

我写这些: 在GymsController中

class GymsController < ApplicationController
  @@gyms = Array.new
  def private_page
    ...
    cookies.permanent[:gyms] = JSON.generate(@@gyms << @page)
  end
end

和history.html.slim

- content_for :title, "History"
- breadcrumb :history
= stylesheet_link_tag 'application'

.outer
  main.privacy-index
    .content-wrapper
      h1.headline2 History一覧
      - JSON.parse(cookies.permanent[:gyms]).reverse.each do |value|
        = (value.to_s.split(":").last)[0..-2].inspect
        br

(value.to_s.split(":").last)[0..-2].inspect是“ 0x007f6f2b587b30” 但是我想得到真实的物体,并且喜欢value.titlevalue.images

1 个答案:

答案 0 :(得分:0)

我不知道通过内存地址(即您的0x007f6f2b587b30)“获取”对象的方法,

但是您可以使用object_id通过 ObjectSpace._id2ref(OBJECT_ID) “获取”对象:

解决方案:

重要提示:这仍然存在继承问题:请参阅下面我的建议。

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

您的查看文件:

- 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

建议:

  • 使用“类实例变量” @gyms代替“类类变量” @@gyms。看看为什么要here

  • 如果您在控制器中的@page变量不是记录(因为它与您拥有的任何模型都不对应,因此未保存在数据库中),则创建一个模型,以便您可以将其保存到数据库中,并通过模型的记录id在上面的视图中检索这些数据,因此不再通过object_id

    这将使您解决我的解决方案的以下问题 以上:

    • 对象驻留在内存中,并且需要进行垃圾回收。因此,如果对象已经被垃圾回收,则使用ObjectSpace._id2ref(OBJECT_ID)可能有时会失败。 (see this SO),因为上面的ObjectSpace._id2ref在我的解决方案代码中运行的执行代码与对象最初定义的位置不同:

      • 一个在控制器中,其中定义了@page对象(某些request1 /例如thread1),
      • 另一个在视图文件中,ObjectSpace._id2ref()试图获取该对象(某些request2 /例如thread2),
    • 在您的代码中,您使用的是@@gyms = Array.new,这意味着@@gyms(存储在内存中)将无法被其他Rails进程访问,因为在这些之间没有共享内存流程,而简单地表示@@gyms对于以下每个流程将具有 DIFFERENT!值:

      • 跟踪服务器#1(例如... server1中的unicorn-1)
      • 跟踪服务器#2(例如... server1中的unicorn-2)
      • 跟踪服务器3(例如... server2中的unicorn-3)
      • 后台工作者进程1(例如... sidekiq-1)
      • 后台工作者进程2(例如... sidekiq-2)
      • 等...

      ...而如果您将gyms(如果可能且仅在必要时)保存到模型中,并且这些健身记录属于用户,那么我可以想像执行以下操作(解决上面的这些潜在的不同值,将不再需要您使用Cookie):

      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