data_guru 0.3.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/.gitignore +9 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +133 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +7 -0
- data/data_guru.gemspec +29 -0
- data/lib/data_guru/client.rb +81 -0
- data/lib/data_guru/collection.rb +58 -0
- data/lib/data_guru/configuration.rb +10 -0
- data/lib/data_guru/model.rb +54 -0
- data/lib/data_guru/model_configuration.rb +32 -0
- data/lib/data_guru/validation.rb +51 -0
- data/lib/data_guru/validations/configuration.rb +37 -0
- data/lib/data_guru/validations/model_configuration.rb +139 -0
- data/lib/data_guru/version.rb +3 -0
- data/lib/data_guru.rb +31 -0
- metadata +179 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8c8667440f7886044b541e700f46712c984955f9
|
4
|
+
data.tar.gz: 744434dea8207c0c22e68762f7e47414ce2cd518
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c4d50f066499af43eb6aaba731c66b8c129462469248e9a33d25384bf189af9545f3f07f19a62f5da48d700fed8648b7090f9e097c2a6d0fbb1d799ded36f902
|
7
|
+
data.tar.gz: 984c11f90833f18b5ce17fae93e813a7613df62fbe6ac295fd4e9c8217dfd0ae057567a4060ee1ffa275d77df1ee2acacf6b6ed6bc142ff0a39969bd0827b2a7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# DataGuru
|
2
|
+
|
3
|
+
Manage configuration stored as JSON data in DataGuru-API server.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'data_guru'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install data_guru
|
20
|
+
|
21
|
+
## Configuration
|
22
|
+
|
23
|
+
Create config file in your app:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# app/config/initializers/data_guru.rb
|
27
|
+
DataGuru.configure do |config|
|
28
|
+
config.api_url = 'url of api server'
|
29
|
+
config.access_token = 'access token'
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Possible configuration values:
|
34
|
+
|
35
|
+
`api_url` - *[mandatory]* api server where data from Permissions is stored
|
36
|
+
|
37
|
+
`access_token` - *[mandatory]* token needed for verifying access to api server
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
If you use default config files (see Permissions section below) you can simply do:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
data = DataGuru::Client.new
|
45
|
+
|
46
|
+
# get collections
|
47
|
+
data.users.all
|
48
|
+
data.projects.all
|
49
|
+
data.github_teams.all
|
50
|
+
data.google_groups.all
|
51
|
+
data.rollbar_teams.all
|
52
|
+
data.toggl_teams.all
|
53
|
+
|
54
|
+
# find in collections by attribute
|
55
|
+
data.projects.find{ |project| project.display_name == 'Some project' }
|
56
|
+
data.users.find{ |user| user.github == 'example' }
|
57
|
+
|
58
|
+
# filter through collections by attributes
|
59
|
+
data.users.select{ |user| user.external }
|
60
|
+
data.users.select{ |user| user.public_key.nil? }.count
|
61
|
+
|
62
|
+
# select key names of all github teams user belongs to
|
63
|
+
user = data.users.first
|
64
|
+
data.github_teams.select{ |team| team.members.include?(user.id) }.map(&:id)
|
65
|
+
```
|
66
|
+
|
67
|
+
The collections have `Enumerable` module included so you can filter models by attributes easily (`data.users.select{ |user| user.some_method }`)
|
68
|
+
|
69
|
+
You can refresh repo and storage at any time, just do:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
data = DataGuru::Client.new
|
73
|
+
data.refresh
|
74
|
+
```
|
75
|
+
|
76
|
+
On a single model you can do:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
data = DataGuru::Client.new
|
80
|
+
user = data.users.all.first
|
81
|
+
|
82
|
+
# to get list of user attributes
|
83
|
+
user.attributes
|
84
|
+
|
85
|
+
# to get list of permitted and required attributes (see Permisions section below)
|
86
|
+
user.permitted_attributes
|
87
|
+
user.required_attributes
|
88
|
+
|
89
|
+
# check if user has all required attributes set
|
90
|
+
user.valid?
|
91
|
+
user.missing_attributes
|
92
|
+
```
|
93
|
+
|
94
|
+
Each model has a set of getter methods (permitted_attributes) so you can for example do `user.github` to get just the github username of the user.
|
95
|
+
Each model also has `id` method which returns the name of the file, for example for the user in a file `john.doe.yml` will return `john.doe`.
|
96
|
+
|
97
|
+
You can check whether configuration (in your rails app) and model configuration (in your permissions repo) is valid by running `DataGuru::Client.new.errors`.
|
98
|
+
|
99
|
+
### Permissions
|
100
|
+
|
101
|
+
A sample permissions repo contains a `config` directory with files like `user.yml`, `project.yml`, `github_team.yml`. In these files you specify attributes for each model with information about whether they are required, what is the default value and what type of value it is.
|
102
|
+
|
103
|
+
```
|
104
|
+
---
|
105
|
+
name:
|
106
|
+
required: true
|
107
|
+
default_value:
|
108
|
+
value_type: string
|
109
|
+
emails:
|
110
|
+
required: true
|
111
|
+
default_value:
|
112
|
+
value_type: array
|
113
|
+
external:
|
114
|
+
required: false
|
115
|
+
default_value: false
|
116
|
+
value_type: boolean
|
117
|
+
```
|
118
|
+
|
119
|
+
The methods `permitted_attributes` and `required_attributes` returns the array of specified attributes.
|
120
|
+
|
121
|
+
All the files should be under the appropriate directory, for example all users under `users` directory, they can be nested if you want.
|
122
|
+
|
123
|
+
For more information see the [permissions template repo](https://github.com/ardhena/permissions-template).
|
124
|
+
|
125
|
+
## Development
|
126
|
+
|
127
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
128
|
+
|
129
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
130
|
+
|
131
|
+
## Contributing
|
132
|
+
|
133
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/netguru/data_guru.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/data_guru.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "data_guru/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "data_guru"
|
8
|
+
spec.version = DataGuru::VERSION
|
9
|
+
spec.authors = ["Adam Nowak", "Katarzyna Jaskólska", "Jacek Adamek"]
|
10
|
+
spec.email = ["adam.nowak@netguru.co", "katarzyna.jaskolska@netguru.co", "jacek.adamek@netguru.co"]
|
11
|
+
|
12
|
+
spec.summary = "Wrapper for data stored in YAML files"
|
13
|
+
spec.homepage = "https://github.com/netguru/data_guru"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|features)/}) }
|
16
|
+
spec.bindir = "exe"
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency "activesupport"
|
21
|
+
spec.add_dependency "git"
|
22
|
+
spec.add_dependency "httparty"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "rubocop"
|
29
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class Client
|
3
|
+
require 'httparty'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
|
6
|
+
def method_missing(name)
|
7
|
+
create_model_class(name) if should_create_class?(name)
|
8
|
+
value = DataGuru::Collection.new(collection_name: name, model: model(name))
|
9
|
+
get_variable(name) || set_variable(name, value)
|
10
|
+
end
|
11
|
+
|
12
|
+
def refresh
|
13
|
+
HTTParty.get(refresh_data_url)
|
14
|
+
wipe_collections_cache
|
15
|
+
end
|
16
|
+
|
17
|
+
def errors
|
18
|
+
DataGuru::Validation.new.errors
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def should_create_class?(name)
|
24
|
+
name_exists?(name) && !class_exists?(class_name(name))
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_model_class(name)
|
28
|
+
DataGuru.const_set(class_name(name), Class.new { include Model })
|
29
|
+
end
|
30
|
+
|
31
|
+
def class_name(name)
|
32
|
+
name.to_s.camelize.singularize
|
33
|
+
end
|
34
|
+
|
35
|
+
def class_exists?(class_name)
|
36
|
+
eval("defined?(#{class_name}) && #{class_name}.is_a?(Class)")
|
37
|
+
end
|
38
|
+
|
39
|
+
def name_exists?(name)
|
40
|
+
collection_names.include?(name.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
def model(name)
|
44
|
+
"data_guru/#{name}".classify.constantize
|
45
|
+
rescue NameError
|
46
|
+
raise "Collection '#{name}' does not exist"
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_variable(name)
|
50
|
+
instance_variable_get("@#{name}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_variable(name, value)
|
54
|
+
instance_variable_set("@#{name}", value)
|
55
|
+
end
|
56
|
+
|
57
|
+
def wipe_collections_cache
|
58
|
+
collection_names.each { |name| instance_variable_set("@#{name}", nil) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def access_token
|
62
|
+
DataGuru.config.access_token
|
63
|
+
end
|
64
|
+
|
65
|
+
def api_url
|
66
|
+
DataGuru.config.api_url
|
67
|
+
end
|
68
|
+
|
69
|
+
def refresh_data_url
|
70
|
+
"#{api_url}/refresh?token=#{access_token}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def collection_names
|
74
|
+
HTTParty.get(collection_names_url)
|
75
|
+
end
|
76
|
+
|
77
|
+
def collection_names_url
|
78
|
+
"#{api_url}/?token=#{access_token}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class Collection
|
3
|
+
include Enumerable
|
4
|
+
require 'httparty'
|
5
|
+
|
6
|
+
attr_reader :collection_name, :model, :config
|
7
|
+
|
8
|
+
def initialize(collection_name:, model:, config: default_config(model))
|
9
|
+
@collection_name = collection_name
|
10
|
+
@model = model
|
11
|
+
@config = config
|
12
|
+
end
|
13
|
+
|
14
|
+
def all
|
15
|
+
@all ||= build_models(collection_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def each(&block)
|
19
|
+
all.each(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def default_config(model)
|
25
|
+
DataGuru::ModelConfiguration.new(model: model)
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_models(collection_type)
|
29
|
+
data(collection_type).map do |key, data|
|
30
|
+
model.new(key, data, config, config_data)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def access_token
|
35
|
+
DataGuru.config.access_token
|
36
|
+
end
|
37
|
+
|
38
|
+
def api_url
|
39
|
+
DataGuru.config.api_url
|
40
|
+
end
|
41
|
+
|
42
|
+
def collection_resource_url(collection_type)
|
43
|
+
"#{api_url}/#{collection_type}?token=#{access_token}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def config_resource_url
|
47
|
+
"#{api_url}/config?token=#{access_token}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def config_data
|
51
|
+
@config_data ||= HTTParty.get(config_resource_url)
|
52
|
+
end
|
53
|
+
|
54
|
+
def data(collection_type)
|
55
|
+
HTTParty.get(collection_resource_url(collection_type))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module DataGuru
|
2
|
+
module Model
|
3
|
+
attr_reader :permitted_attributes, :required_attributes, :id
|
4
|
+
|
5
|
+
def initialize(key, attrs, config, config_data)
|
6
|
+
@id = key
|
7
|
+
@permitted_attributes = config.permitted_attributes(config_data)
|
8
|
+
@required_attributes = config.required_attributes(config_data)
|
9
|
+
|
10
|
+
permitted_attributes.each do |attribute|
|
11
|
+
set_attr_getter(attribute)
|
12
|
+
default_value = config.attributes(config_data)[attribute.to_s]["default_value"]
|
13
|
+
set_attr_value(attribute, attrs[attribute.to_s], default_value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def attributes
|
18
|
+
@attributes ||= all_attributes
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
present_required_attributes == required_attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
def missing_attributes
|
26
|
+
required_attributes - present_required_attributes
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def set_attr_getter(attribute)
|
32
|
+
self.class.send(:define_method, attribute) do
|
33
|
+
instance_variable_get("@#{attribute}")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_attr_value(attribute, value, default_value)
|
38
|
+
value_to_set = value.nil? ? default_value : value
|
39
|
+
instance_variable_set("@#{attribute}", value_to_set)
|
40
|
+
end
|
41
|
+
|
42
|
+
def present_required_attributes
|
43
|
+
required_attributes.map do |name|
|
44
|
+
!attributes[name].nil? ? name : nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_attributes
|
49
|
+
attrs = permitted_attributes
|
50
|
+
.map{ |name| [name, public_send(name)] } << [:id, id]
|
51
|
+
Hash[attrs]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class ModelConfiguration
|
3
|
+
attr_reader :model, :model_name
|
4
|
+
|
5
|
+
def initialize(model:, model_name: default_model_name(model))
|
6
|
+
@model = model
|
7
|
+
@model_name = model_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def attributes(config_data)
|
11
|
+
config_data[model_name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def permitted_attributes(config_data)
|
15
|
+
attributes(config_data).map{ |k, _v| k.to_sym }
|
16
|
+
end
|
17
|
+
|
18
|
+
def required_attributes(config_data)
|
19
|
+
attributes(config_data).map{ |k, v| v["required"] ? k.to_sym : nil }.reject(&:nil?)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def default_model_name(model)
|
25
|
+
model.name.split('::').last
|
26
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
27
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
28
|
+
.tr("-", "_")
|
29
|
+
.downcase
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class Validation
|
3
|
+
require 'httparty'
|
4
|
+
attr_reader :config, :keys
|
5
|
+
|
6
|
+
TYPES = %w(configuration model_configuration)
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@config = config_data
|
10
|
+
@keys = keys
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
TYPES.flat_map{ |type| send("#{type}_errors") }
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def config_data
|
20
|
+
HTTParty.get(config_resource_url)
|
21
|
+
end
|
22
|
+
|
23
|
+
def config_resource_url
|
24
|
+
"#{api_url}/config?token=#{access_token}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def api_url
|
28
|
+
DataGuru.config.api_url
|
29
|
+
end
|
30
|
+
|
31
|
+
def access_token
|
32
|
+
DataGuru.config.access_token
|
33
|
+
end
|
34
|
+
|
35
|
+
def keys
|
36
|
+
HTTParty.get(keys_resource_url)
|
37
|
+
end
|
38
|
+
|
39
|
+
def keys_resource_url
|
40
|
+
"#{api_url}?token=#{access_token}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def configuration_errors
|
44
|
+
DataGuru::ConfigurationValidation.new.errors
|
45
|
+
end
|
46
|
+
|
47
|
+
def model_configuration_errors
|
48
|
+
DataGuru::ModelConfigurationValidation.new(config, keys).errors
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class ConfigurationValidation
|
3
|
+
VALIDATIONS = %w(api_url access_token)
|
4
|
+
|
5
|
+
def errors
|
6
|
+
return [] if valid?
|
7
|
+
build_errors
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def valid?
|
13
|
+
api_url_valid? && access_token_valid?
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_errors
|
17
|
+
VALIDATIONS.flat_map do |name|
|
18
|
+
send("#{name}_valid?") ? [] : send("#{name}_error")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
VALIDATIONS.each do |name|
|
23
|
+
# def api_url_valid?, access_token_valid?
|
24
|
+
define_method("#{name}_valid?") do
|
25
|
+
!DataGuru.config.public_send(name).nil?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def api_url_error
|
30
|
+
'Configuration: no api url'
|
31
|
+
end
|
32
|
+
|
33
|
+
def access_token_error
|
34
|
+
'Configuration: no access token'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module DataGuru
|
2
|
+
class ModelConfigurationValidation
|
3
|
+
attr_reader :config, :keys
|
4
|
+
|
5
|
+
VALIDATIONS = %w(config model_file model_attributes model_attribute_name
|
6
|
+
model_attribute_content)
|
7
|
+
RESERVED_WORDS = %w(id attributes permitted_attributes required_attributes
|
8
|
+
missing_attributes valid?)
|
9
|
+
ATTRIBUTE_TYPES = %w(required default_value value_type)
|
10
|
+
|
11
|
+
def initialize(config, keys)
|
12
|
+
@config = config
|
13
|
+
@keys = keys
|
14
|
+
end
|
15
|
+
|
16
|
+
def errors
|
17
|
+
return [] if valid?
|
18
|
+
build_errors
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def model_names
|
24
|
+
keys.map(&:singularize) - ['config']
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
config_valid? && model_file_valid? && model_attributes_valid? &&
|
29
|
+
model_attribute_name_valid? && model_attribute_content_valid?
|
30
|
+
end
|
31
|
+
|
32
|
+
def build_errors
|
33
|
+
VALIDATIONS.flat_map do |name|
|
34
|
+
send("#{name}_valid?") ? [] : send("#{name}_error")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def config_valid?
|
39
|
+
keys.include?('config')
|
40
|
+
end
|
41
|
+
|
42
|
+
def model_file_valid?
|
43
|
+
return false unless config_valid?
|
44
|
+
valid_files = model_names
|
45
|
+
.map{ |name| config.include?(name) }
|
46
|
+
.select{ |name| name }
|
47
|
+
valid_files.size == model_names.size
|
48
|
+
end
|
49
|
+
|
50
|
+
def model_attributes_valid?
|
51
|
+
return false unless model_file_valid?
|
52
|
+
valid_models = model_names
|
53
|
+
.map{ |name| config[name] == false || config[name].nil? }
|
54
|
+
.select{ |name| !name }
|
55
|
+
valid_models.size == model_names.size
|
56
|
+
end
|
57
|
+
|
58
|
+
def model_attribute_name_valid?
|
59
|
+
attributes = present_models.flat_map{ |model| config[model].keys }
|
60
|
+
diff = attributes - RESERVED_WORDS
|
61
|
+
attributes.count == diff.count
|
62
|
+
end
|
63
|
+
|
64
|
+
def model_attribute_content_valid?
|
65
|
+
attributes = present_models.map{ |model| config[model] }
|
66
|
+
invalid_attrs = attributes.flat_map{ |model|
|
67
|
+
model.values.map{ |attributes| attributes.keys.sort == ATTRIBUTE_TYPES.sort }
|
68
|
+
}.select{ |a| !a }
|
69
|
+
invalid_attrs.size == 0
|
70
|
+
end
|
71
|
+
|
72
|
+
def config_error
|
73
|
+
'Model Configuration: no config directory in repo'
|
74
|
+
end
|
75
|
+
|
76
|
+
def model_file_error
|
77
|
+
"Model Configuration: no config file for model - #{missing_models.join(', ')}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def model_attributes_error
|
81
|
+
"Model Configuration: no permitted attributes for model - #{missing_model_contents.join(', ')}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def model_attribute_name_error
|
85
|
+
reserved_model_attributes.map do |model, attrs|
|
86
|
+
"Model Configuration: reserved words used as attributes in model #{model} - #{attrs.join(', ')}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def model_attribute_content_error
|
91
|
+
missing_model_attributes.flat_map do |model, attrs|
|
92
|
+
attrs.map do |name, type|
|
93
|
+
attributes = "attribute #{name} missing #{type.join(', ')}"
|
94
|
+
"Model Configuration: missing attribute declaration in model #{model} - #{attributes}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def missing_models
|
100
|
+
return model_names unless config_valid?
|
101
|
+
model_names.flat_map{ |name| config.include?(name) ? [] : name }
|
102
|
+
end
|
103
|
+
|
104
|
+
def missing_model_contents
|
105
|
+
return model_names unless config_valid?
|
106
|
+
model_names.flat_map do |name|
|
107
|
+
if missing_models.include?(name)
|
108
|
+
name
|
109
|
+
else
|
110
|
+
config[name] == false || config[name].nil? ? name : []
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def present_models
|
116
|
+
model_names - missing_model_contents
|
117
|
+
end
|
118
|
+
|
119
|
+
def reserved_model_attributes
|
120
|
+
wrong_attributes = present_models.map do |model|
|
121
|
+
wrong_attrs = config[model].keys & RESERVED_WORDS
|
122
|
+
[ model, wrong_attrs ]
|
123
|
+
end
|
124
|
+
Hash[wrong_attributes]
|
125
|
+
end
|
126
|
+
|
127
|
+
def missing_model_attributes
|
128
|
+
all = Hash[present_models.map{ |model| [model, config[model]] }]
|
129
|
+
missing = all.map do |model, attributes|
|
130
|
+
attrs = Hash[ attributes.map{ |name, types| [name, ATTRIBUTE_TYPES - types.keys] } ]
|
131
|
+
without_empty = attrs
|
132
|
+
.map{ |name, types| types.empty? ? [] : [name, types] }
|
133
|
+
.reject{ |array| array.empty? }
|
134
|
+
[ model, Hash[without_empty] ]
|
135
|
+
end
|
136
|
+
Hash[missing.reject{ |k, v| v.empty? }]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/lib/data_guru.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "data_guru/version"
|
2
|
+
require "data_guru/configuration"
|
3
|
+
require "data_guru/model_configuration"
|
4
|
+
|
5
|
+
require "data_guru/validation"
|
6
|
+
require "data_guru/validations/configuration"
|
7
|
+
require "data_guru/validations/model_configuration"
|
8
|
+
|
9
|
+
require "data_guru/collection"
|
10
|
+
|
11
|
+
require "data_guru/model"
|
12
|
+
|
13
|
+
require "data_guru/client"
|
14
|
+
|
15
|
+
module DataGuru
|
16
|
+
class << self
|
17
|
+
attr_accessor :config
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.config
|
21
|
+
@config ||= Configuration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.configure
|
25
|
+
yield(config)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.reset
|
29
|
+
@config = Configuration.new
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: data_guru
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Adam Nowak
|
8
|
+
- Katarzyna Jaskólska
|
9
|
+
- Jacek Adamek
|
10
|
+
autorequire:
|
11
|
+
bindir: exe
|
12
|
+
cert_chain: []
|
13
|
+
date: 2015-10-19 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: git
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '0'
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: httparty
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: bundler
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.10'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - "~>"
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '1.10'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: pry
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rake
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '10.0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - "~>"
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '10.0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: rspec
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: rubocop
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
description:
|
128
|
+
email:
|
129
|
+
- adam.nowak@netguru.co
|
130
|
+
- katarzyna.jaskolska@netguru.co
|
131
|
+
- jacek.adamek@netguru.co
|
132
|
+
executables: []
|
133
|
+
extensions: []
|
134
|
+
extra_rdoc_files: []
|
135
|
+
files:
|
136
|
+
- ".gitignore"
|
137
|
+
- ".rspec"
|
138
|
+
- ".rubocop.yml"
|
139
|
+
- ".travis.yml"
|
140
|
+
- Gemfile
|
141
|
+
- README.md
|
142
|
+
- Rakefile
|
143
|
+
- bin/console
|
144
|
+
- bin/setup
|
145
|
+
- data_guru.gemspec
|
146
|
+
- lib/data_guru.rb
|
147
|
+
- lib/data_guru/client.rb
|
148
|
+
- lib/data_guru/collection.rb
|
149
|
+
- lib/data_guru/configuration.rb
|
150
|
+
- lib/data_guru/model.rb
|
151
|
+
- lib/data_guru/model_configuration.rb
|
152
|
+
- lib/data_guru/validation.rb
|
153
|
+
- lib/data_guru/validations/configuration.rb
|
154
|
+
- lib/data_guru/validations/model_configuration.rb
|
155
|
+
- lib/data_guru/version.rb
|
156
|
+
homepage: https://github.com/netguru/data_guru
|
157
|
+
licenses: []
|
158
|
+
metadata: {}
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubyforge_project:
|
175
|
+
rubygems_version: 2.4.8
|
176
|
+
signing_key:
|
177
|
+
specification_version: 4
|
178
|
+
summary: Wrapper for data stored in YAML files
|
179
|
+
test_files: []
|