Giter Club home page Giter Club logo

rails-settings-cached's Introduction

Rails Settings Cached

This a plugin that makes managing a table of ะฐ global key, value pairs easy. Think of it like a global Hash stored in your database, that uses simple ActiveRecord like methods for manipulation. Keep track of any global setting that you don't want to hard code into your rails app. You can store any kind of object. Strings, numbers, arrays, or any object.

Gem Version CI Status codecov.io

Installation

Edit your Gemfile:

$ bundle add rails-settings-cached

Generate your settings:

$ rails g settings:install

# Or use a custom name:
$ rails g settings:install AppConfig

You will get app/models/setting.rb

class Setting < RailsSettings::Base
  # cache_prefix { "v1" }
  field :app_name, default: "Rails Settings"
  field :host, default: "http://example.com", readonly: true
  field :default_locale, default: "zh-CN"
  field :readonly_item, type: :integer, default: 100, readonly: true
  field :user_limits, type: :integer, default: 20
  field :exchange_rate, type: :float, default: 0.123
  field :admin_emails, type: :array, default: %w[[email protected]]
  field :captcha_enable, type: :boolean, default: true

  # Override array separator, default: /[\n,]/ split with \n or comma.
  field :tips, type: :array, separator: /[\n]+/

  field :notification_options, type: :hash, default: {
    send_all: true,
    logging: true,
    sender_email: "[email protected]"
  }

  # lambda default value
  field :welcome_message, type: :string, default: -> { "welcome to #{self.app_name}" }
end

You must use field method to statement the setting keys, otherwise you can't use it.

Now just put that migration in the database with:

$ rails db:migrate

Usage

The syntax is easy. First, let's create some settings to keep track of:

irb > Setting.host
"http://example.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
["[email protected]"]
irb > Setting.admin_emails = %w[[email protected] [email protected]]
irb > Setting.admin_emails
["[email protected]", "[email protected]"]
irb > Setting.admin_emails = "[email protected],[email protected]\n[email protected]"
irb > Setting.admin_emails
["[email protected]", "[email protected]", "[email protected]"]

irb > Setting.notification_options
{
  send_all: true,
  logging: true,
  sender_email: "[email protected]"
}
irb > Setting.notification_options = {
  sender_email: "[email protected]"
}
irb > Setting.notification_options
{
  sender_email: "[email protected]"
}

Get defined fields

version 2.3+

# Get all keys
Setting.keys
=> ["app_name", "host", "default_locale", "readonly_item"]

# Get editable keys
Settng.editable_keys
=> ["app_name", "default_locale"]

# Get readonly keys
Setting.readonly_keys
=> ["host", "readonly_item"]

# Get options of field
Setting.get_field("host")
=> { key: "host", type: :string, default: "http://example.com", readonly: true }
Setting.get_field("app_name")
=> { key: "app_name", type: :string, default: "Rails Settings", readonly: false }

Use Setting in Rails initializing:

In version 2.3+ we allows you to use Setting before Rails is initialized.

For example 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 field

You may also want use Setting before Rails initialize:

config/environments/*.rb

If you want do that do that, the setting field must has readonly: true.

For example:

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

config/environments/production.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

Caching flow:

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

In each Setting keys call, we will load the cache/db and save in ActiveSupport::CurrentAttributes to avoid hit cache/db.

Each key update will expire the cache, so do not add some frequent update key.

Change cache key

Some times you may need to force update cache, now you can use cache_prefix

class Setting < RailsSettings::Base
  cache_prefix { "you-prefix" }
  ...
end

In testing, you need add Setting.clear_cache for each Test case:

class ActiveSupport::TestCase
  teardown do
    Setting.clear_cache
  end
end

How to manage Settings in the admin interface?

If you want to create an admin interface to editing the Settings, you can try methods in following:

config/routes.rb

namespace :admin do
  resource :settings
end

app/controllers/admin/settings_controller.rb

module Admin
  class SettingsController < ApplicationController
    def create
      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
end

app/views/admin/settings/show.html.erb

<%= form_for(Setting.new, url: admin_settings_path) do |f| %>
  <div class="form-group">
    <label class="control-label">Host</label>
    <%= f.text_field :host, value: Setting.host, class: "form-control", placeholder: "http://localhost"  %>
  </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 %>

Scoped Settings

๐Ÿšจ BREAK CHANGES WARNING: rails-settings-cached 2.x has redesigned the API, the new version will compatible with the stored setting values by an older version. When you want to upgrade 2.x, you must read the README again, and follow guides to change your Setting model. 0.x stable branch: https://github.com/huacnlee/rails-settings-cached/tree/0.x

For new project / new user of rails-settings-cached. The ActiveRecord::AttributeMethods::Serialization is best choice.

This is reason of why rails-settings-cached 2.x removed Scoped Settings feature.

For example:

We wants a preferences setting for user.

class User < ActiveRecord::Base
  serialize :preferences
end

@user = User.new
@user.preferences[:receive_emails] = true
@user.preferences[:public_email] = true
@user.save

Use cases:

And more than 1K repositories used.

rails-settings-cached's People

Contributors

accessd avatar adambutler avatar alexanderadam avatar alexjwayne avatar amanfrinati avatar berkos avatar brandoncordell avatar brentkearney avatar dangerous avatar dependabot[bot] avatar hovsater avatar huacnlee avatar huobazi avatar jehops avatar justin-natance avatar justin808 avatar kennethteh90 avatar kiela avatar ledermann avatar merqlove avatar mgrachev avatar miks avatar mlandauer avatar ncreuschling avatar paxa avatar phlipper avatar pmq20 avatar roschaefer avatar sangnguyen1001 avatar tsipiniuk avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.