繁体   English   中英

Ruby on Rails-存储应用程序配置

[英]Ruby on Rails - Storing application configuration

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

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

有没有其他地方可以定义此信息,还是最好将其保存在数据库中?

任何建议表示赞赏。

谢谢。

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

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

Setting.foo = 123
Setting.foo # returns 123

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

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

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

尝试查看它可能是您所需要的。

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

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

对于rails 4,如果您使用的是postgresql,则可以使用HStore ,它类似于可序列化的属性,但是您可以使用它进行SQL查询。

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

我本人已经使用app_config gem有一段时间了,但是它在Rails 2.3.9(可能还与Rails 3.x)上失败了,所以我发现这个博客提到了rails-settingsconfiguration ,rails-settings将值存储在DB中,但是配置具有内置的名称空间。 我没有尝试过,但是我想我会切换到Rails-settings。

我现在注意到, 林逸如提到的rails-settings分支似乎比其他rails-settings更具特色。

贵族

我尝试了https://github.com/huacnlee/rails-settings-cached ,但是它不能像描述的那样工作。 显然,作者忘记了在宝石用法说明中提到的其他一些改进。 我未能编写用于设置操作的控制器。

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

configurable_engine 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文件中预先设置一些默认值,稍后可以在运行时覆盖它们。 但是您不能在运行时创建新设置(不存在yml文件)-仅修改存在(在yml文件中)的设置-这是很合逻辑的。

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

该代码已经过检查,可以与Rails 5一起使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM