Rails单个对象清除控制器

时间:2011-10-06 19:07:33

标签: ruby-on-rails singleton

我有一个Rails 3应用程序,并且正在实现配置文件完整性类功能。当用户登录时,应用程序应显示他/她在制作“完整”配置文件方面的进度。即使我在app初始化时使用填充了需求的单例类。单例有一个数组@requirements。使用我的初始化程序正确填充它。当我点击ProfileController要求显示时。但是,在第一个子项请求ProfileController#completeness之后,列出没有@requirements。单身人士的阵列是空的。我相信单例不会在控制器请求中返回相同的实例。我在哪里错了?

注意:这个类只是持有需求,而不是特定用户实现它们的进度。需求很少改变所以我想避免数据库查找。

# lib/profile_completeness.rb
require 'singleton'

class ProfileCompleteness

  include Singleton
  include Enumerable

  attr_reader :requirements

  def add_requirement(args)
    b = Requirement.new(args)
    @requirements << b
    b
  end


  def clear
    @requirements = []
  end


  def each(&block)
    @requirements.each { |r| block.call(r) }
  end


  class Requirement
    # stuff
  end

end

-

# config/initializers/profile_completeness.rb
collection = ProfileCompleteness.instance()
collection.clear

collection.add_requirement({ :attr_name => "facebook_profiles",
                             :count => 1,
                             :model_name => "User",
                             :instructions => "Add a Facebook profile" })

-

class ProfileController < ApplicationController
  def completeness
    @requirements = ProfileCompleteness.instance
  end

end

-

<!-- app/views/profile/completeness.html.erb -->
<h2>Your Profile Progress</h2>
<table>
  <%- @requirements.each do |requirement|
        complete_class = requirement.is_fulfilled_for?(current_user) ? "complete" : "incomplete" -%>

    <tr class="profile_requirement <%= complete_class -%>">

      <td>
        <%- if requirement.is_fulfilled_for?(current_user) -%>
          &#10003;
        <%- end -%>
      </td>

      <td><%= raw requirement.instructions %></td>

    </tr>
  <%- end -%>
</table>
<p><%= link_to "Profile", profile_path -%></p>

2 个答案:

答案 0 :(得分:2)

这不起作用(多线程,不同的rails worker等)你不能指望在每个请求都落在同一个rails app线程中。如果您的服务器崩溃,所有进度都会丢失!因此,跨请求/会话持久保存数据的方式是数据库。

将完整性跟踪器建模为模型并将其存储在数据库中。

另一种解决方案是使用Rails应用程序缓存。

设置键/值对:

Rails.cache.write('mykey', 'myvalue');

读:

cached_value = Rails.cache.read('mykey');

Read more about Rails Cache

如果您需要大数据集和快速访问的解决方案,我建议您使用redis:

Here is a good article特别是“使用Redis作为您的Rails缓存存储”部分,并查看“Redis相关宝石”部分。

重要的是键/值数据结构,我会选择像

这样的键
progress:user_id:requirements = [{ ...requirement 1 hash...}, {..requirement 2 hash.. }]

答案 1 :(得分:1)

你不能在Rails环境中使用单例,因为它们被隔离到单个进程,其中可能有很多,而且在开发模式中,这些类在每次请求时都被故意重新初始化。

这就是为什么你看到保存在它们中的任何东西都消失了。

如果您必须在请求之间保留这样的数据,请使用session工具。

一般的想法是创建一些你可以通过这里引用的持久性记录,例如创建一个表来存储ProfileCompleteness记录。然后,您将在每个请求上重新加载它,根据需要更新它,并保存更改。