Подтвердить что ты не робот

Ruby on Rails - сохранение конфигурации приложения

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

Я знаю, что могу хранить константы и т.д. в файле environment.rb, однако они выглядят загруженными только при перезапуске сервера.

Есть ли альтернативное место, где я могу определить эту информацию, или было бы лучше сохранить ее в базе данных?

Любые советы приветствуются.

Спасибо.

4b9b3361

Ответ 1

Вы можете использовать базу данных. Создайте отдельную таблицу "Настройки", в которой хранятся параметры ключа/значения, которые вам нужны. Недостатком этого решения является производительность (запрос DB каждый раз, когда вам нужна настройка). Чтобы исправить эту проблему, вы могли бы читать/писать через кеш, например "cache_money", или создавать свои собственные, используя "Rails.cache"

Ответ 2

Вы можете использовать драгоценный камень rails-settings-cached, который является вилкой драгоценного камня с рельсами (связанный Yi-Ru Lin в другом ответе).

После настройки вы сможете делать такие вещи, как:

Setting.foo = 123
Setting.foo # returns 123

Вы также можете управлять настройками на моделях, например:

user.settings.color = :red
user.settings.color # returns :red

Ответ 4

Лучший способ - использовать таблицу базы данных. Каждая строка должна содержать ключевое слово и значение. Simples.

Ответ 5

Я использовал app_config сам камень, но он не работает с рельсами 2.3.9 (и, вероятно, также с рельсами 3.x), поэтому я нашел этот блог, в котором упоминается rails-settings и конфигурация, настройки rails сохраняют значения в БД, но конфигурация имеет пространство имён. Я не пробовал их, но я думаю, что переключусь на настройки рельсов.

Теперь я замечаю, что ветвь настроек рельсов, о которых упоминает Yi-Ru Lin, кажется более функциональной, чем другая rails-settings

Ярл

Ответ 6

Для рельсов 4, если вы используете postgresql, вы можете использовать HStore, что похоже на сериализуемый атрибут, но вы делаете SQL-запросы с ним.

Для рельсов 3 вы можете использовать activerecord-postgres-hstore gem.

Ответ 7

Я попробовал https://github.com/huacnlee/rails-settings-cached, но он не работает, как описано. Очевидно, автор забыл упомянуть некоторые дополнительные настройки в описании использования драгоценных камней. Я не смог написать контроллер для настройки параметров.

Вместо этого мне удалось использовать https://github.com/paulca/configurable_engine - несмотря на некоторые незначительные проблемы, этот драгоценный камень гораздо разумнее, чем rails-settings-cached.

У драгоценного камня configurable_engine есть недостаток: он имеет жестко закодированные маршруты, которые являются неясными и неудобными. Автор gem обещал исправить его, но сказал, что у него в настоящее время нет времени на это.

Итак, эта проблема была легко организована путем простого создания моих собственных маршрутов. Вот мой код (добавленный, чтобы этот жемчуг действительно работал):

routes.rb

 namespace :admin do
   resources :configurables, only: [:index, :show, :edit, :update, :destroy]
 end

админ /configurables _controller.rb

class Admin::ConfigurablesController < Admin::ApplicationController
      # include the engine controller actions
  include ConfigurableEngine::ConfigurablesController

  before_action :set_configurable, only: [:show, :edit, :update, :destroy]

  def index

    @configurables = (Configurable.all.size > 0 ? Configurable.all : []) + 
    (Configurable.defaults.keys - Configurable.all.collect { |c| c.name })

  end

  def show
  end

  def edit
    new = params[:new]
  end

  def new

    respond_to do |format|

      name = params[:name]

        if name

            @configurable = Configurable.create!(name: name, value: nil)

            if @configurable
            format.html { redirect_to edit_admin_configurable_path(@configurable, new: true), notice: 'The setting was successfully created.' }
        else
            format.html { redirect_to admin_configurables_url, notice: 'Failed to create the setting.' }
        end
        else
            format.html { redirect_to admin_configurables_url, notice: 'The name of the new setting was not specified.' }
        end

    end

  end

  def update
    respond_to do |format|
      if @configurable.update(configurable_params)
        format.html { redirect_to [:admin, @configurable], notice: 'The setting was successfully updated.' }
        format.json { render :show, status: :ok, location: @configurable }
      else
        format.html { render :edit }
        format.json { render json: @configurable.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @configurable.destroy
    respond_to do |format|
      format.html { redirect_to admin_configurables_url, notice: 'The setting was successfully destroyed.' }
      format.json { head :no_content }
    end
  end  

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_configurable
      @configurable = Configurable.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def configurable_params
      params.require(:configurable).permit(:name, :value)
    end  

end

index.html.erb

<h1 class="page-header">Settings</h1>

<div class="table-responsive">
<table class="table table-striped">
  <thead>
    <tr>
      <th>Name</th>   
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @configurables.each do |configurable| %>
      <tr>
        <% if configurable.try(:name) %>
          <td><%= Configurable.defaults[configurable.name][:name]%></td>
          <td></td>   
          <td><%= link_to 'Show', [:admin, configurable] %></td>
          <td><%= link_to 'Edit', edit_admin_configurable_path(configurable) %></td>
          <td><%= link_to 'Destroy', [:admin, configurable], method: :delete, data: { confirm: 'Are you sure?' } %></td>
        <% else %>
          <td><%= Configurable.defaults[configurable][:name] %></td>     
          <td><%= link_to 'Create', new_admin_configurable_path(name: configurable) %></td>
          <td colspan="3"></td>
        <% end %>
      </tr>
    <% end %>
  </tbody>
</table>
</div>

edit.html.erb

<h1>Editing <%= @new ? "new " : "" %>setting</h1>

<%= render 'form', configurable: @configurable %>

<%= link_to 'Show', [:admin, @configurable] %> |
<%= link_to 'Back', admin_configurables_path %>

show.html.erb

<p>
  <strong>Name:</strong>
  <%= Configurable.defaults[@configurable.name][:name] %>
</p>

<p>
  <strong>Value:</strong>
  <%= @configurable.value %>
</p>


<%= link_to 'Edit', edit_admin_configurable_path(@configurable) %> |
<%= link_to 'Back', admin_configurables_path %>

_form.html.erb

<%= form_for([:admin, configurable]) do |f| %>

  <div class="field">
    <%= f.label "Name" %>
    <%= Configurable.defaults[@configurable.name][:name] %>
  </div>

  <div class="field">
    <%= f.label "Value" %>
    <%= f.text_area :value %>
  </div>  

  <div class="actions">
    <%= f.submit "Submit" %>
  </div>
<% end %>

Из-за жестко закодированных маршрутов мой контроллер не полностью совместим с REST, но он довольно близок. Мое действие new фактически создает параметр (хранимый в базе данных) (только для переопределения его значения yml файла).

Таким образом, этот код, добавленный в код описания gem, позволяет вам практически использовать параметры RoR, изменяемые во время выполнения.

Драгоценный камень требует, чтобы вы заранее задали некоторые значения по умолчанию в файле yml, которые вы можете переопределить позже во время выполнения. Но вы не можете создать новый параметр во время выполнения (не-yml-file-existent) - только изменить существующий (в yml файле) один, что вполне логично.

Или вы можете восстановить (во время выполнения) значение по умолчанию для любого параметра (путем удаления его переопределенного значения базы данных).

Этот код был проверен для работы с Rails 5.