【问题标题】:Ruby on Rails - Storing application configurationRuby on Rails - 存储应用程序配置
【发布时间】:2011-01-08 20:03:24
【问题描述】:

我有一个相对简单的 Rails 应用程序,我想存储管理员用户可以在应用程序运行时更改的各种配置设置,例如,允许帖子上的 cmets 或更改日期的显示格式。

我知道我可以在 environment.rb 文件中存储常量等,但是这些似乎只有在服务器重新启动时才会加载。

我可以在其他地方定义此信息还是将其保存在数据库中更好?

任何建议表示赞赏。

谢谢。

【问题讨论】:

    标签: ruby-on-rails configuration


    【解决方案1】:

    您可以使用 rails-settings-cached gem,它是 rails-settings gem 的一个分支(由 Yi-Ru Lin 在另一个答案中链接)。

    设置完成后,您将能够执行以下操作:

    Setting.foo = 123
    Setting.foo # returns 123
    

    您还可以管理模型的设置,例如:

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

    【讨论】:

      【解决方案2】:

      您可以使用数据库。创建一个单独的表“设置”来存储您需要的键/值参数。此解决方案的缺点是性能下降(每次需要设置时都查询数据库)。要解决此问题,您可以通过“cache_money”之类的缓存读取/写入,或者使用“Rails.cache”创建自己的缓存

      【讨论】:

      • 刚刚发布了一个答案,该方法将设置保存在数据库中,根据需要更新它们,并且在不使用缓存数据库内容的情况下不会遇到性能问题。
      【解决方案3】:

      试着看看它可能是你需要的。

      http://github.com/ledermann/rails-settings

      【讨论】:

      • squeegy repo 已经过时了 4 年,无法与现代 rails 一起使用。 ledermann gem 要求您绑定到另一个活动记录对象(使其无法用于全局应用程序设置。)如果您想要全局应用程序设置,github.com/huacnlee/rails-settings-cached 是最好的
      【解决方案4】:

      最好的方法是使用数据库表。每行应包含一个关键字和一个值。简单。

      【讨论】:

      • 好的,但是您将如何管理不同的数据类型?例如,有些设置是布尔值,有些是字符串,有些是整数等
      • 你不能只使用一行并将每个设置添加为一列吗?检索设置就像 SELECT enable_setting FROM server_settings LIMIT 1;
      【解决方案5】:

      我自己使用app_config gem 有一段时间了,但它在rails 2.3.9 上失败了(也可能在rails 3.x 上),所以我发现this blog 提到了rails-settingsconfiguration, rails-settings 将值存储在 DB 中,但配置具有内置的命名空间。我还没有尝试过,但我想我会切换到 rails-settings。

      我现在注意到the branch of rails-settings that Yi-Ru Lin mentions 似乎比其他rails-settings 更有特色

      贾尔

      【讨论】:

        【解决方案6】:

        对于rails 4,如果你使用的是postgresql,你可以使用HStore,这就像一个可序列化的属性,但是你用它来做SQL查询。

        对于 rails 3,您可以使用 activerecord-postgres-hstore gem。

        【讨论】:

          【解决方案7】:

          我试过https://github.com/huacnlee/rails-settings-cached,但它不像描述的那样工作。显然作者忘记在 gem 使用说明中提到一些额外的调整。我未能编写用于设置操作的控制器。

          相反,我成功地使用了https://github.com/paulca/configurable_engine - 尽管有一些小问题,但这个 gem 远比 rails-settings-cached 合理。

          configurable_engine gem 有一个缺点:它的硬编码路线晦涩难懂且不方便。 gem的作者promised to correct it,但表示目前没空。

          因此,只需创建自己的路线即可轻松解决此问题。这是我的代码(添加以使这个 gem 真正起作用):

          routes.rb

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

          admin/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 设置。

          gem 要求您提前在 yml 文件中设置一些默认值,您可以稍后在运行时覆盖这些默认值。但是你不能在运行时创建一个新设置(not-yml-file-existent)——只能修改一个存在的(在 yml 文件中)——这很合乎逻辑。

          或者您可以(在运行时)恢复任何设置的默认值(通过删除其数据库存储的覆盖值)。

          已检查此代码可与 Rails 5 一起使用。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-10
            • 1970-01-01
            • 2013-06-19
            • 2011-05-15
            • 2017-12-09
            • 1970-01-01
            相关资源
            最近更新 更多