web47core 0.0.7 → 0.0.8
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +44 -1
- data/lib/app/models/concerns/core_system_configuration.rb +23 -3
- data/lib/app/models/concerns/formable.rb +111 -0
- data/lib/app/models/concerns/standard_model.rb +22 -1
- data/lib/web47core.rb +1 -0
- data/test/models/concerns/formable_test.rb +74 -0
- data/web47core.gemspec +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e82f9597abea49e585537bf7b37dd78220136b34e2f2bc0ade5592e4d70ae9d
|
4
|
+
data.tar.gz: 523f737ac0beae20e3203ba4188c66e4cf5c09b8749084bf67dfd07fb039a3e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4a973a0840c34dc033b5f512e9e5bb62618afa44f20fc5b9e6993a59ef0cbde59befc204becd175dd15db7f02f4952f516af9d77dfb9cbb8fd70fd17991fc32
|
7
|
+
data.tar.gz: 6b2dff4fb23a286a60a0cccc2cd618d17b38379148aad5d385463df8a81ce55542ec9cde451516a52c6dfaf68204f585682849d546c6989800c4006fac95c091
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -37,4 +37,47 @@ bundle exec rake test
|
|
37
37
|
# Deployment
|
38
38
|
The `web47core` project is a gem that will be deployed via [Ruby Gems](https://rubygems.org). When an update is ready, the following steps should be followed
|
39
39
|
|
40
|
-
1. Build the gem `gem build`
|
40
|
+
1. Build the gem `gem build web47core.gemspec`
|
41
|
+
1. Push the new gem to [Ruby Gems](https://rubygems.org) `gem push web47core-<<version>>.gem`
|
42
|
+
1. There may be a delay when using the gem file
|
43
|
+
|
44
|
+
# Usage
|
45
|
+
## Importing the gem
|
46
|
+
To use the `app47core` gem in a project, first add the gem to your Gemfile in one of two ways
|
47
|
+
|
48
|
+
Using the gem from [Ruby Gems](https://rubygems.org)
|
49
|
+
```
|
50
|
+
gem 'web47core'
|
51
|
+
```
|
52
|
+
|
53
|
+
If you need the gem immediately or need to pull from development branch, you can use the git repo
|
54
|
+
```
|
55
|
+
gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :master
|
56
|
+
```
|
57
|
+
or from the develop branch
|
58
|
+
```
|
59
|
+
gem 'web47core', git: 'git@github.com:App47/web47core.git', branch: :develop
|
60
|
+
```
|
61
|
+
|
62
|
+
_Please do not ship to production code using the git repo, as the production servers will not have keys to pull from the web47core repo_
|
63
|
+
|
64
|
+
## Features
|
65
|
+
|
66
|
+
### Models
|
67
|
+
#### Concerns
|
68
|
+
1. `StandardModel` - Includes the common set of includes, Mongoid, Auditable, AutoClearCache, etc.
|
69
|
+
1. `CdnUrl` - Provide CDN URLs of your classes URLs when cdn_url is configured in system configuration
|
70
|
+
1. `AutoClearCache` - Clears your objects cache out of Rails.cache using the object's id
|
71
|
+
#### System Configuration
|
72
|
+
Define a `SystemConfiguration` class in your project and import the core concern.
|
73
|
+
|
74
|
+
```
|
75
|
+
class SystemConfiguration
|
76
|
+
include StandardModel
|
77
|
+
include CoreSystemConfiguration
|
78
|
+
|
79
|
+
# Include your additional system configuration fields and methods
|
80
|
+
field :google_sso_client_id, type: String
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
@@ -64,6 +64,9 @@ module CoreSystemConfiguration
|
|
64
64
|
# Validations
|
65
65
|
#
|
66
66
|
validates :environment, presence: true, uniqueness: true
|
67
|
+
validates :slack_support_channel, presence: true
|
68
|
+
validates :slack_sales_channel, presence: true
|
69
|
+
validates :default_time_zone, presence: true
|
67
70
|
end
|
68
71
|
base.extend ClassMethods
|
69
72
|
end
|
@@ -116,12 +119,17 @@ module CoreSystemConfiguration
|
|
116
119
|
end
|
117
120
|
# rubocop:enable Style/MethodMissingSuper
|
118
121
|
end
|
122
|
+
|
119
123
|
#
|
120
124
|
# Make sure the password doesn't get blanked out on an update
|
121
125
|
#
|
122
|
-
def
|
123
|
-
%i[smtp_password
|
124
|
-
|
126
|
+
def secure_fields
|
127
|
+
super + %i[smtp_password
|
128
|
+
aws_access_secret
|
129
|
+
mailgun_api_key
|
130
|
+
switchboard_stack_api_token
|
131
|
+
twilio_auth_token
|
132
|
+
zendesk_token]
|
125
133
|
end
|
126
134
|
|
127
135
|
#
|
@@ -247,6 +255,18 @@ module CoreSystemConfiguration
|
|
247
255
|
[twilio_account_id.present?, twilio_auth_token.present?, twilio_phone_number.present?].all?
|
248
256
|
end
|
249
257
|
|
258
|
+
#
|
259
|
+
# Determine if Slack is configured
|
260
|
+
#
|
261
|
+
# Examples
|
262
|
+
#
|
263
|
+
# switchboard_configured?
|
264
|
+
# # => true || false
|
265
|
+
#
|
266
|
+
def slack_configured?
|
267
|
+
slack_api_url.present?
|
268
|
+
end
|
269
|
+
|
250
270
|
private
|
251
271
|
|
252
272
|
#
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# For models that are updated via forms, we need an easy and consistent way to
|
5
|
+
# return a list of allowed parameters for a given model. While doing Model.attribute_names
|
6
|
+
# is working for most forms, it DOES NOT deal with relationships at all.
|
7
|
+
#
|
8
|
+
# This mix is should be included in those models, and the model then calls
|
9
|
+
# Model.allowed_param_names to retrieve a complete (dynamic) list of
|
10
|
+
# * Attribute names
|
11
|
+
# * Many to many relationships (has_many_and_belongs_to)
|
12
|
+
# * One to many relationships (belongs to)
|
13
|
+
#
|
14
|
+
module Formable
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
#
|
17
|
+
# Include the class methods into the model
|
18
|
+
#
|
19
|
+
def self.included(base)
|
20
|
+
base.class_eval do
|
21
|
+
base.extend ClassMethods
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Public: Add to class methods
|
27
|
+
#
|
28
|
+
module ClassMethods
|
29
|
+
#
|
30
|
+
# Return the complete list of key names that would appear in the form.
|
31
|
+
#
|
32
|
+
def allowed_param_names(filter_names = [])
|
33
|
+
# Always filter out the mongoid reserved items
|
34
|
+
filter_names += %w[created_at updated_at _type _id]
|
35
|
+
associations = all_associations
|
36
|
+
# filter out the relationship names so we don't have dups
|
37
|
+
associations.each { |association| filter_names << association.keys.first }
|
38
|
+
(field_names + associations).delete_if { |name| filter_names.include?(name) }
|
39
|
+
rescue StandardError
|
40
|
+
attribute_names.delete_if { |name| filter_names.include?(name) }
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# allow the model to filter out a name if they want to, meaning the model
|
45
|
+
# can return a subset of attribute names
|
46
|
+
#
|
47
|
+
def field_names
|
48
|
+
attribute_names
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# gather up the collections we care about and return them. For now, the
|
53
|
+
# many to many associations are the ones that need some extra help.
|
54
|
+
#
|
55
|
+
def all_associations
|
56
|
+
many_to_many_associations
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Return a collection of many to many assocations. We basically
|
61
|
+
# need to turn the current value returned by attribute names
|
62
|
+
#
|
63
|
+
# relationship_ids
|
64
|
+
#
|
65
|
+
# to
|
66
|
+
#
|
67
|
+
# { relationship_ids => [] }
|
68
|
+
#
|
69
|
+
# Telling the permit command to accept the value as an array of items.
|
70
|
+
#
|
71
|
+
def many_to_many_associations
|
72
|
+
associations = []
|
73
|
+
reflect_on_all_associations.each do |association|
|
74
|
+
next unless association.macro == :has_and_belongs_to_many
|
75
|
+
|
76
|
+
associations << { association.key => [] }
|
77
|
+
end
|
78
|
+
associations
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Remove updates for secure fields that come across as blank to start with and get removed on update
|
84
|
+
#
|
85
|
+
def update(params)
|
86
|
+
super(remove_blank_secure_fields(params))
|
87
|
+
end
|
88
|
+
|
89
|
+
alias :update_attributes :update
|
90
|
+
|
91
|
+
#
|
92
|
+
# Remove updates for secure fields that come across as blank to start with and get removed on update
|
93
|
+
#
|
94
|
+
def update!(params)
|
95
|
+
super(remove_blank_secure_fields(params))
|
96
|
+
end
|
97
|
+
|
98
|
+
alias :update_attributes! :update!
|
99
|
+
|
100
|
+
#
|
101
|
+
# List of secure fields, to add fields in concrete class, simply override this method
|
102
|
+
#
|
103
|
+
def secure_fields
|
104
|
+
[]
|
105
|
+
end
|
106
|
+
|
107
|
+
def remove_blank_secure_fields(params)
|
108
|
+
secure_fields.each { |field| params.delete(field) if params[field].blank? }
|
109
|
+
params
|
110
|
+
end
|
111
|
+
end
|
@@ -13,8 +13,29 @@ module StandardModel
|
|
13
13
|
include Mongoid::Timestamps
|
14
14
|
# include App47Logger
|
15
15
|
# include Auditable
|
16
|
-
|
16
|
+
include Formable
|
17
17
|
include AutoClearCache
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Mixin to add methods to the classes themselves
|
23
|
+
# Used by calling model.method_name
|
24
|
+
#
|
25
|
+
module ClassMethods
|
26
|
+
# Used by calling 'model.without_callback(*.args, &block) do'
|
27
|
+
def without_callback(*args, &_block)
|
28
|
+
skip_callback(*args)
|
29
|
+
result = yield
|
30
|
+
set_callback(*args)
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Turn the array into a list of options
|
36
|
+
#
|
37
|
+
def make_options(options)
|
38
|
+
options.collect { |t| [t, t.humanize] }
|
39
|
+
end
|
40
|
+
end
|
20
41
|
end
|
data/lib/web47core.rb
CHANGED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# TODO: CMS add tests for clearing by account id as well as id
|
4
|
+
class FormableTest < ActiveSupport::TestCase
|
5
|
+
|
6
|
+
context 'allowed_params' do
|
7
|
+
should 'return test form fields' do
|
8
|
+
allowed = TestForm.allowed_param_names
|
9
|
+
assert_equal 2, allowed.count
|
10
|
+
assert allowed.include?('name'), allowed.inspect
|
11
|
+
assert allowed.include?('password'), allowed.inspect
|
12
|
+
end
|
13
|
+
should 'return test input fields' do
|
14
|
+
allowed = TestInput.allowed_param_names
|
15
|
+
assert_equal 2, allowed.count
|
16
|
+
assert allowed.include?('input_type'), allowed.inspect
|
17
|
+
assert allowed.include?('test_form_id'), allowed.inspect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context 'update the model safely' do
|
21
|
+
setup do
|
22
|
+
@model = TestForm.create! name: 'name', password: 'abc123'
|
23
|
+
end
|
24
|
+
should 'update password' do
|
25
|
+
assert @model.update name: 'foo', password: 'bar'
|
26
|
+
assert_equal 'foo', @model.name
|
27
|
+
assert_equal 'bar', @model.password
|
28
|
+
end
|
29
|
+
should 'update not blank password' do
|
30
|
+
assert @model.update name: 'foo', password: ''
|
31
|
+
assert_equal 'foo', @model.name
|
32
|
+
assert_equal 'abc123', @model.password
|
33
|
+
end
|
34
|
+
should 'update not nil password' do
|
35
|
+
assert @model.update name: 'foo', password: nil
|
36
|
+
assert_equal 'foo', @model.name
|
37
|
+
assert_equal 'abc123', @model.password
|
38
|
+
end
|
39
|
+
should 'update! not blank password' do
|
40
|
+
assert @model.update! name: 'foo', password: ''
|
41
|
+
assert_equal 'foo', @model.name
|
42
|
+
assert_equal 'abc123', @model.password
|
43
|
+
end
|
44
|
+
should 'update_attributes! not blank password' do
|
45
|
+
assert @model.update_attributes! name: 'foo', password: ''
|
46
|
+
assert_equal 'foo', @model.name
|
47
|
+
assert_equal 'abc123', @model.password
|
48
|
+
end
|
49
|
+
should 'update_attributes not blank password' do
|
50
|
+
assert @model.update_attributes name: 'foo', password: ''
|
51
|
+
assert_equal 'foo', @model.name
|
52
|
+
assert_equal 'abc123', @model.password
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TestForm
|
58
|
+
include Mongoid::Document
|
59
|
+
include Formable
|
60
|
+
field :name
|
61
|
+
field :password
|
62
|
+
has_many :test_inputs
|
63
|
+
|
64
|
+
def secure_fields
|
65
|
+
super + %i[password]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class TestInput
|
70
|
+
include Mongoid::Document
|
71
|
+
include Formable
|
72
|
+
field :input_type
|
73
|
+
belongs_to :test_form
|
74
|
+
end
|
data/web47core.gemspec
CHANGED
@@ -8,7 +8,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
8
8
|
Gem::Specification.new do |spec|
|
9
9
|
spec.required_ruby_version = '~> 2.4.1'
|
10
10
|
spec.name = 'web47core'
|
11
|
-
spec.version = '0.0.
|
11
|
+
spec.version = '0.0.8'
|
12
12
|
spec.authors = ['Chris Schroeder']
|
13
13
|
spec.email = ['chris@app47.com']
|
14
14
|
spec.summary = 'App47 Web Core Library.'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web47core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Schroeder
|
@@ -402,11 +402,13 @@ files:
|
|
402
402
|
- lib/app/models/concerns/auto_clear_cache.rb
|
403
403
|
- lib/app/models/concerns/cdn_url.rb
|
404
404
|
- lib/app/models/concerns/core_system_configuration.rb
|
405
|
+
- lib/app/models/concerns/formable.rb
|
405
406
|
- lib/app/models/concerns/standard_model.rb
|
406
407
|
- lib/web47core.rb
|
407
408
|
- test/fixtures/mongoid.yml
|
408
409
|
- test/models/concerns/auto_clear_cache_test.rb
|
409
410
|
- test/models/concerns/cdn_url_test.rb
|
411
|
+
- test/models/concerns/formable_test.rb
|
410
412
|
- test/models/concerns/system_configuration_test.rb
|
411
413
|
- test/rails_setup.rb
|
412
414
|
- test/shoulda_macros/mongoid.rb
|
@@ -439,6 +441,7 @@ test_files:
|
|
439
441
|
- test/fixtures/mongoid.yml
|
440
442
|
- test/models/concerns/auto_clear_cache_test.rb
|
441
443
|
- test/models/concerns/cdn_url_test.rb
|
444
|
+
- test/models/concerns/formable_test.rb
|
442
445
|
- test/models/concerns/system_configuration_test.rb
|
443
446
|
- test/rails_setup.rb
|
444
447
|
- test/shoulda_macros/mongoid.rb
|