Очистка одиночного объекта Rails через контроллеры - PullRequest
2 голосов
/ 06 октября 2011

У меня есть приложение Rails 3, и я реализую полноту профиля .Когда пользователь вошел в систему, приложение должно показать ему / ей прогресс в создании «полного» профиля.Я использую одноэлементный класс, заполненный требованиями при инициализации приложения.Синглтон имеет массив @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 ]

2 голосов
/ 06 октября 2011

это не сработает (многопоточность, работа с разными рельсами и т. Д.), Вы не можете ожидать, что при каждом запросе вы попадете в одну и ту же ветку приложения rails. Если ваш сервер выходит из строя, весь прогресс теряется! Таким образом, для сохранения (постоянно) данных в запросах / сессиях используется база данных.

Смоделируйте ваш трекер полноты как модель и сохраните его в своей базе данных.

Другое решение - использовать кэш приложений Rails.

Установка пары ключ / значение:

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

Чтение:

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

Подробнее о Rails Cache

Если вам нужно решение для больших наборов данных и быстрого доступа, я рекомендую вам использовать redis:

Вот хорошая статья , в частности, раздел «Использование Redis в качестве хранилища кеша Rails» и обзор раздела «Gems, связанные с Redis».

Важная вещь - это структура данных ключ / значение, я бы выбрал такие ключи, как

progress:user_id:requirements = [{ ...requirement 1 hash...}, {..requirement 2 hash.. }]
1 голос
/ 06 октября 2011

Нельзя использовать синглтоны в среде Rails, потому что они изолированы от отдельных процессов, которых может быть много, и, кроме того, как и в режиме разработки, эти классы намеренно повторно инициализируются при каждом запросе.

Вот почему вы видите, что что-то сохраненное в них исчезает.

Если вам необходимо сохранять данные, подобные этим, между запросами, используйте средство session.

Общая идея состоит в том, чтобы создать какую-то постоянную запись, на которую вы можете ссылаться, например, создать таблицу для хранения записей ProfileCompleteness. Затем вы будете перезагружать его при каждом запросе, обновлять его по мере необходимости и сохранять изменения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...