2011-10-06 32 views
2

我有一个Rails 3应用程序,并正在执行配置文件完整性某种功能。当用户登录时,应用程序应该向他/她展示制作“完整”配置文件的进度。为了说明我正在使用在应用程序初始化时填充了需求的单例类。单例有一个数组@requirements。它使用我的初始化程序正确填充。当我点击ProfileController时,显示需求。但是,在第一个分支请求ProfileController#completeness列表否@requirements。单例中的数组是空的。我相信单身人士不会在控制器请求中返回相同的实例。我在哪里错了?跨控制器的Rails单身对象清除

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

# 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

这是不行的(多线程,不同的rails工作人员等),你不能指望在每个请求登陆相同的rails应用程序线程。如果您的服务器崩溃,所有进度都会丢失!因此,跨请求/会话永久保存数据的方式就是数据库。

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

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

设置一个键/值对:

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

阅读:

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

Read more about Rails Cache

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

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

重要的是键/值数据结构,我会去键,如

progress:user_id:requirements = [{ ...requirement 1 hash...}, {..requirement 2 hash.. }] 
+0

ProfileComplete类只保存需求,而不是特定用户的进度。向班级询问用户完成多少要求是很容易的。需求很少会改变,所以我想保存一个数据库查询。 –

+0

看到我的编辑;) – sled

+0

是的,这将做。 –

1

,因为这些被隔离到单个进程不能在Rails的环境中使用单身的其中可能会有很多,而且很糟糕她和开发模式一样,这些类在每次请求时都会故意重新初始化。

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

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

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

+0

我想避免访问数据库。将会有一些几乎不会改变的要求。我认为会议适合个人的要求。我想在整个应用程序的内存中收集一个集合。 –

+0

只要查询很快,我就不会害怕旅行到数据库。没人会注意到加载延迟1ms。 – tadman