rails_settings_cached_cr
Version, currently master branch1 version
- master branchlatestOct 15, 2026
github.com/OrelSokolov/rails_settings_cached.cr
Порт rails-settings-cached 2.9.5 (huacnlee) на Crystal — 1:1 API. Setting.field / cache_prefix / readonly / validates; кэш настроек через ActiveSupport::Cache, хранение — ActiveRecord (таблица settings, YAML в value совместим байт-в-байт с Ruby Psych).
Installation
# Add this to your shard.yml
dependencies:
rails_settings_cached_cr:
github: OrelSokolov/rails_settings_cached.cr
branch: mastermaster is a branch, not a release, so this tracks it rather than pinning a version.
Then run:
shards installshard.yml
- Crystal
>= 1.21.0- Author
- oleg
Dependencies
Runtime Dependencies
- active_record_cr~> 0.1.0github: OrelSokolov/active_record.cr
- active_support_cr~> 0.1.0github: OrelSokolov/active_support.cr
README
rails_settings_cached.cr
A Crystal port of huacnlee/rails-settings-cached
2.9.5 — cached, database-backed application settings as typed fields
on a settings (var, value) table. Values are stored as YAML
byte-compatible with Ruby Psych (string quoting rules, block styles,
BigDecimal marshal format), so a database written by the Ruby gem is
readable by the port and vice versa.
⚠️ EXPERIMENTAL — DO NOT USE IN PRODUCTION YET.
Installation
dependencies:
rails_settings_cached_cr:
github: OrelSokolov/rails_settings_cached.cr
shards install
Requires PostgreSQL (test DB crails_rsc_test, override with
RSC_TEST_URL); depends on active_record.cr and active_support.cr.
Usage
class Setting < RailsSettings::Base
cache_prefix { "v1" }
scope :application do
field :host, default: "http://example.com", validates: {presence: true}
field :admin_emails, type: :array, default: %w[admin@rubyonrails.org]
field :captcha_enable, type: :boolean, default: true
field :user_limits, type: :integer, default: 1,
validates: {format: {with: /\d+/, message: "must be numbers"}}
end
end
Setting.host # => "http://example.com"
Setting.host = "https://..." # saves! (RecordInvalid on validation failure)
Setting.captcha_enable? # boolean predicate
Setting.clear_cache
Feature comparison vs rails-settings-cached 2.9.5
| Feature | Original (rails-settings-cached) | Port (rails_settings_cached.cr) | Status |
|---|---|---|---|
field with type:, default:, readonly:, separator:, extra options | ✅ | Macro — key must be an identifier literal; values are RailsSettings::FieldValue (typed union) | 🔶 |
Field types :string :integer :float :big_decimal :boolean :array :hash, custom Fields::Custom(T) < Base(T), unknown type → String | ✅ | Same | ✅ |
scope blocks | ✅ | Same (scope with an extension block not supported) | 🔶 |
cache_prefix { "v1" } → Setting.cache_key (rails-settings-cached/v1) | ✅ | Same; runtime override via Setting.__rs_override_cache_prefix = "v2" | 🔶 |
Getter/setter class API, boolean predicates, Setting.keys / editable_keys / readonly_keys / defined_fields | ✅ | Same | ✅ |
get_field("host") | ✅ (returns Hash) | Returns a Field object or nil | 🔶 |
YAML storage byte-compatible with Ruby Psych (quoting 'true'/'42'/"y"/'1:2', block styles, BigDecimal !ruby/object:BigDecimal) | ✅ | Same, round-trip verified | ✅ |
Cache via ActiveSupport::Cache, expires_in: 7.days, _all_settings JSON-serialized, clear_cache | ✅ | Same; default store is MemoryStore (no global Rails.cache — the app overrides in configure) | 🔶 |
Cache invalidation on commit (after_commit on create/update/destroy) | ✅ | Via an __run_after_commit interception | ✅ |
validates: (presence/format/inclusion, Rails messages: "can't be blank", custom, "is not included in the list") | ✅ | Same; validation reads the YAML-decoded value, runs only for records with var == key | ✅ |
RailsSettings.config.cache_storage, RailsSettings.configure, RailsSettings.version | ✅ | Same | ✅ |
| RequestCache + Middleware | ✅ | RequestCache is a class variable (no fiber-local storage); requests must end with disable! | 🔶 |
Symbols round-trip (keys :foo, values :symbol) | ✅ | Dumped YAML-compatibly, but read back as Strings (no runtime String#to_sym) | 🔶 |
Writing readonly/nonexistent field → NoMethodError | ✅ | Compile-time error; tests check with responds_to? | ❌ (equivalent: compile-time check) |
NoConnectionSetting (no-DB mode) | ✅ | Not ported (single global connection) | ⬜ |
Deviations & Crystal-specific notes
field/scope/cache_prefixare macros; model-level API is generated in amacro finishedpass from compile-time registries.- Integer fields return
Int64; the instance gettervalueis the raw DB string — userecord.decoded_valuefor YAML decoding. to_sqlfrom active_record.cr uses its own format (explicit column list,$1placeholders).use_parent_strategy-style stub semantics do not apply here; see factory_bot.cr for its own notes.
Testing
crystal spec # 141 examples
spec/oracle_spec.cr— 111 cases recorded with the real gem (oracle/cases.rb→oracle/expected.yml, Ruby + AR 8.1 + SQLite), replayed 1:1 (values, byte-identicalsettings.value, error and validation texts).spec/base_spec.cr,spec/validation_spec.cr— ports of the gem'sbase_test.rb/validation_test.rb.
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This branch
- Branch
master- Seen
- Oct 15, 2026
- Crystal
>= 1.21.0- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/OrelSokolov/rails_settings_cached.cr
Metadata
- Created
- Oct 12, 2026
- Updated
- Oct 23, 2026
- Synced
- Oct 22, 2026
- Versions
- 1