graphql-rails-activereflection 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []