[英]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”創建自己的緩存
嘗試查看它可能是您所需要的。
最好的方法是使用數據庫表。 每行應包含一個關鍵字和一個值。 簡單。
對於rails 4,如果您使用的是postgresql,則可以使用HStore ,它類似於可序列化的屬性,但是您可以使用它進行SQL查詢。
對於rails 3,可以使用activerecord-postgres-hstore gem。
我本人已經使用app_config gem有一段時間了,但是它在Rails 2.3.9(可能還與Rails 3.x)上失敗了,所以我發現這個博客提到了rails-settings和configuration ,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.