{"id":24582670,"url":"https://github.com/ez-engines/ez-settings","last_synced_at":"2025-04-24T05:04:57.365Z","repository":{"id":22115544,"uuid":"94803233","full_name":"ez-engines/ez-settings","owner":"ez-engines","description":"Ez Settings (read as \"easy settings\") - one of the ez-engines collection that helps easily add settings interface to your Rails application.","archived":false,"fork":false,"pushed_at":"2023-01-19T23:31:18.000Z","size":133,"stargazers_count":9,"open_issues_count":17,"forks_count":7,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-24T05:04:36.254Z","etag":null,"topics":["component","easy","engines","modular","rails","rails-engine"],"latest_commit_sha":null,"homepage":"https://github.com/ez-engines","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ez-engines.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-19T17:31:54.000Z","updated_at":"2023-08-30T09:55:48.000Z","dependencies_parsed_at":"2023-02-11T22:30:26.401Z","dependency_job_id":null,"html_url":"https://github.com/ez-engines/ez-settings","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ez-engines%2Fez-settings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ez-engines%2Fez-settings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ez-engines%2Fez-settings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ez-engines%2Fez-settings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ez-engines","download_url":"https://codeload.github.com/ez-engines/ez-settings/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250566458,"owners_count":21451231,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component","easy","engines","modular","rails","rails-engine"],"created_at":"2025-01-24T03:25:44.364Z","updated_at":"2025-04-24T05:04:57.339Z","avatar_url":"https://github.com/ez-engines.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ez::Settings\n\n[![Gem Version](https://badge.fury.io/rb/ez-settings.svg)](https://badge.fury.io/rb/ez-settings)\n[![Build Status](https://travis-ci.org/ez-engines/ez-settings.svg?branch=master)](https://travis-ci.org/ez-engines/ez-settings)\n\n**Ez Settings** (read as \"easy settings\") - one of the [ez-engines](https://github.com/ez-engines) collection that helps easily add settings interface to your [Rails](http://rubyonrails.org/) application.\n\n- Flexible tool with simple DSL\n- Convetion over configuration principles.\n- Depends on [ez-core](https://github.com/ez-engines/ez-core)\n\n## Installation\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'ez-settings', '~\u003e 0.1'\n```\n\nAnd then execute:\n```bash\n$ bundle\n```\n\nOr install it yourself as:\n```bash\n$ gem install ez-settings\n```\n\nand `bundle install`\n\n### Initialize\n\n`rails generate ez:settings:install`\n\nGenerates initializer config file and I18n yaml file with english keys\n\n`config/initializers/ez_settings.rb`\n```ruby\n# By default engine try to inherit from ApplicationController, but you could change this:\n# Ez::Settings.config.base_controller = 'Admin::BaseController'\n#\n# Then you should define settings interfaces (you can create as much as you need)\n# Ierachy is pretty simple: Interface -\u003e Group -\u003e Key\n#\n# Interface DSL allows you to do this very declaratively\n#\napp = Ez::Settings::Interface.define :app do         # :app - interface name\n  group :general do                                  # :general - name of the group\n    key :app_title, default: -\u003e { 'Main app title' } # :app_title - key name for store value in :general group for :app interface\n  end\n\n  # And so on...\n  group :admin do\n    key :app_title, default: -\u003e { 'Admin app title' }\n  end\n\n  # If you want to see all power of the engine, add this showcase:\n  group :showcase, on_change: -\u003e(changes) { YourHandler.call(changes) } do\n    key :string,                        default: -\u003e { 'simple string' }\n    key :bool,         type: :boolean,  default: -\u003e { true }\n    key :integer,      type: :integer,  default: -\u003e { 777 }, min: 0, suffix: 'USD', wrapper: :custom_wrapper\n    key :select,       type: :select,   default: -\u003e { 'foo' }, collection: %w(foo bar baz)\n    key :not_validate, required: false, presence: false\n    key :not_for_ui,   required: false, ui:       false\n  end\n  # Group could have:\n  # :on_change - closure to call after the group is changed\n  # Keys could have:\n  # :type (string by default), now ez-settings supports only: string, boolean, integer and select\n  # :default value (as callable objects)\n  # :required - be or not (all keys are required by default)\n  # :ui visible or not (all keys are UI visible by default)\n  # :min - the minimum value for the element\n  # :suffix - unit of measurement\n  # :wrapper - custom wrapper for simple_form\nend\n\n# After defining settings interface groups/keys you need to configure it:\napp.configure do |config|\n  # Backend adapter to store all settings\n  config.backend = Ez::Settings::Backend::ActiveRecord.new\n  # and DB table name that you can change as well\n  # config.active_record_table_name = :ez_settings_store\n\n  # YAML filesystem\n  # config.backend = Ez::Settings::Backend::FileSystem.new(Rails.root.join('config', 'settings.yml'))\n\n  # Redis\n  # require 'redis'\n  # config.backend = Ez::Settings::Backend::Redis.new(Redis.current, namespace: 'myapp')\n\n  # Default path for redirect in the settings controller\n  config.default_path = '/admin/settings'\n\n  # Pass your custom css classes through css_map config\n  # Defaults would be merged with yours:\n  # config.custom_css_map  = {\n  #   nav_label:                           'ez-settings-nav-label',\n  #   nav_menu:                            'ez-settings-nav-menu',\n  #   nav_menu_item:                       'ez-settings-nav-menu-item',\n  #   overview_page_wrapper:               'ez-settings-overview',\n  #   overview_page_section:               'ez-settings-overview-section',\n  #   overview_page_section_header:        'ez-settings-overview-section-header',\n  #   overview_page_section_content:       'ez-settings-overview-section-content',\n  #   overview_page_section_content_key:   'ez-settings-overview-section-content-key',\n  #   overview_page_section_content_value: 'ez-settings-overview-section-content-value',\n  #   group_page_wrapper:                  'ez-settings-group-wrapper',\n  #   group_page_inner_wrapper:            'ez-settings-group-inner-wrapper',\n  #   group_page_header:                   'ez-settings-group-header',\n  #   group_page_form_wrapper:             'ez-settings-group-form-wrapper',\n  #   group_page_form_inner:               'ez-settings-group-form-inner',\n  #   group_page_form_field_row:           'ez-settings-group-form-field-row',\n  #   group_page_form_string_wrapper:      'ez-settings-group-form-string-wrapper',\n  #   group_page_form_boolean_wrapper:     'ez-settings-group-form-boolean-wrapper',\n  #   group_page_form_select_wrapper:      'ez-settings-group-form-select-wrapper',\n  #   group_page_actions_wrapper:          'ez-settings-group-actions-wrapper',\n  #   group_page_actions_save_button:      'ez-settings-group-actions-save-btn',\n  #   group_page_actions_cancel_link:      'ez-settings-group-actions-cancel-link'\n  # }\n  #\n  # Highly recommend inspecting settings page DOM.\n  # You can find there a lot of interesting id/class stuff\n  #\n  # You even can define dynamic map for allows to decide which CSS class could be added\n  # `if` must contain callable object that receives controller as a first argument and dynamic element as second one:\n  #\n  # In this example, you easily could add 'active' CSS class if route end with some fragment:\n  # config.dynamic_css_map = {\n  #   nav_menu_item: {\n  #     css_class: 'active',\n  #     if: -\u003e(controller, path_fragment) { controller.request.path.end_with?(path_fragment.to_s) }\n  #   }\n  # }\nend\n\n# Ez::Settings uses Ez::Registry from ez-core lib for storing all knowledges in one place.\n# This place is registry records for :settings_interfaces registry\n#\n# Register `app` variable as settings interface\nEz::Registry.in(:settings_interfaces, by: 'YourAppName') do |registry|\n  registry.add app\nend\n```\n\n\n### Database storage as backend (ActiveRecord)\n\nYou can use migrations generator\n\n`rails generate ez:settings:active_record_migrations`\n\nGenerates migration for `ez_settings_store` table.\n\n`rails db:migrate`\n\n\n\n### Routes\n`config/routes.rb`\n\n```ruby\nRails.application.routes.draw do\n  # your routes code before\n\n  # We recommend to hide settings into admin area\n  authenticate :user, -\u003e(u) { u.admin? } do\n    namespace :admin do\n      # :app just interface name as you registred it in Ez::Registry\n      ez_settings_for :app\n    end\n  end\n\n  # more your routes after\nend\n```\n\nThis routes setup allows you to have routes like:\n\n`rake routes | grep settings`\n```\n admin_ez_settings          /admin/settings  Ez::Settings::Engine {:interface=\u003e:app}\n\n  root GET  /                 ez/settings/settings#index\n       GET  /:group(.:format) ez/settings/settings#show\n       PUT  /:group(.:format) ez/settings/settings#update\n```\n\nIn case of example above you could route:\n```\nGET      /admin/settings/         - overview page for all :app interface settings\nGET/PUT: /admin/settings/general  - general group settings\nGET/PUT: /admin/settings/admin    - admin group settings\nGET/PUT: /admin/settings/showcase - showcase group settings\n```\n\n### Settings accessors\nTo access your settings use template `Ez::Settings['interface', 'group', 'key']`.\n\nAccess interface:\n```ruby\nEz::Settings[:app]\n#=\u003e \u003cEz::Settings::Interface:0x007ff1ea7d3168 @groups=[...], @keys=[], @name=:app\u003e\n```\n\nAccess group:\n```ruby\nEz::Settings[:app, :general]\n#=\u003e \u003cEz::Settings::Interface::Group:0x007ff1ea7d2f88 @interface=:app, @keys=[...], @name=:general, @options={}\u003e\n```\n\nAccess setting value:\n```ruby\nEz::Settings[:app, :general, :app_title]\n# =\u003e 'Main app title'\n```\n\nIn the case of missing interface/group/key you will receive one of exceptions:\n```\nNotRegistredInterfaceError\nNotRegistredGroupError\nNotRegistredKeyError\n```\n\nBe careful ;)\n\n### I18n\n\nBy default, all interfaces/groups/keys name would be humanized, but in fact, it tries to get translations from YAML first.\n\nIf you need, create locale file with this structure:\n\n`config/locales/ez-settings.en.yml`\n```yaml\n  en:\n    ez_settings:\n      label: Ez Settings\n      interfaces:\n        app:\n          label: App Settings\n          actions:\n            save:\n              label: Save Settings\n            cancel:\n              label: Cancel Settings\n          groups:\n            general:\n              label: General\n              description: General settings of your application\n            admin:\n              label: Admin\n              description: Admin area settings\n            showcase:\n              label: Showcase\n              description: Just an example of possible settings UI elements\n              keys:\n                string:\n                  label: String\n                bool:\n                  label: Bool\n                integer:\n                  label: Integer\n                select:\n                  label: Select\n                not_validate:\n                  label: Not Validate\n                not_for_ui:\n                  label: Not For UI\n```\n\n## TODO\nThis features will be implemented in upcoming 0.2 and 0.3 releases:\n- [] JSON API endpoints and `ez_settings_api_for` routes helper\n- [] Scoped settings (`:scope_id`, `:scope_type`)\n- [] Controller before actions as configured callbacks (for external usage)\n- [] Interface description (and show at UI)\n- [] Groups description (and show at UI)\n- [] Keys description (and show at UI)\n- [] Database storage as backend (ActiveRecord)\n- [] Backend#read method should receive app, group \u0026 key attributes and avoid loading all in case of SQL adapter\n- [] UI frameworks adapters: bootsrap3, bootstrap4, foundation, semantic, etc.\n- [X] Bug: Read only defaul values if ActiveRecord do not ready yet (migrations)\n\n## Contributing\nFork =\u003e Fix =\u003e MR warmly welcomed!\n\n## License\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fez-engines%2Fez-settings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fez-engines%2Fez-settings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fez-engines%2Fez-settings/lists"}