ez-settings 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +241 -0
- data/Rakefile +28 -0
- data/app/assets/config/ez_settings_manifest.js +2 -0
- data/app/assets/javascripts/ez/settings/application.js +13 -0
- data/app/assets/stylesheets/ez/settings/application.css +15 -0
- data/app/cells/ez/settings/base_cell.rb +95 -0
- data/app/cells/ez/settings/group/show.slim +17 -0
- data/app/cells/ez/settings/group_cell.rb +26 -0
- data/app/cells/ez/settings/index/show.slim +18 -0
- data/app/cells/ez/settings/index_cell.rb +4 -0
- data/app/cells/ez/settings/key/show.slim +4 -0
- data/app/cells/ez/settings/key_cell.rb +21 -0
- data/app/cells/ez/settings/nav/show.slim +9 -0
- data/app/cells/ez/settings/nav_cell.rb +13 -0
- data/app/controllers/ez/settings/application_controller.rb +11 -0
- data/app/controllers/ez/settings/settings_controller.rb +35 -0
- data/app/helpers/ez/settings/application_helper.rb +6 -0
- data/app/models/ez/settings/application_record.rb +7 -0
- data/config/routes.rb +8 -0
- data/lib/ez/settings.rb +10 -0
- data/lib/ez/settings/accessors.rb +31 -0
- data/lib/ez/settings/backend/file_system.rb +24 -0
- data/lib/ez/settings/config.rb +9 -0
- data/lib/ez/settings/engine.rb +13 -0
- data/lib/ez/settings/interface.rb +65 -0
- data/lib/ez/settings/interface/group.rb +44 -0
- data/lib/ez/settings/interface/key.rb +24 -0
- data/lib/ez/settings/request_dispatcher.rb +19 -0
- data/lib/ez/settings/routes.rb +7 -0
- data/lib/ez/settings/store.rb +80 -0
- data/lib/ez/settings/version.rb +5 -0
- data/lib/generators/ez/settings/install_generator.rb +1 -0
- metadata +259 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab92996758b0720c782a270a27937d4e62d2f84a
|
4
|
+
data.tar.gz: ccad41c32652e4f590a428b7e64268e0605b1ee3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a07335a8448a2baf82d96f22c67855aa02c24cb8b2e8a2f9f14fa3a6304cf2b53448aa717670238253efef4aaa2515975787d6dba3cd31db8cfabab5940673d
|
7
|
+
data.tar.gz: a61b3c69ff16ebe41297861b902add48fe025da4e95e748610c0e89570244293a6aeb238a7fca05b25df37ff151f3f8eb50e8fbcbdae85c682df42049816e0c2
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Volodya Sveredyuk
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
# Ez::Settings
|
2
|
+
**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.
|
3
|
+
|
4
|
+
- Flexible tool with simple DSL
|
5
|
+
- Convetion over configuration principles.
|
6
|
+
- Depends on [ez-core](https://github.com/ez-engines/ez-core)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'ez-settings'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
```bash
|
17
|
+
$ bundle
|
18
|
+
```
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
```bash
|
22
|
+
$ gem install ez-settings
|
23
|
+
```
|
24
|
+
|
25
|
+
## Setup
|
26
|
+
|
27
|
+
### Initializer
|
28
|
+
|
29
|
+
Create initializer: `config/initializers/ez_settings.rb` (rails generator would be added in 0.2 version)
|
30
|
+
|
31
|
+
If you are boring to read all this stuff maybe this video motivates you:
|
32
|
+
|
33
|
+
[YouTube demonstrates how easy we integrated ez-settings for our pivorak-web-app only by ±50 lines of code](https://www.youtube.com/watch?v=TiX0QDHEaKA&feature=youtu.be)
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# By default engine try to inherit from ApplicationController, but you could change this:
|
37
|
+
# Ez::Settings.config.base_controller = 'Admin::BaseController'
|
38
|
+
#
|
39
|
+
# Then you should define settings interfaces (you can create as much as you need)
|
40
|
+
# Ierachy is pretty simple: Interface -> Group -> Key
|
41
|
+
#
|
42
|
+
# Interface DSL allows you to do this very declaratively
|
43
|
+
#
|
44
|
+
#
|
45
|
+
app = Ez::Settings::Interface.define :app do # :app - interface name
|
46
|
+
group :general do # :general will be name of the group
|
47
|
+
key :app_title, default: -> { 'Main app title' } # :app_title will be as settings key name for store value in :general group for :app interface
|
48
|
+
end
|
49
|
+
|
50
|
+
# And so on...
|
51
|
+
group :admin do
|
52
|
+
key :app_title, default: -> { 'Admin app title' }
|
53
|
+
end
|
54
|
+
|
55
|
+
# If you want to see all power of the engine, add this showcase:
|
56
|
+
group :showcase do
|
57
|
+
key :string, default: -> { 'simple string' }
|
58
|
+
key :bool, type: :boolean, default: -> { true }
|
59
|
+
key :integer, type: :integer, default: -> { 777 }
|
60
|
+
key :select, type: :select, default: -> { 'foo' }, collection: %w(foo bar baz)
|
61
|
+
key :not_validate, required: false, presence: false
|
62
|
+
key :not_for_ui, required: false, ui: false
|
63
|
+
end
|
64
|
+
# Keys could have:
|
65
|
+
# :type (string by default), now ez-settings supports only: string, boolean, integer and select
|
66
|
+
# :default value (as callable objects)
|
67
|
+
# :required - be or not (all keys are required by default)
|
68
|
+
# :ui visible or not (all keys are UI visible by default)
|
69
|
+
end
|
70
|
+
|
71
|
+
# After defining settings interface groups/keys you need to configure it:
|
72
|
+
app.configure do |config|
|
73
|
+
# Backend adapter to store all settings (in current version only file system)
|
74
|
+
config.backend = Ez::Settings::Backend::FileSystem.new(Rails.root.join('config', 'settings.yml'))
|
75
|
+
|
76
|
+
# Default path for redirect in controller
|
77
|
+
config.default_path = '/admin/settings'
|
78
|
+
|
79
|
+
# Pass your custom css classes through css_map config
|
80
|
+
# Defaults would be merged with yours:
|
81
|
+
# config.custom_css_map = {
|
82
|
+
# nav_label: 'ez-settings-nav-label',
|
83
|
+
# nav_menu: 'ez-settings-nav-menu',
|
84
|
+
# nav_menu_item: 'ez-settings-nav-menu-item',
|
85
|
+
# overview_page_wrapper: 'ez-settings-overview',
|
86
|
+
# overview_page_section: 'ez-settings-overview-section',
|
87
|
+
# overview_page_section_header: 'ez-settings-overview-section-header',
|
88
|
+
# overview_page_section_content: 'ez-settings-overview-section-content',
|
89
|
+
# overview_page_section_content_key: 'ez-settings-overview-section-content-key',
|
90
|
+
# overview_page_section_content_value: 'ez-settings-overview-section-content-value',
|
91
|
+
# group_page_wrapper: 'ez-settings-group-wrapper',
|
92
|
+
# group_page_inner_wrapper: 'ez-settings-group-inner-wrapper',
|
93
|
+
# group_page_header: 'ez-settings-group-header',
|
94
|
+
# group_page_form_wrapper: 'ez-settings-group-form-wrapper',
|
95
|
+
# group_page_form_inner: 'ez-settings-group-form-inner',
|
96
|
+
# group_page_form_field_row: 'ez-settings-group-form-field-row',
|
97
|
+
# group_page_form_string_wrapper: 'ez-settings-group-form-string-wrapper',
|
98
|
+
# group_page_form_boolean_wrapper: 'ez-settings-group-form-boolean-wrapper',
|
99
|
+
# group_page_form_select_wrapper: 'ez-settings-group-form-select-wrapper',
|
100
|
+
# group_page_actions_wrapper: 'ez-settings-group-actions-wrapper',
|
101
|
+
# group_page_actions_wrapper: 'ez-settings-group-actions-wrapper',
|
102
|
+
# group_page_actions_save_button: 'ez-settings-group-actions-save-btn',
|
103
|
+
# group_page_actions_cancel_link: 'ez-settings-group-actions-cancel-link'
|
104
|
+
# }
|
105
|
+
#
|
106
|
+
# Highly recommend inspecting settings page DOM.
|
107
|
+
# You can find there a lot of interesting id/class stuff
|
108
|
+
#
|
109
|
+
# You even can define dynamic map for allows to decide which CSS class could be added
|
110
|
+
# `if` must contain callable object that receives controller as a first argument and dynamic element as second one:
|
111
|
+
#
|
112
|
+
# In this example, you easily could add 'active' CSS class if route end with some fragment:
|
113
|
+
# config.dynamic_css_map = {
|
114
|
+
# nav_menu_item: {
|
115
|
+
# css_class: 'active',
|
116
|
+
# if: ->(controller, path_fragment) { controller.request.path.end_with?(path_fragment.to_s) }
|
117
|
+
# }
|
118
|
+
# }
|
119
|
+
end
|
120
|
+
|
121
|
+
# EzSettings uses Ez::Registry from ez-core lib for storing all knowledges in one place.
|
122
|
+
# This place is registry records for :settings_interfaces registry
|
123
|
+
#
|
124
|
+
# Register `app` variable as settings interface
|
125
|
+
Ez::Registry.in(:settings_interfaces, by: PivorakWebApp) do |registry|
|
126
|
+
registry.add app
|
127
|
+
end
|
128
|
+
```
|
129
|
+
### Routes
|
130
|
+
`config/routes.rb`
|
131
|
+
```ruby
|
132
|
+
Rails.application.routes.draw do
|
133
|
+
# your routes code before
|
134
|
+
|
135
|
+
# We recommend to hide settings into admin area
|
136
|
+
authenticate :user, ->(u) { u.admin? } do
|
137
|
+
namespace :admin do
|
138
|
+
# :app just interface name as you registred it in Ez::Registry
|
139
|
+
ez_settings_for :app
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# more your routes after
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
This routes setup allows you to have routes like:
|
148
|
+
|
149
|
+
`rake routes | grep settings`
|
150
|
+
```
|
151
|
+
admin_ez_settings /admin/settings Ez::Settings::Engine {:interface=>:app}
|
152
|
+
|
153
|
+
root GET / ez/settings/settings#index
|
154
|
+
GET /:group(.:format) ez/settings/settings#show
|
155
|
+
PUT /:group(.:format) ez/settings/settings#update
|
156
|
+
```
|
157
|
+
|
158
|
+
In case of example above you could route:
|
159
|
+
```
|
160
|
+
GET /admin/settings/ - overview page for all :app interface settings
|
161
|
+
GET/PUT: /admin/settings/general - general group settings
|
162
|
+
GET/PUT: /admin/settings/admin - admin group settings
|
163
|
+
GET/PUT: /admin/settings/showcase - showcase group settings
|
164
|
+
```
|
165
|
+
|
166
|
+
### Settings accessors
|
167
|
+
In your app you could access to settings values through:
|
168
|
+
```ruby
|
169
|
+
Ez::Settings[:all, :general, :app_title]
|
170
|
+
Ez::Settings[:all, :admin, :app_title]
|
171
|
+
Ez::Settings[:all, :showcase, :select]
|
172
|
+
```
|
173
|
+
Just use template: `Ez::Settings['interface', 'group', 'key']`
|
174
|
+
|
175
|
+
In the case of missing interface/group/key you will receive one of exceptions:
|
176
|
+
```
|
177
|
+
NotRegistredInterfaceError
|
178
|
+
NotRegistredGroupError
|
179
|
+
NotRegistredKeyError
|
180
|
+
```
|
181
|
+
Be careful ;)
|
182
|
+
|
183
|
+
### I18n
|
184
|
+
|
185
|
+
By default, all interfaces/groups/keys name would be humanized, but in fact, it tries to get translations from YAML first.
|
186
|
+
|
187
|
+
If you need, create locale file with this structure:
|
188
|
+
|
189
|
+
`config/locales/ez-settings.en.yml`
|
190
|
+
```yaml
|
191
|
+
en:
|
192
|
+
ez_settings:
|
193
|
+
label: Ez Settings
|
194
|
+
interfaces:
|
195
|
+
app:
|
196
|
+
label: App Settings
|
197
|
+
actions:
|
198
|
+
save:
|
199
|
+
label: Save Settings
|
200
|
+
cancel:
|
201
|
+
label: Cancel Settings
|
202
|
+
groups:
|
203
|
+
general:
|
204
|
+
label: General
|
205
|
+
admin:
|
206
|
+
label: Admin
|
207
|
+
showcase:
|
208
|
+
label: Showcase
|
209
|
+
keys:
|
210
|
+
string:
|
211
|
+
label: String
|
212
|
+
bool:
|
213
|
+
label: Bool
|
214
|
+
integer:
|
215
|
+
label: Integer
|
216
|
+
select:
|
217
|
+
label: Select
|
218
|
+
not_validate:
|
219
|
+
label: Not Validate
|
220
|
+
not_for_ui:
|
221
|
+
label: Not For UI
|
222
|
+
```
|
223
|
+
|
224
|
+
## TODO
|
225
|
+
This features will be implemented in upcoming 0.2 and 0.3 releases:
|
226
|
+
- `rails g ez:settings:install` it creates `config/ez_settings.rb` and `config/locales/ez-settings.en.yml`
|
227
|
+
- Scoped settings (`:scope_id`, `:scope_type`)
|
228
|
+
- groups as defined methods for interface
|
229
|
+
- controller before actions as configured callbacks
|
230
|
+
- JSON API endpoints
|
231
|
+
- Allow to config endpoints
|
232
|
+
- Interface description (and show at UI)
|
233
|
+
- Groups description (and show at UI)
|
234
|
+
- Database storage as backend
|
235
|
+
- Redis storage as backend
|
236
|
+
|
237
|
+
## Contributing
|
238
|
+
Fork => Fix => MR warmly welcomed!
|
239
|
+
|
240
|
+
## License
|
241
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Ez::Settings'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require "rspec/core/rake_task"
|
25
|
+
|
26
|
+
RSpec::Core::RakeTask.new(:spec)
|
27
|
+
|
28
|
+
task :default => :spec
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
class BaseCell < Cell::ViewModel
|
3
|
+
include RequestDispatcher
|
4
|
+
|
5
|
+
self.view_paths = ["#{Ez::Settings::Engine.root}/app/cells"]
|
6
|
+
|
7
|
+
delegate :t, to: I18n
|
8
|
+
delegate :params, :request, to: :controller
|
9
|
+
delegate :dynamic_css_map, to: :'interface.config'
|
10
|
+
|
11
|
+
SCOPE = 'ez_settings'
|
12
|
+
LABEL = 'label'
|
13
|
+
INTERFACES = 'interfaces'
|
14
|
+
GROUPS = 'groups'
|
15
|
+
KEYS = 'keys'
|
16
|
+
ACTIONS = 'actions'
|
17
|
+
SAVE = 'save'
|
18
|
+
CANCEL = 'cancel'
|
19
|
+
|
20
|
+
def self.form
|
21
|
+
include ActionView::Helpers::FormHelper
|
22
|
+
include SimpleForm::ActionViewExtensions::FormHelper
|
23
|
+
include ActionView::RecordIdentifier
|
24
|
+
include ActionView::Helpers::FormOptionsHelper
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.option(name, default: nil)
|
28
|
+
define_method name do
|
29
|
+
options[name]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def css_for(item, dynamic: nil)
|
34
|
+
return "ez-settings-defined-#{item}" unless css_map[item]
|
35
|
+
return css_map[item] unless dynamic
|
36
|
+
|
37
|
+
if dynamic_css_map.dig(item, :if)&.call(controller, dynamic)
|
38
|
+
dynamic_css_map.dig(item, :css_class) + ' ' + css_map[item]
|
39
|
+
else
|
40
|
+
css_map[item]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def css_map
|
45
|
+
{
|
46
|
+
nav_label: 'ez-settings-nav-label',
|
47
|
+
nav_menu: 'ez-settings-nav-menu',
|
48
|
+
nav_menu_item: 'ez-settings-nav-menu-item',
|
49
|
+
overview_page_wrapper: 'ez-settings-overview',
|
50
|
+
overview_page_section: 'ez-settings-overview-section',
|
51
|
+
overview_page_section_header: 'ez-settings-overview-section-header',
|
52
|
+
overview_page_section_content: 'ez-settings-overview-section-content',
|
53
|
+
overview_page_section_content_key: 'ez-settings-overview-section-content-key',
|
54
|
+
overview_page_section_content_value: 'ez-settings-overview-section-content-value',
|
55
|
+
group_page_wrapper: 'ez-settings-group-wrapper',
|
56
|
+
group_page_inner_wrapper: 'ez-settings-group-inner-wrapper',
|
57
|
+
group_page_header: 'ez-settings-group-header',
|
58
|
+
group_page_form_wrapper: 'ez-settings-group-form-wrapper',
|
59
|
+
group_page_form_inner: 'ez-settings-group-form-inner',
|
60
|
+
group_page_form_field_row: 'ez-settings-group-form-field-row',
|
61
|
+
group_page_form_string_wrapper: 'ez-settings-group-form-string-wrapper',
|
62
|
+
group_page_form_boolean_wrapper: 'ez-settings-group-form-boolean-wrapper',
|
63
|
+
group_page_form_select_wrapper: 'ez-settings-group-form-select-wrapper',
|
64
|
+
group_page_actions_wrapper: 'ez-settings-group-actions-wrapper',
|
65
|
+
group_page_actions_wrapper: 'ez-settings-group-actions-wrapper',
|
66
|
+
group_page_actions_save_button: 'ez-settings-group-actions-save-btn',
|
67
|
+
group_page_actions_cancel_link: 'ez-settings-group-actions-cancel-link',
|
68
|
+
}.merge(interface.config.custom_css_map)
|
69
|
+
end
|
70
|
+
|
71
|
+
def controller
|
72
|
+
context[:controller]
|
73
|
+
end
|
74
|
+
|
75
|
+
def group_link(group, options = {})
|
76
|
+
link_to i18n_group_label(group),
|
77
|
+
group_path(group),
|
78
|
+
class: css_for(:nav_menu_item, dynamic: "settings/#{group.name}")
|
79
|
+
end
|
80
|
+
|
81
|
+
def group_path(group)
|
82
|
+
"#{interface.config.default_path}/#{group.name}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def i18n_group_label(group)
|
86
|
+
t(LABEL, scope: [SCOPE, INTERFACES, group.interface, GROUPS, group.name],
|
87
|
+
default: group.name.to_s.humanize)
|
88
|
+
end
|
89
|
+
|
90
|
+
def i18n_key_label(key)
|
91
|
+
t(LABEL, scope: [SCOPE, INTERFACES, key.interface, GROUPS, key.group, KEYS, key.name],
|
92
|
+
default: key.name.to_s.humanize)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#ez-settings
|
2
|
+
= cell 'ez/settings/nav'
|
3
|
+
|
4
|
+
div class="#{css_for :group_page_wrapper} ez-settings-group-#{group.name}"
|
5
|
+
div class=(css_for :group_page_inner_wrapper)
|
6
|
+
div class=(css_for :group_page_header)
|
7
|
+
= i18n_group_label(group)
|
8
|
+
|
9
|
+
div class=(css_for :group_page_form_wrapper)
|
10
|
+
= simple_form_for store, as: :settings, url: form_url, method: :put do |f|
|
11
|
+
div class=(css_for :group_page_form_inner)
|
12
|
+
- ui_keys.each do |key|
|
13
|
+
= cell 'ez/settings/key', key, form: f
|
14
|
+
|
15
|
+
div class=(css_for :group_page_actions_wrapper)
|
16
|
+
= save_button(f)
|
17
|
+
= cancel_link
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
class GroupCell < BaseCell
|
3
|
+
form
|
4
|
+
|
5
|
+
property :ui_keys
|
6
|
+
option :store
|
7
|
+
|
8
|
+
def form_url
|
9
|
+
"#{interface.config.default_path}/#{model.name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def save_button(form)
|
13
|
+
form.button :submit,
|
14
|
+
t(LABEL, scope: [SCOPE, INTERFACES, model.interface, ACTIONS, SAVE],
|
15
|
+
default: 'Save'),
|
16
|
+
class: css_for(:group_page_actions_save_button)
|
17
|
+
end
|
18
|
+
|
19
|
+
def cancel_link
|
20
|
+
link_to t(LABEL, scope: [SCOPE, INTERFACES, model.interface, ACTIONS,CANCEL],
|
21
|
+
default: 'Cancel'),
|
22
|
+
interface.config.default_path,
|
23
|
+
class: css_for(:group_page_actions_cancel_link)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#ez-settings
|
2
|
+
= cell 'ez/settings/nav'
|
3
|
+
|
4
|
+
div class="#{css_for :overview_page_wrapper}"
|
5
|
+
- interface.groups.each do |group|
|
6
|
+
|
7
|
+
div class="#{css_for :overview_page_section}"
|
8
|
+
div class="#{css_for :overview_page_section_header}"
|
9
|
+
= group_link(group)
|
10
|
+
|
11
|
+
- group.ui_keys.each do |key|
|
12
|
+
div class="#{css_for :overview_page_section_content}"
|
13
|
+
|
14
|
+
div class="#{css_for :overview_page_section_content_key}"
|
15
|
+
= i18n_key_label(key)
|
16
|
+
|
17
|
+
div class="#{css_for :overview_page_section_content_value}"
|
18
|
+
= group.store(interface.config.backend).send(key.name)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
class KeyCell < BaseCell
|
3
|
+
form
|
4
|
+
|
5
|
+
option :form
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def html_options
|
10
|
+
{
|
11
|
+
label: i18n_key_label(model),
|
12
|
+
as: model.type,
|
13
|
+
collection: model.collection,
|
14
|
+
include_blank: model.default.present?,
|
15
|
+
required: model.required?,
|
16
|
+
checked_value: TRUE.to_s,
|
17
|
+
unchecked_value: FALSE.to_s
|
18
|
+
}.merge(model.options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
class NavCell < BaseCell
|
3
|
+
def nav_label
|
4
|
+
t(LABEL, scope: SCOPE, default: 'Settings')
|
5
|
+
end
|
6
|
+
|
7
|
+
def settings_link
|
8
|
+
link_to nav_label,
|
9
|
+
interface.config.default_path,
|
10
|
+
class: css_for(:nav_menu_item, dynamic: 'settings/')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ez
|
2
|
+
module Settings
|
3
|
+
class ApplicationController < Ez::Settings.config.base_controller.constantize
|
4
|
+
protect_from_forgery with: :exception
|
5
|
+
|
6
|
+
def view(cell_name, *args)
|
7
|
+
render html: cell("ez/settings/#{cell_name}", *args), layout: true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Ez
|
2
|
+
module Settings
|
3
|
+
class SettingsController < Ez::Settings::ApplicationController
|
4
|
+
include Ez::Settings::RequestDispatcher
|
5
|
+
|
6
|
+
def index
|
7
|
+
view :index
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
render_group(group, group.store(backend))
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
store = group.store(backend).update(params[:settings])
|
16
|
+
|
17
|
+
if store.valid?
|
18
|
+
redirect_to interface.config.default_path
|
19
|
+
else
|
20
|
+
render_group(group, store)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def render_group(group, store)
|
27
|
+
view :group, group, store: store
|
28
|
+
end
|
29
|
+
|
30
|
+
def backend
|
31
|
+
interface.config.backend
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/config/routes.rb
ADDED
data/lib/ez/settings.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
NotRegistredInterfaceError = Class.new(StandardError)
|
3
|
+
NotRegistredGroupError = Class.new(StandardError)
|
4
|
+
NotRegistredKeyError = Class.new(StandardError)
|
5
|
+
|
6
|
+
module Accessors
|
7
|
+
def [](interface_name, group_name, key_name)
|
8
|
+
interface = Ez::Registry.data(:settings_interfaces).find do |interface|
|
9
|
+
interface.name == interface_name.to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
unless interface
|
13
|
+
raise NotRegistredInterfaceError, "Interface #{interface_name} is not registred!"
|
14
|
+
end
|
15
|
+
|
16
|
+
group = interface.groups.find { |g| g.name == group_name.to_sym }
|
17
|
+
|
18
|
+
unless group
|
19
|
+
raise NotRegistredGroupError, "Group #{group_name} is not registred for #{interface_name} interface"
|
20
|
+
end
|
21
|
+
|
22
|
+
store = Ez::Settings::Store.new(group, interface.config.backend)
|
23
|
+
|
24
|
+
begin
|
25
|
+
store.send(key_name.to_sym)
|
26
|
+
rescue NoMethodError
|
27
|
+
raise NotRegistredKeyError, "Key #{key_name} is not registred for #{interface_name} interface, #{group_name} group"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
|
4
|
+
module Ez::Settings
|
5
|
+
module Backend
|
6
|
+
class FileSystem
|
7
|
+
attr_reader :file
|
8
|
+
|
9
|
+
def initialize(file)
|
10
|
+
@file = file
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
return {} unless File.exist?(file)
|
15
|
+
|
16
|
+
YAML.load_file(file).deep_symbolize_keys
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(data)
|
20
|
+
File.write(file, read.merge(data).deep_stringify_keys.to_yaml)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative 'interface/group'
|
2
|
+
require_relative 'interface/key'
|
3
|
+
require_relative 'store'
|
4
|
+
|
5
|
+
require 'ez/configurator'
|
6
|
+
require 'ez/settings/backend/file_system'
|
7
|
+
|
8
|
+
module Ez::Settings
|
9
|
+
class Interface
|
10
|
+
include Ez::Configurator
|
11
|
+
|
12
|
+
configure do |config|
|
13
|
+
config.base_controller = 'ApplicationController'
|
14
|
+
config.default_path = '/settings'
|
15
|
+
config.backend = Backend::FileSystem.new('settings.yml')
|
16
|
+
config.custom_css_map = {}
|
17
|
+
config.dynamic_css_map = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.define(name, &block)
|
21
|
+
interface = new(name)
|
22
|
+
interface.instance_eval(&block)
|
23
|
+
interface
|
24
|
+
end
|
25
|
+
|
26
|
+
delegate :config, :configure, to: :class
|
27
|
+
|
28
|
+
attr_reader :name, :groups, :store
|
29
|
+
|
30
|
+
def initialize(name)
|
31
|
+
@name = name
|
32
|
+
@keys, @groups = [], []
|
33
|
+
end
|
34
|
+
|
35
|
+
def define(&block)
|
36
|
+
self.instance_eval(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def group(name, &block)
|
40
|
+
find_or_initialize_group(name, &block)
|
41
|
+
end
|
42
|
+
|
43
|
+
def keys
|
44
|
+
groups.map(&:keys).flatten
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def find_or_initialize_group(name, &block)
|
50
|
+
existing_group = groups.find { |g| g.name == name }
|
51
|
+
|
52
|
+
if existing_group
|
53
|
+
existing_group.instance_eval(&block)
|
54
|
+
else
|
55
|
+
add_group(Group.new(name, self.name, &block))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_group(group)
|
60
|
+
@groups << group
|
61
|
+
|
62
|
+
group
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative 'key'
|
2
|
+
require_relative '../store'
|
3
|
+
|
4
|
+
module Ez::Settings
|
5
|
+
class Interface
|
6
|
+
class Group
|
7
|
+
OverwriteKeyError = Class.new(StandardError)
|
8
|
+
|
9
|
+
attr_reader :name, :options, :keys, :store, :interface
|
10
|
+
|
11
|
+
def initialize(name, interface, options = {}, &block)
|
12
|
+
@name = name
|
13
|
+
@interface = interface
|
14
|
+
@options = options
|
15
|
+
@keys = []
|
16
|
+
|
17
|
+
instance_eval(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def key(key_name, params = {})
|
21
|
+
prevent_key_rewrite!(key_name)
|
22
|
+
|
23
|
+
keys << Interface::Key.new(key_name, params.merge(group: name, interface: interface))
|
24
|
+
keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def ui_keys
|
28
|
+
keys.select(&:ui?)
|
29
|
+
end
|
30
|
+
|
31
|
+
def store(backend)
|
32
|
+
Ez::Settings::Store.new(self, backend)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def prevent_key_rewrite!(key_name)
|
38
|
+
return unless keys.map(&:name).include?(key_name)
|
39
|
+
|
40
|
+
raise OverwriteKeyError, "Key #{key_name} already registred in #{name} group"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ez::Settings
|
2
|
+
class Interface
|
3
|
+
class Key
|
4
|
+
attr_reader :name, :group, :interface, :type, :default,
|
5
|
+
:ui, :required, :collection, :options
|
6
|
+
|
7
|
+
def initialize(name, params)
|
8
|
+
@name = name
|
9
|
+
@group = params.fetch(:group)
|
10
|
+
@interface = params.fetch(:interface)
|
11
|
+
@type = params.fetch(:type, :string)
|
12
|
+
@default = params.fetch(:default, -> {}).call
|
13
|
+
@ui = params.fetch(:ui, true)
|
14
|
+
@required = params.fetch(:required, true)
|
15
|
+
@collection = params.fetch(:collection, [])
|
16
|
+
@options = params.fetch(:options, {})
|
17
|
+
end
|
18
|
+
|
19
|
+
# Alias all boolean-like options to predicates methods, please
|
20
|
+
alias_method :ui?, :ui
|
21
|
+
alias_method :required?, :required
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Ez
|
2
|
+
module Settings
|
3
|
+
module RequestDispatcher
|
4
|
+
# should implement :params
|
5
|
+
|
6
|
+
def interface
|
7
|
+
# TODO: add raise exception in nil
|
8
|
+
Ez::Registry.data(:settings_interfaces).find do |interface|
|
9
|
+
interface.name == params[:interface].to_sym
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def group
|
14
|
+
# TODO: add raise exception if nil
|
15
|
+
interface.groups.find { |g| g.name == params[:group].to_sym }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
require 'ez/settings/config'
|
4
|
+
|
5
|
+
module Ez::Settings
|
6
|
+
class Store
|
7
|
+
delegate :keys, to: :group
|
8
|
+
|
9
|
+
attr_reader :group, :errors, :backend
|
10
|
+
|
11
|
+
def initialize(group, backend)
|
12
|
+
@group = group
|
13
|
+
@errors = ActiveModel::Errors.new(self)
|
14
|
+
@backend = backend
|
15
|
+
|
16
|
+
define_accessors
|
17
|
+
|
18
|
+
keys.each { |key| default_or_exists_value(data, key) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate
|
22
|
+
@errors = ActiveModel::Errors.new(self)
|
23
|
+
|
24
|
+
group.keys.select(&:required?).each do |key|
|
25
|
+
errors.add(key.name, "can't be blank") if self.send(key.name).blank?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
errors.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def invalid?
|
34
|
+
!valid?
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(params)
|
38
|
+
params.each { |key, value| self.public_send("#{key}=", value) }
|
39
|
+
|
40
|
+
validate
|
41
|
+
return self unless errors.empty?
|
42
|
+
|
43
|
+
backend.write(schema)
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def schema
|
49
|
+
{
|
50
|
+
group.name => group.keys.map(&:name).each_with_object({}) do |key_name, schema|
|
51
|
+
schema[key_name] = send(key_name)
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def default_or_exists_value(from_data, key)
|
59
|
+
value = from_data[key.name].nil? ? key.default : from_data[key.name]
|
60
|
+
|
61
|
+
public_send("#{key.name}=", value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def data
|
65
|
+
@data ||= backend.read[group.name] || {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def define_accessors
|
69
|
+
group.keys.map(&:name).each do |name|
|
70
|
+
define_singleton_method(name) do
|
71
|
+
instance_variable_get("@#{name}")
|
72
|
+
end
|
73
|
+
|
74
|
+
define_singleton_method("#{name}=") do |value|
|
75
|
+
instance_variable_set("@#{name}", value)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# TODO @VS [0.2]
|
metadata
ADDED
@@ -0,0 +1,259 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ez-settings
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Volodya Sveredyuk
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ez-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: cells-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.8
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.8
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: cells-slim
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.5
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.0.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simple_form
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.5.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.5.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-rails
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: capybara
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: launchy
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: faker
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: guard-rspec
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: Easy settings engine for Rails app.
|
196
|
+
email:
|
197
|
+
- sveredyuk@gmail.com
|
198
|
+
executables: []
|
199
|
+
extensions: []
|
200
|
+
extra_rdoc_files: []
|
201
|
+
files:
|
202
|
+
- MIT-LICENSE
|
203
|
+
- README.md
|
204
|
+
- Rakefile
|
205
|
+
- app/assets/config/ez_settings_manifest.js
|
206
|
+
- app/assets/javascripts/ez/settings/application.js
|
207
|
+
- app/assets/stylesheets/ez/settings/application.css
|
208
|
+
- app/cells/ez/settings/base_cell.rb
|
209
|
+
- app/cells/ez/settings/group/show.slim
|
210
|
+
- app/cells/ez/settings/group_cell.rb
|
211
|
+
- app/cells/ez/settings/index/show.slim
|
212
|
+
- app/cells/ez/settings/index_cell.rb
|
213
|
+
- app/cells/ez/settings/key/show.slim
|
214
|
+
- app/cells/ez/settings/key_cell.rb
|
215
|
+
- app/cells/ez/settings/nav/show.slim
|
216
|
+
- app/cells/ez/settings/nav_cell.rb
|
217
|
+
- app/controllers/ez/settings/application_controller.rb
|
218
|
+
- app/controllers/ez/settings/settings_controller.rb
|
219
|
+
- app/helpers/ez/settings/application_helper.rb
|
220
|
+
- app/models/ez/settings/application_record.rb
|
221
|
+
- config/routes.rb
|
222
|
+
- lib/ez/settings.rb
|
223
|
+
- lib/ez/settings/accessors.rb
|
224
|
+
- lib/ez/settings/backend/file_system.rb
|
225
|
+
- lib/ez/settings/config.rb
|
226
|
+
- lib/ez/settings/engine.rb
|
227
|
+
- lib/ez/settings/interface.rb
|
228
|
+
- lib/ez/settings/interface/group.rb
|
229
|
+
- lib/ez/settings/interface/key.rb
|
230
|
+
- lib/ez/settings/request_dispatcher.rb
|
231
|
+
- lib/ez/settings/routes.rb
|
232
|
+
- lib/ez/settings/store.rb
|
233
|
+
- lib/ez/settings/version.rb
|
234
|
+
- lib/generators/ez/settings/install_generator.rb
|
235
|
+
homepage: https://github.com/ez-engines
|
236
|
+
licenses:
|
237
|
+
- MIT
|
238
|
+
metadata: {}
|
239
|
+
post_install_message:
|
240
|
+
rdoc_options: []
|
241
|
+
require_paths:
|
242
|
+
- lib
|
243
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
244
|
+
requirements:
|
245
|
+
- - ">="
|
246
|
+
- !ruby/object:Gem::Version
|
247
|
+
version: '0'
|
248
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
249
|
+
requirements:
|
250
|
+
- - ">="
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: '0'
|
253
|
+
requirements: []
|
254
|
+
rubyforge_project:
|
255
|
+
rubygems_version: 2.5.1
|
256
|
+
signing_key:
|
257
|
+
specification_version: 4
|
258
|
+
summary: Easy settings engine for Rails app.
|
259
|
+
test_files: []
|