graphql_rails 0.6.0 → 1.2.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 +4 -4
- data/.hound.yml +1 -0
- data/.rubocop.yml +3 -3
- data/.ruby-version +1 -1
- data/.travis.yml +2 -2
- data/CHANGELOG.md +38 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +181 -71
- data/docs/README.md +48 -9
- data/docs/_sidebar.md +5 -0
- data/docs/components/controller.md +294 -8
- data/docs/components/decorator.md +69 -0
- data/docs/components/model.md +349 -11
- data/docs/components/routes.md +43 -1
- data/docs/getting_started/quick_start.md +9 -2
- data/docs/index.html +1 -1
- data/docs/logging_and_monitoring/logging_and_monitoring.md +35 -0
- data/docs/other_tools/query_runner.md +49 -0
- data/docs/other_tools/schema_dump.md +29 -0
- data/docs/testing/testing.md +3 -1
- data/graphql_rails.gemspec +5 -4
- data/lib/generators/graphql_rails/install_generator.rb +50 -0
- data/lib/generators/graphql_rails/templates/example_users_controller.erb +19 -0
- data/lib/generators/graphql_rails/templates/graphql_application_controller.erb +8 -0
- data/lib/generators/graphql_rails/templates/graphql_controller.erb +20 -0
- data/lib/generators/graphql_rails/templates/graphql_router.erb +19 -0
- data/lib/generators/graphql_rails/templates/graphql_router_spec.erb +21 -0
- data/lib/graphql_rails.rb +7 -1
- data/lib/graphql_rails/attributes.rb +13 -0
- data/lib/graphql_rails/{attribute → attributes}/attributable.rb +25 -20
- data/lib/graphql_rails/attributes/attribute.rb +94 -0
- data/lib/graphql_rails/{attribute → attributes}/attribute_name_parser.rb +2 -2
- data/lib/graphql_rails/attributes/input_attribute.rb +65 -0
- data/lib/graphql_rails/attributes/input_type_parser.rb +62 -0
- data/lib/graphql_rails/attributes/type_name_info.rb +38 -0
- data/lib/graphql_rails/attributes/type_parseable.rb +128 -0
- data/lib/graphql_rails/attributes/type_parser.rb +121 -0
- data/lib/graphql_rails/concerns/service.rb +19 -0
- data/lib/graphql_rails/controller.rb +42 -21
- data/lib/graphql_rails/controller/action.rb +12 -67
- data/lib/graphql_rails/controller/action_configuration.rb +71 -31
- data/lib/graphql_rails/controller/build_controller_action_resolver.rb +52 -0
- data/lib/graphql_rails/controller/build_controller_action_resolver/controller_action_resolver.rb +28 -0
- data/lib/graphql_rails/controller/configuration.rb +56 -4
- data/lib/graphql_rails/controller/log_controller_action.rb +71 -0
- data/lib/graphql_rails/controller/request.rb +29 -8
- data/lib/graphql_rails/controller/request/format_errors.rb +58 -0
- data/lib/graphql_rails/decorator.rb +41 -0
- data/lib/graphql_rails/decorator/relation_decorator.rb +75 -0
- data/lib/graphql_rails/errors/custom_execution_error.rb +22 -0
- data/lib/graphql_rails/errors/execution_error.rb +8 -7
- data/lib/graphql_rails/errors/system_error.rb +14 -0
- data/lib/graphql_rails/errors/validation_error.rb +1 -5
- data/lib/graphql_rails/input_configurable.rb +47 -0
- data/lib/graphql_rails/integrations.rb +19 -0
- data/lib/graphql_rails/integrations/lograge.rb +39 -0
- data/lib/graphql_rails/integrations/sentry.rb +34 -0
- data/lib/graphql_rails/model.rb +26 -4
- data/lib/graphql_rails/model/add_fields_to_graphql_type.rb +45 -0
- data/lib/graphql_rails/model/build_connection_type.rb +52 -0
- data/lib/graphql_rails/model/{configuration → build_connection_type}/count_items.rb +5 -5
- data/lib/graphql_rails/model/build_enum_type.rb +68 -0
- data/lib/graphql_rails/model/{graphql_input_type_builder.rb → build_graphql_input_type.rb} +10 -2
- data/lib/graphql_rails/model/call_graphql_model_method.rb +72 -0
- data/lib/graphql_rails/model/configurable.rb +6 -2
- data/lib/graphql_rails/model/configuration.rb +34 -19
- data/lib/graphql_rails/model/find_or_build_graphql_type.rb +64 -0
- data/lib/graphql_rails/model/find_or_build_graphql_type_class.rb +46 -0
- data/lib/graphql_rails/model/input.rb +25 -11
- data/lib/graphql_rails/query_runner.rb +68 -0
- data/lib/graphql_rails/railtie.rb +10 -0
- data/lib/graphql_rails/router.rb +40 -13
- data/lib/graphql_rails/router/resource_routes_builder.rb +19 -11
- data/lib/graphql_rails/router/route.rb +21 -6
- data/lib/graphql_rails/router/schema_builder.rb +36 -11
- data/lib/graphql_rails/rspec_controller_helpers.rb +6 -4
- data/lib/graphql_rails/tasks/dump_graphql_schema.rb +57 -0
- data/lib/graphql_rails/tasks/schema.rake +14 -0
- data/lib/graphql_rails/version.rb +1 -1
- metadata +78 -26
- data/README.md +0 -194
- data/lib/graphql_rails/attribute.rb +0 -28
- data/lib/graphql_rails/attribute/type_parser.rb +0 -115
- data/lib/graphql_rails/controller/controller_function.rb +0 -50
- data/lib/graphql_rails/controller/format_results.rb +0 -36
- data/lib/graphql_rails/model/graphql_type_builder.rb +0 -33
- data/lib/graphql_rails/model/input_attribute.rb +0 -47
data/README.md
DELETED
@@ -1,194 +0,0 @@
|
|
1
|
-
# GraphqlRails
|
2
|
-
|
3
|
-
[](https://travis-ci.org/samesystem/graphql_rails)
|
4
|
-
[](https://codecov.io/gh/samesystem/graphql_rails)
|
5
|
-
[](https://samesystem.github.io/graphql_rails)
|
6
|
-
|
7
|
-
Rails style structure for GraphQL API.
|
8
|
-
|
9
|
-
## Installation
|
10
|
-
|
11
|
-
Add this line to your application's Gemfile:
|
12
|
-
|
13
|
-
```ruby
|
14
|
-
gem 'graphql_rails'
|
15
|
-
```
|
16
|
-
|
17
|
-
And then execute:
|
18
|
-
|
19
|
-
$ bundle
|
20
|
-
|
21
|
-
Or install it yourself as:
|
22
|
-
|
23
|
-
$ gem install graphql_rails
|
24
|
-
|
25
|
-
## Usage
|
26
|
-
|
27
|
-
### Define GraphQL schema as RoR routes
|
28
|
-
|
29
|
-
```ruby
|
30
|
-
MyGraphqlSchema = GraphqlRails::Router.draw do
|
31
|
-
# will create createUser, updateUser, deleteUser mutations and user, users queries.
|
32
|
-
# expects that UsersController class exist
|
33
|
-
resources :users
|
34
|
-
|
35
|
-
# if you want custom queries or mutation
|
36
|
-
query 'searchLogs', to: 'logs#search' # redirects request to LogsController
|
37
|
-
mutation 'changeUserPassword', to: 'users#change_password'
|
38
|
-
end
|
39
|
-
```
|
40
|
-
|
41
|
-
### Define your Graphql model
|
42
|
-
|
43
|
-
```ruby
|
44
|
-
class User # works with any class including ActiveRecord
|
45
|
-
include GraphqlRails::Model
|
46
|
-
|
47
|
-
graphql do |c|
|
48
|
-
# most common attributes, like :id, :name, :title has default type, so you don't have to specify it (but you can!)
|
49
|
-
c.attribute :id
|
50
|
-
|
51
|
-
c.attribute :email, type: :string
|
52
|
-
c.attribute :surname, type: :string
|
53
|
-
end
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
### Define controller
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
class UsersController < GraphqlRails::Controller
|
61
|
-
# graphql requires to describe which attributes controller action accepts and which returns
|
62
|
-
action(:change_user_password)
|
63
|
-
.permit(:password!, :id!) # Bang (!) indicates that attribute is required
|
64
|
-
|
65
|
-
def change_user_password
|
66
|
-
user = User.find(params[:id])
|
67
|
-
user.update!(password: params[:password])
|
68
|
-
|
69
|
-
# returned value needs to have all methods defined in model `graphql do` part
|
70
|
-
user # or SomeDecorator.new(user)
|
71
|
-
end
|
72
|
-
|
73
|
-
action(:search).permit(search_fields!: SearchFieldsInput) # you can specify your own input fields
|
74
|
-
def search
|
75
|
-
end
|
76
|
-
end
|
77
|
-
```
|
78
|
-
|
79
|
-
## Routes
|
80
|
-
|
81
|
-
```ruby
|
82
|
-
MyGraphqlSchema = GraphqlRails::Router.draw do
|
83
|
-
# generates `friend`, `createFriend`, `updateFriend`, `destroyFriend`, `friends` routes
|
84
|
-
resources :friends
|
85
|
-
resources :shops, only: [:show, :index] # generates `shop` and `shops` routes only
|
86
|
-
resources :orders, except: :update # generates all routes except `updateOrder`
|
87
|
-
|
88
|
-
resources :users do
|
89
|
-
# generates `findUser` query
|
90
|
-
query :find, on: :member
|
91
|
-
|
92
|
-
# generates `searchUsers` query
|
93
|
-
query :search, on: :collection
|
94
|
-
end
|
95
|
-
|
96
|
-
# you can use namespaced controllers too:
|
97
|
-
scope module: 'admin' do
|
98
|
-
# `updateTranslations` route will be handeled by `Admin::TranslationsController`
|
99
|
-
mutation :updateTranslations, to: 'translations#update'
|
100
|
-
|
101
|
-
# all :groups routes will be handeled by `Admin::GroupsController`
|
102
|
-
resources :groups
|
103
|
-
end
|
104
|
-
end
|
105
|
-
```
|
106
|
-
|
107
|
-
## Testing your GraphqlRails::Controller in RSpec
|
108
|
-
|
109
|
-
### Setup
|
110
|
-
|
111
|
-
Add those lines in your `spec/spec_helper.rb` file
|
112
|
-
|
113
|
-
```ruby
|
114
|
-
# spec/spec_helper.rb
|
115
|
-
require 'graphql_rails/rspec_controller_helpers'
|
116
|
-
|
117
|
-
RSpec.configure do |config|
|
118
|
-
config.include(GraphqlRails::RSpecControllerHelpers, type: :graphql_controller)
|
119
|
-
# ... your other configuration ...
|
120
|
-
end
|
121
|
-
```
|
122
|
-
|
123
|
-
### Helper methods
|
124
|
-
|
125
|
-
There are 3 helper methods:
|
126
|
-
|
127
|
-
* `mutation(:your_controller_action_name, params: {}, context: {})`. `params` and `context` are optional
|
128
|
-
* `query(:your_controller_action_name, params: {}, context: {})`. `params` and `context` are optional
|
129
|
-
* `response`. Response is set only after you call `mutation` or `query`
|
130
|
-
|
131
|
-
### Test examples
|
132
|
-
|
133
|
-
```ruby
|
134
|
-
class MyGraphqlController
|
135
|
-
def index
|
136
|
-
"Called from index: #{params[:message]}"
|
137
|
-
end
|
138
|
-
|
139
|
-
action(:create_user).permit(:full_name, :email)
|
140
|
-
def create_user
|
141
|
-
User.create!(params)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
RSpec.describe MyGraphqlController, type: :graphql_controller do
|
146
|
-
describe '#index' do
|
147
|
-
it 'is successful' do
|
148
|
-
query(:index)
|
149
|
-
expect(response).to be_successful
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'returns correct message' do
|
153
|
-
query(:index, params: { message: 'Hello world!' })
|
154
|
-
expect(response.result).to eq "Called from index: Hello world!"
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
describe '#create_user' do
|
159
|
-
context 'when bad email is given' do
|
160
|
-
it 'fails' do
|
161
|
-
mutation(:create_user, params { email: 'bad' })
|
162
|
-
expect(response).to be_failure
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'contains errors' do
|
166
|
-
mutation(:create_user, params { email: 'bad' })
|
167
|
-
expect(response.errors).not_to be_empty
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
```
|
173
|
-
|
174
|
-
## Detailed documentation
|
175
|
-
|
176
|
-
Check https://samesystem.github.io/graphql_rails for more details
|
177
|
-
|
178
|
-
## Development
|
179
|
-
|
180
|
-
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.
|
181
|
-
|
182
|
-
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).
|
183
|
-
|
184
|
-
## Contributing
|
185
|
-
|
186
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/samesystem/graphql_rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
187
|
-
|
188
|
-
## License
|
189
|
-
|
190
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
191
|
-
|
192
|
-
## Code of Conduct
|
193
|
-
|
194
|
-
Everyone interacting in the GraphqlRails project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/samesystem/graphql_rails/blob/master/CODE_OF_CONDUCT.md).
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'graphql'
|
4
|
-
require 'graphql_rails/attribute/attributable'
|
5
|
-
|
6
|
-
module GraphqlRails
|
7
|
-
# contains info about single graphql attribute
|
8
|
-
class Attribute
|
9
|
-
include Attributable
|
10
|
-
|
11
|
-
attr_reader :property, :description
|
12
|
-
|
13
|
-
def initialize(name, type = nil, description: nil, property: name)
|
14
|
-
@initial_type = type
|
15
|
-
@initial_name = name
|
16
|
-
@description = description
|
17
|
-
@property = property.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
def field_args
|
21
|
-
[field_name, graphql_field_type, { property: property.to_sym, description: description }]
|
22
|
-
end
|
23
|
-
|
24
|
-
protected
|
25
|
-
|
26
|
-
attr_reader :initial_type, :initial_name
|
27
|
-
end
|
28
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'graphql'
|
4
|
-
|
5
|
-
module GraphqlRails
|
6
|
-
class Attribute
|
7
|
-
# converts string value in to GraphQL type
|
8
|
-
class TypeParser
|
9
|
-
class UnknownTypeError < ArgumentError; end
|
10
|
-
|
11
|
-
TYPE_MAPPING = {
|
12
|
-
'id' => GraphQL::ID_TYPE,
|
13
|
-
|
14
|
-
'int' => GraphQL::INT_TYPE,
|
15
|
-
'integer' => GraphQL::INT_TYPE,
|
16
|
-
|
17
|
-
'string' => GraphQL::STRING_TYPE,
|
18
|
-
'str' => GraphQL::STRING_TYPE,
|
19
|
-
'text' => GraphQL::STRING_TYPE,
|
20
|
-
'time' => GraphQL::STRING_TYPE,
|
21
|
-
'date' => GraphQL::STRING_TYPE,
|
22
|
-
|
23
|
-
'bool' => GraphQL::BOOLEAN_TYPE,
|
24
|
-
'boolean' => GraphQL::BOOLEAN_TYPE,
|
25
|
-
|
26
|
-
'float' => GraphQL::FLOAT_TYPE,
|
27
|
-
'double' => GraphQL::FLOAT_TYPE,
|
28
|
-
'decimal' => GraphQL::FLOAT_TYPE
|
29
|
-
}.freeze
|
30
|
-
|
31
|
-
def initialize(unparsed_type)
|
32
|
-
@unparsed_type = unparsed_type
|
33
|
-
end
|
34
|
-
|
35
|
-
def graphql_type
|
36
|
-
return unparsed_type if raw_graphql_type?
|
37
|
-
|
38
|
-
if list?
|
39
|
-
parsed_list_type
|
40
|
-
else
|
41
|
-
parsed_inner_type
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def graphql_model
|
46
|
-
type_class = inner_type_name.safe_constantize
|
47
|
-
return unless type_class.respond_to?(:graphql)
|
48
|
-
|
49
|
-
type_class
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
attr_reader :unparsed_type
|
55
|
-
|
56
|
-
def parsed_list_type
|
57
|
-
list_type = parsed_inner_type.to_list_type
|
58
|
-
|
59
|
-
if required_list_type?
|
60
|
-
list_type.to_non_null_type
|
61
|
-
else
|
62
|
-
list_type
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def parsed_inner_type
|
67
|
-
if required_inner_type?
|
68
|
-
type_by_name.to_non_null_type
|
69
|
-
else
|
70
|
-
type_by_name
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def required_inner_type?
|
75
|
-
!!unparsed_type[/\w!/] # rubocop:disable Style/DoubleNegation
|
76
|
-
end
|
77
|
-
|
78
|
-
def list?
|
79
|
-
unparsed_type.to_s.include?(']')
|
80
|
-
end
|
81
|
-
|
82
|
-
def required_list_type?
|
83
|
-
unparsed_type.to_s.include?(']!')
|
84
|
-
end
|
85
|
-
|
86
|
-
def raw_graphql_type?
|
87
|
-
unparsed_type.is_a?(GraphQL::BaseType) ||
|
88
|
-
unparsed_type.is_a?(GraphQL::ObjectType) ||
|
89
|
-
unparsed_type.is_a?(GraphQL::InputObjectType) ||
|
90
|
-
(defined?(GraphQL::Schema::Member) && unparsed_type.is_a?(Class) && unparsed_type < GraphQL::Schema::Member)
|
91
|
-
end
|
92
|
-
|
93
|
-
def inner_type_name
|
94
|
-
unparsed_type.to_s.tr('[]!', '')
|
95
|
-
end
|
96
|
-
|
97
|
-
def type_by_name
|
98
|
-
TYPE_MAPPING.fetch(inner_type_name.downcase) do
|
99
|
-
dynamicly_defined_type || raise(
|
100
|
-
UnknownTypeError,
|
101
|
-
"Type #{unparsed_type.inspect} is not supported. Supported scalar types are: #{TYPE_MAPPING.keys}." \
|
102
|
-
' All the classes that includes `GraphqlRails::Model` are also supported as types.'
|
103
|
-
)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def dynamicly_defined_type
|
108
|
-
type_class = graphql_model
|
109
|
-
return unless type_class
|
110
|
-
|
111
|
-
type_class.graphql.graphql_type
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'graphql_rails/controller/action'
|
4
|
-
require_relative 'request'
|
5
|
-
require_relative 'action'
|
6
|
-
|
7
|
-
module GraphqlRails
|
8
|
-
class Controller
|
9
|
-
# graphql resolver which redirects actions to appropriate controller and controller action
|
10
|
-
class ControllerFunction < GraphQL::Function
|
11
|
-
# accepts path of given format "controller_name#action"
|
12
|
-
attr_reader :type
|
13
|
-
|
14
|
-
def initialize(controller:, action_name:, type:)
|
15
|
-
@controller = controller
|
16
|
-
@action_name = action_name
|
17
|
-
@type = type
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.from_route(route)
|
21
|
-
action = Action.new(route)
|
22
|
-
|
23
|
-
action_function_class(action).new(
|
24
|
-
controller: action.controller,
|
25
|
-
action_name: action.name,
|
26
|
-
type: action.return_type
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.action_function_class(action)
|
31
|
-
Class.new(self) do
|
32
|
-
description(action.description)
|
33
|
-
|
34
|
-
action.arguments.each do |attribute|
|
35
|
-
argument(*attribute.function_argument_args)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def call(object, inputs, ctx)
|
41
|
-
request = Request.new(object, inputs, ctx)
|
42
|
-
controller.new(request).call(action_name)
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
attr_reader :controller, :action_name
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GraphqlRails
|
4
|
-
class Controller
|
5
|
-
# Convers raw controller results in to graphql-friendly format
|
6
|
-
class FormatResults
|
7
|
-
def initialize(original_result, action_config:, params:, graphql_context:)
|
8
|
-
@original_result = original_result
|
9
|
-
@action_config = action_config
|
10
|
-
@controller_params = params
|
11
|
-
@graphql_context = graphql_context
|
12
|
-
end
|
13
|
-
|
14
|
-
def call
|
15
|
-
if action_config.paginated? && original_result
|
16
|
-
paginated_result
|
17
|
-
else
|
18
|
-
original_result
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
attr_reader :original_result, :action_config, :controller_params, :graphql_context
|
25
|
-
|
26
|
-
def paginated_result
|
27
|
-
pagination_params = controller_params.slice(:first, :last, :before, :after)
|
28
|
-
pagination_options = action_config.pagination_options.merge(context: graphql_context)
|
29
|
-
|
30
|
-
GraphQL::Relay::BaseConnection
|
31
|
-
.connection_for_nodes(original_result)
|
32
|
-
.new(original_result, pagination_params, pagination_options)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GraphqlRails
|
4
|
-
module Model
|
5
|
-
# stores information about model specific config, like attributes and types
|
6
|
-
class GraphqlTypeBuilder
|
7
|
-
def initialize(name:, description: nil, attributes:)
|
8
|
-
@name = name
|
9
|
-
@attributes = attributes
|
10
|
-
@description = description
|
11
|
-
end
|
12
|
-
|
13
|
-
def call
|
14
|
-
type_name = name
|
15
|
-
type_description = description
|
16
|
-
type_attributes = attributes
|
17
|
-
|
18
|
-
GraphQL::ObjectType.define do
|
19
|
-
name(type_name)
|
20
|
-
description(type_description)
|
21
|
-
|
22
|
-
type_attributes.each_value do |attribute|
|
23
|
-
field(*attribute.field_args)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
attr_reader :model_configuration, :attributes, :name, :description
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|