rails settings cached
在Rails应用程序中存储全球设置的最佳解决方案。
该宝石将使管理全局密钥的表,值对。可以将其视为存储在您的数据库中的全局哈希,它使用了简单的ActivereCord进行操作的方法。跟踪您不想将其硬代码纳入Rails应用程序的任何全局设置。
安装
编辑您的Gemfile:
$ bundle add rails-settings-cached生成您的设置:
$ rails g settings:install
# Or use a custom name:
$ rails g settings:install AppConfig您将获得app/models/setting.rb
class Setting < RailsSettings :: Base
# cache_prefix { "v1" }
scope :application do
field :app_name , default : "Rails Settings" , validates : { presence : true , length : { in : 2 .. 20 } }
field :host , default : "http://*ex*am*ple.com" , readonly : true
field :default_locale , default : "zh-CN" , validates : { presence : true , inclusion : { in : %w[ zh-CN en jp ] } } , option_values : %w[ en zh-CN jp ] , help_text : "Bla bla ..."
field :admin_emails , type : :array , default : %w[ admin@rubyonrails.org ]
# lambda default value
field :welcome_message , type : :string , default : -> { "welcome to #{ self . app_name } " } , validates : { length : { maximum : 255 } }
# Override array separator, default: /[n,]/ split with n or comma.
field :tips , type : :array , separator : /[ n ]+/
end
scope :limits do
field :user_limits , type : :integer , default : 20
field :exchange_rate , type : :float , default : 0.123
field :captcha_enable , type : :boolean , default : true
end
field :notification_options , type : :hash , default : {
send_all : true ,
logging : true ,
sender_email : "foo@bar.com"
}
field :readonly_item , type : :integer , default : 100 , readonly : true
end您必须使用field方法来对设置键进行声明,否则您不能使用它。
scope方法允许您对admin UI的键进行分组。
现在只将该迁移放在数据库中:
$ rails db:migrate用法
语法很容易。首先,让我们创建一些设置以跟踪:
irb > Setting . host
"http://*ex*am*ple.com"
irb > Setting . app_name
"Rails Settings"
irb > Setting . app_name = " rails settings cached "
irb > Setting . app_name
" rails settings cached "
irb > Setting . user_limits
20
irb > Setting . user_limits = "30"
irb > Setting . user_limits
30
irb > Setting . user_limits = 45
irb > Setting . user_limits
45
irb > Setting . captcha_enable
1
irb > Setting . captcha_enable?
true
irb > Setting . captcha_enable = "0"
irb > Setting . captcha_enable
false
irb > Setting . captcha_enable = "1"
irb > Setting . captcha_enable
true
irb > Setting . captcha_enable = "false"
irb > Setting . captcha_enable
false
irb > Setting . captcha_enable = "true"
irb > Setting . captcha_enable
true
irb > Setting . captcha_enable?
true
irb > Setting . admin_emails
[ "admin@rubyonrails.org" ]
irb > Setting . admin_emails = %w[ foo@bar.com bar@dar.com ]
irb > Setting . admin_emails
[ "foo@bar.com" , "bar@dar.com" ]
irb > Setting . admin_emails = "huacnlee@gmail.com,admin@admin.com n admin@rubyonrails.org"
irb > Setting . admin_emails
[ "huacnlee@gmail.com" , "admin@admin.com" , "admin@rubyonrails.org" ]
irb > Setting . notification_options
{
send_all : true ,
logging : true ,
sender_email : "foo@bar.com"
}
irb > Setting . notification_options = {
sender_email : "notice@rubyonrails.org"
}
irb > Setting . notification_options
{
sender_email : "notice@rubyonrails.org"
}
获取定义的字段
版本2.3+
# Get all keys
Setting . keys
=> [ "app_name" , "host" , "default_locale" , "readonly_item" ]
# Get editable keys
Setting . editable_keys
=> [ "app_name" , "default_locale" ]
# Get readonly keys
Setting . readonly_keys
=> [ "host" , "readonly_item" ]
# Get field
Setting . get_field ( "host" )
=> { scope : :application , key : "host" , type : :string , default : "http://*ex*am*ple.com" , readonly : true }
Setting . get_field ( "app_name" )
=> { scope : :application , key : "app_name" , type : :string , default : "Rails Settings" , readonly : false }
Setting . get_field ( :user_limits )
=> { scope : :limits , key : "user_limits" , type : :integer , default : 20 , readonly : false }
# Get field options
Setting . get_field ( "default_locale" ) [ :options ]
=> { option_values : %w[ en zh-CN jp ] , help_text : "Bla bla ..." }定制类型用于设置
自:2.9.0
您可以通过RailsSettings::Fields模块编写自定义字段类型。
例如
module RailsSettings
module Fields
class YesNo < :: RailsSettings :: Fields :: Base
def serialize ( value )
case value
when true then "YES"
when false then "NO"
else raise StandardError , 'invalid value'
end
end
def deserialize ( value )
case value
when "YES" then true
when "NO" then false
else nil
end
end
end
end
end现在,您可以在设置中使用yes_no类型:
class Setting
field :custom_item , type : :yes_no , default : 'YES'
end irb > Setting . custom_item = 'YES'
irb > Setting . custom_item
true
irb > Setting . custom_item = 'NO'
irb > Setting . custom_item
false 获取所有定义的字段
版本2.7.0+
您可以使用defined_fields方法在设置中获取所有定义的字段。
# Get editable fields and group by scope
editable_fields = Setting . defined_fields
. select { | field | ! field [ :readonly ] }
. group_by { | field | field [ :scope ] } 验证
您可以使用validates选项来特殊轨道验证字段。
class Setting < RailsSettings :: Base
# cache_prefix { "v1" }
field :app_name , default : "Rails Settings" , validates : { presence : true , length : { in : 2 .. 20 } }
field :default_locale , default : "zh-CN" , validates : { presence : true , inclusion : { in : %w[ zh-CN en jp ] , message : "is not included in [zh-CN, en, jp]" } }
end现在,验证将在记录上工作:
irb > Setting . app_name = ""
ActiveRecord :: RecordInvalid : ( Validation failed : App name can ' t be blank )
irb > Setting . app_name = "Rails Settings"
"Rails Settings"
irb > Setting . default_locale = "zh-TW"
ActiveRecord :: RecordInvalid : ( Validation failed : Default locale is not included in [ zh - CN , en , jp ] )
irb > Setting . default_locale = "en"
"en"通过save / valid?方法:
setting = Setting . find_or_initialize_by ( var : :app_name )
setting . value = ""
setting . valid?
# => false
setting . errors . full_messages
# => ["App name can't be blank", "App name too short (minimum is 2 characters)"]
setting = Setting . find_or_initialize_by ( var : :default_locale )
setting . value = "zh-TW"
setting . save
# => false
setting . errors . full_messages
# => ["Default locale is not included in [zh-CN, en, jp]"]
setting . value = "en"
setting . valid?
# => true 在轨道中使用设置初始化:
在version 2.3+您可以在初始化导轨之前使用设置。
例如config/initializers/devise.rb
Devise . setup do | config |
if Setting . omniauth_google_client_id . present?
config . omniauth :google_oauth2 , Setting . omniauth_google_client_id , Setting . omniauth_google_client_secret
end
end class Setting < RailsSettings :: Base
field :omniauth_google_client_id , default : ENV [ "OMNIAUTH_GOOGLE_CLIENT_ID" ]
field :omniauth_google_client_secret , default : ENV [ "OMNIAUTH_GOOGLE_CLIENT_SECRET" ]
end Readonly字段
您可能还需要在Rails初始化之前使用设置:
config/environments/*.rb
如果您想这样做,则设置字段必须具有readonly: true 。
例如:
class Setting < RailsSettings :: Base
field :mailer_provider , default : ( ENV [ "mailer_provider" ] || "smtp" ) , readonly : true
field :mailer_options , type : :hash , readonly : true , default : {
address : ENV [ "mailer_options.address" ] ,
port : ENV [ "mailer_options.port" ] ,
domain : ENV [ "mailer_options.domain" ] ,
user_name : ENV [ "mailer_options.user_name" ] ,
password : ENV [ "mailer_options.password" ] ,
authentication : ENV [ "mailer_options.authentication" ] || "login" ,
enable_starttls_auto : ENV [ "mailer_options.enable_starttls_auto" ]
}
end配置/环境/生产.rb
# You must require_relative directly in Rails 6.1+ in config/environments/production.rb
require_relative "../../app/models/setting"
Rails . application . configure do
config . action_mailer . delivery_method = :smtp
config . action_mailer . smtp_settings = Setting . mailer_options . deep_symbolize_keys
end提示:您还可以按照此文件来重写ActionMailer的mail方法,以便从启动导轨后设置配置邮件选项。
https://github*.**com/ruby-china/homeland/blob/main/app/mailers/application_mailer.rb#l19
缓存流:
Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
|
Fetch all key and values from DB -> Write Cache -> Get value of key for cache -> return
|
Return default value or nil
在每个设置键调用中,我们将加载缓存/db并保存在ActiveSupport :: CurrentAttributes中,以避免击中缓存/DB。
每个密钥更新将过期缓存,因此请勿添加一些频繁的更新密钥。
更改缓存键
有时您可能需要强制更新缓存,现在您可以使用cache_prefix
class Setting < RailsSettings :: Base
cache_prefix { "you-prefix" }
...
end在测试中,您需要添加Setting.clear_cache 。每种测试用例Clear_cache:
class ActiveSupport :: TestCase
teardown do
Setting . clear_cache
end
end 如何管理管理接口中的设置?
如果要创建管理界面以编辑设置,则可以尝试以下方法:
config/routes.rb
namespace :admin do
resource :settings
endApp/Controllers/admin/settings_controller.rb
module Admin
class SettingsController < ApplicationController
def create
@errors = ActiveModel :: Errors . new
setting_params . keys . each do | key |
next if setting_params [ key ] . nil?
setting = Setting . new ( var : key )
setting . value = setting_params [ key ] . strip
unless setting . valid?
@errors . merge! ( setting . errors )
end
end
if @errors . any?
render :new
end
setting_params . keys . each do | key |
Setting . send ( " #{ key } =" , setting_params [ key ] . strip ) unless setting_params [ key ] . nil?
end
redirect_to admin_settings_path , notice : "Setting was successfully updated."
end
private
def setting_params
params . require ( :setting ) . permit ( :host , :user_limits , :admin_emails ,
:captcha_enable , :notification_options )
end
end
endapp/views/admin/settings/show.html.erb
-
<% @errors.full_messages.each do |msg| %>
- <%= msg %> <% end %>
<%= form_for(Setting.new, url: admin_settings_path) do |f| %> <% if @errors.any? %> < div class =" alert alert-block alert-danger " > < ul > <% @errors . full_messages . each do | msg | %> < li > <%= msg %> li > <% end %> ul > div > <% end %> < div class =" form-group " > < label class =" control-label " > Host label > <%= f . text_field :host , value : Setting . host , class : "form-control" , placeholder : "http://*loca*lho*st" %> div > < div class =" form-group form-checkbox " > < label > <%= f . check_box :captcha_enable , checked : Setting . captcha_enable? %> Enable/Disable Captcha label > div > < div class =" form-group " > < label class =" control-label " > Admin Emails label > <%= f . text_area :admin_emails , value : Setting . admin_emails . join ( " n " ) , class : "form-control" %> div > < div class =" form-group " > < label class =" control-label " > Notification options label > <%= f . text_area :notification_options , value : YAML . dump ( Setting . notification_options ) , class : "form-control" , style : "height: 180px;" %> < div class =" form-text " > Use YAML format to config the SMTP_html div > div > < div > <%= f . submit 'Update Settings' %> div > <% end %>
特殊的缓存存储
您可以使用cache_store更改缓存存储,默认为Rails.cache 。
添加config/initializers/rails_settings.rb
RailsSettings . configure do
self . cache_storage = ActiveSupport :: Cache :: RedisCacheStore . new ( url : "redis://localhost:6379" )
end 范围设置
休息更改警告:Rails-Settings-Sached 2.X已重新设计了API,新版本将与较旧版本的存储设置值兼容。当您想升级2.x时,必须再次阅读读书文件,然后遵循指南以更改设置模型。 0.x稳定分支:https://github.com/huacnlee/rails-settings-cached/tree/0.x
- 向后兼容以支持0.x范围的设置
适用于新项目 /轨道静止的新用户。 ActivereCord :: AttributeHods ::序列化是最佳选择。
这就是为什么轨道插座的2.x删除范围示波器设置功能的原因