graphql-rails-activereflection 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f290ca96c78a7e555293a6c0579c148a98cd3cb7
4
+ data.tar.gz: e9d4d6c77d65f00195cceac332adc08716b1df04
5
+ SHA512:
6
+ metadata.gz: c8694fc4b9c0671f1fbf7f5827d9e12a672b676341de78dd4a7fd7eabe5432fa2495e178e882731777edf26dc4c5e1df9e2dd85bc6f61e7dcda242442d9e2fca
7
+ data.tar.gz: 665656bc9fb5419af9b85571004ad71a304694c5aea3a4629533ebe30059db03b81365bb51e7075c9b0fe78288b101cf13f2ffef125193b963233cadbc7f2253
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # GraphQL::Rails::ActiveReflection
2
+ ## CHANGELOG
3
+
4
+ ### Version 0.1.0
5
+ Initial commit. More to come.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Cole Turner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # GraphQL::Rails::ActiveReflection
2
+ ## (graphql-rails-activereflection)
3
+ Reflection over GraphQL for ActiveRecord models and validators
4
+
5
+ # What is it?
6
+ The purpose of this gem is to enable ActiveRecord reflections on models over GraphQL.
7
+
8
+ At release, this gem only contains reflections on validators. This is to avoid duplication and doubling up on the front-end for how to validate form inputs.
9
+
10
+ Eventually I would like to include some React examples and sample container components to apply the validators.
11
+
12
+ # Installation
13
+ To begin, install the gem by adding it to the `Gemfile`:
14
+
15
+ ```ruby
16
+ gem 'graphql-rails-activereflection'
17
+ ```
18
+
19
+ You're now ready to expose validators for your GraphQL Fields. This only works for fields that resolve to ActiveRecord Models.
20
+
21
+ To expose a field, add the following line:
22
+
23
+ ```ruby
24
+ implements GraphQL::Rails::ActiveReflection::Model.interface, inherit: true
25
+ ```
26
+
27
+ And that's it! This will add a `_model` field to the object type and enables the following query:
28
+
29
+ ```graphql
30
+ fragment on YourObjectType {
31
+ _model {
32
+ attributes {
33
+ name
34
+
35
+ validators {
36
+ abscence: Boolean
37
+ prescence: Boolean
38
+ uniqueness: Boolean
39
+ with_format: String
40
+ without_format: String
41
+ min_length: Integer
42
+ max_length: Integer
43
+ inclusion: [String]
44
+ exclusion: [String]
45
+ }
46
+
47
+ validate(int: Integer, str: String, float: Float, bool: Boolean) {
48
+ valid: Boolean
49
+ errors: [String]
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ Each of the validators corresponds to the standard Rails validators. Almost all validators for an attribute will be returned, **except those that have the `if` or `unless` conditionals.** This is by design and therefore make note that any conditional validations will have to be performed manually.
57
+
58
+ There is also the `validate(...)` field with arguments for standard scalar types. Any one of the arguments can be provided, but only one. The result will contain a `valid` boolean and a list of `errors` strings returned from the validators.
59
+
60
+ In the future all of the `validate(...)` should be chained for a single call.
61
+
62
+ ## Direction
63
+ Future plans for this module are to expose any reflections for an ActiveRecord model.
64
+
65
+ # Needs Help
66
+ If you wish to contribute to this project, any pull request is warmly welcomed.
67
+
68
+ - [ ] Documentation
69
+ - [ ] Examples
70
+ - [ ] Unit Tests
71
+ - [ ] Merge `validate(...)` calls
72
+
73
+ # Credits
74
+ - Cole Turner ([@colepatrickturner](https://github.com/colepatrickturner))
@@ -0,0 +1,42 @@
1
+ require 'graphql'
2
+ require 'graphql/rails/active_reflection/model_reflection'
3
+ require 'graphql/rails/active_reflection/attribute_reflection'
4
+ require 'graphql/rails/active_reflection/validation_result'
5
+ require 'graphql/rails/active_reflection/validator_reflection'
6
+ require 'graphql/rails/active_reflection/types'
7
+
8
+ module GraphQL
9
+ module Rails
10
+ module ActiveReflection
11
+ VERSION = '0.1.0'
12
+
13
+ class UnsupportedObject < StandardError; end
14
+
15
+ class Model
16
+ def self.interface
17
+ @interface ||= GraphQL::InterfaceType.define do
18
+ name "ActiveReflectionInterface"
19
+ field('_model', ModelReflectionType, 'Model of attributes for field.')
20
+ end
21
+ end
22
+
23
+ def self.field(**kwargs, &block)
24
+ # We have to define it fresh each time because
25
+ # its name will be modified and its description
26
+ # _may_ be modified.
27
+ field = GraphQL::Field.define do
28
+ type(GraphQL::Rails::ActiveReflection::Model.interface)
29
+ description('Fetch the content model for the given object.')
30
+ resolve(ModelReflection)
31
+ end
32
+
33
+ if kwargs.any? || block
34
+ field = field.redefine(kwargs, &block)
35
+ end
36
+
37
+ field
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ class AttributeReflection
5
+ @schema_name = "ActiveReflectionAttribute"
6
+
7
+ attr_reader :klass
8
+ attr_reader :name
9
+ attr_reader :description
10
+ attr_reader :validators
11
+
12
+ def initialize(field, klass, schema)
13
+ @klass = klass
14
+ @name = field.property || field.name
15
+ @validators = klass.validators.map { |validator|
16
+ return nil if validator.attributes.exclude? @name
17
+ return nil if validator.options[:if].present?
18
+ return nil if validator.options[:unless].present?
19
+
20
+ ValidatorReflection.new(validator)
21
+ }.compact
22
+ @errors = []
23
+ end
24
+
25
+ class << self
26
+ attr_accessor :schema_name
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ class ModelReflection
5
+ @schema_name = "ActiveReflectionModel"
6
+
7
+ def self.call(obj, args, ctx)
8
+ raise UnsupportedObject unless obj < ActiveRecord::Base
9
+ @reflections[obj.class] ||= new(obj.class, ctx.schema)
10
+ end
11
+
12
+ attr_reader :attributes
13
+
14
+ def initialize(klass, schema)
15
+ @klass = klass
16
+ @type = schema.resolve_type(@klass)
17
+ @schema = schema
18
+ @attributes = @type.fields.map { |field|
19
+ # No reflection if it's not a model attribute
20
+ property = field.property || field.name
21
+ return nil unless klass.attribute_names.include? property
22
+
23
+ AttributeReflection.new(field, klass, schema)
24
+ }.compact
25
+ end
26
+
27
+ class << self
28
+ attr_accessor :schema_name
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ require 'graphql/rails/active_reflection/types/model_reflection_type'
2
+ require 'graphql/rails/active_reflection/types/attribute_reflection_type'
3
+ require 'graphql/rails/active_reflection/types/validation_result_type'
4
+ require 'graphql/rails/active_reflection/types/validator_type'
@@ -0,0 +1,36 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ module Types
5
+
6
+ AttributeReflectionType = ::GraphQL::ObjectType.define do
7
+ name AttributeReflection.schema_name
8
+
9
+ field :name, !types.String
10
+ field :validators, ValidatorType.to_list_type
11
+ field :validate, ValidationResultType do
12
+ argument :int, types.Int
13
+ argument :str, types.String
14
+ argument :float, types.Float
15
+ argument :bool, types.Boolean
16
+
17
+ resolve ->(obj, args, _ctx) do
18
+ values = [args['int'], args['str'], args['float'], args['bool']]
19
+ raise ArgumentError, "Must specify at least one argument" if values.compact.empty?
20
+ raise ArgumentError, "Too many arguments, one expected" if values.compact.size > 1
21
+
22
+ value = values.compact.first
23
+
24
+ model = obj.klass.new
25
+ model[obj.name] = value
26
+
27
+ model.validate!
28
+ ValidationResult.new(model.valid?, model.errors[obj.name])
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ module Types
5
+ ModelReflectionType = ::GraphQL::ObjectType.define do
6
+ name ModelReflection.schema_name
7
+ field :attributes, AttributeReflectionType.to_list_type
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ module Types
5
+ ValidationResultType = ::GraphQL::ObjectType.define do
6
+ name ValidationResult.schema_name
7
+
8
+ field :valid, types.Boolean
9
+ field :errors, types.String.to_list_type
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,77 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ module Types
5
+ ValidatorType = ::GraphQL::ObjectType.define do
6
+ name ValidatorReflection.schema_name
7
+ # TODO NumericalityValidator
8
+
9
+ field :abscence, types.Boolean do
10
+ resolve ->(obj, _args, _ctx) do
11
+ obj < ActiveModel::Validations::AbsenceValidator
12
+ end
13
+ end
14
+
15
+ field :prescence, types.Boolean do
16
+ resolve ->(obj, _args, _ctx) do
17
+ obj < ActiveModel::Validations::PrescenceValidator
18
+ end
19
+ end
20
+
21
+ field :uniqueness, types.Boolean do
22
+ resolve ->(obj, _args, _ctx) do
23
+ obj < ActiveModel::Validations::UniquenessValidator
24
+ end
25
+ end
26
+
27
+ field :with_format, types.String do
28
+ resolve ->(obj, _args, _ctx) do
29
+ return nil unless obj < ActiveModel::Validations::FormatValidator
30
+ obj.options[:with]
31
+ end
32
+ end
33
+
34
+ field :without_format, types.String do
35
+ resolve ->(obj, _args, _ctx) do
36
+ return nil unless obj < ActiveModel::Validations::FormatValidator
37
+ obj.options[:without]
38
+ end
39
+ end
40
+
41
+ field :min_length, types.Int do
42
+ resolve ->(obj, _args, _ctx) do
43
+ return nil unless obj < ActiveModel::Validations::LengthValidator
44
+ obj.options[:minimum]
45
+ end
46
+ end
47
+
48
+ field :max_length, types.Int do
49
+ resolve ->(obj, _args, _ctx) do
50
+ return nil unless obj < ActiveModel::Validations::LengthValidator
51
+ obj.options[:maximum]
52
+ end
53
+ end
54
+
55
+ field :inclusion, types.String.to_list_type do
56
+ resolve ->(obj, _args, _ctx) do
57
+ return nil unless obj < ActiveModel::Validations::InclusionValidator
58
+ return nil if obj.options[:in].respond_to? :call
59
+ obj.options[:in]
60
+ end
61
+ end
62
+
63
+ field :exclusion, types.String.to_list_type do
64
+ resolve ->(obj, _args, _ctx) do
65
+ return nil unless obj < ActiveModel::Validations::ExclusionValidator
66
+ return nil if obj.options[:in].respond_to? :call
67
+ obj.options[:in]
68
+ end
69
+ end
70
+
71
+ # TODO AcceptanceValidator (is this relevant anymore?)
72
+
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ class ValidationResult
5
+ @schema_name = "ActiveReflectionValidation"
6
+
7
+ attr_reader :valid
8
+ attr_reader :errors
9
+
10
+ def initialize(valid, errors)
11
+ @valid = valid
12
+ @errors = errors
13
+ end
14
+
15
+ class << self
16
+ attr_accessor :schema_name
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,65 @@
1
+ module GraphQL
2
+ module Rails
3
+ module ActiveReflection
4
+ class ValidatorReflection
5
+ @schema_name = "ActiveReflectionValidator"
6
+
7
+ attr_reader :validator
8
+
9
+ def initialize(validator)
10
+ @validator = validator
11
+ end
12
+
13
+ def abscence
14
+ @validator < ActiveModel::Validations::AbsenceValidator
15
+ end
16
+
17
+ def prescence
18
+ resolve ->(obj, _args, _ctx) do
19
+ @validator < ActiveModel::Validations::PrescenceValidator
20
+ end
21
+ end
22
+
23
+ def uniqueness
24
+ @validator < ActiveModel::Validations::UniquenessValidator
25
+ end
26
+
27
+ def with_format
28
+ return nil unless @validator < ActiveModel::Validations::FormatValidator
29
+ @validator.options[:with]
30
+ end
31
+
32
+ def without_format
33
+ return nil unless @validator < ActiveModel::Validations::FormatValidator
34
+ @validator.options[:without]
35
+ end
36
+
37
+ def min_length
38
+ return nil unless @validator < ActiveModel::Validations::LengthValidator
39
+ @validator.options[:minimum]
40
+ end
41
+
42
+ def max_length
43
+ return nil unless @validator < ActiveModel::Validations::LengthValidator
44
+ @validator.options[:maximum]
45
+ end
46
+
47
+ def inclusion
48
+ return nil unless @validator < ActiveModel::Validations::InclusionValidator
49
+ return nil if @validator.options[:in].respond_to? :call
50
+ @validator.options[:in]
51
+ end
52
+
53
+ def exclusion
54
+ return nil unless @validator < ActiveModel::Validations::ExclusionValidator
55
+ return nil if @validator.options[:in].respond_to? :call
56
+ @validator.options[:in]
57
+ end
58
+
59
+ class << self
60
+ attr_accessor :schema_name
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: graphql-rails-activereflection
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cole Turner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-04-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: graphql
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.5.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.5.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: activerecord
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: Reflection over GraphQL for ActiveRecord models and validators
48
+ email: turner.cole@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - CHANGELOG.md
54
+ - LICENSE
55
+ - README.md
56
+ - lib/graphql/rails/active_reflection.rb
57
+ - lib/graphql/rails/active_reflection/attribute_reflection.rb
58
+ - lib/graphql/rails/active_reflection/model_reflection.rb
59
+ - lib/graphql/rails/active_reflection/types.rb
60
+ - lib/graphql/rails/active_reflection/types/attribute_reflection_type.rb
61
+ - lib/graphql/rails/active_reflection/types/model_reflection_type.rb
62
+ - lib/graphql/rails/active_reflection/types/validation_result_type.rb
63
+ - lib/graphql/rails/active_reflection/types/validator_type.rb
64
+ - lib/graphql/rails/active_reflection/validation_result.rb
65
+ - lib/graphql/rails/active_reflection/validator_reflection.rb
66
+ homepage: http://rubygems.org/gems/graphql-rails-activereflection
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 2.3.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.6.8
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Reflection over GraphQL for ActiveRecord validators
90
+ test_files: []