hai 0.0.3 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd1e9a5e790765b1b2030e4384048a2ad08f420e2078b5d883e2bffd2d8dc8eb
4
- data.tar.gz: 4da9e653d8c708d2e01135aa8cbf70234ec73100a0c158cb3dbd1583a47add28
3
+ metadata.gz: 398bd31884dbdd9428de5a190d7266098c5ffbe0516e9d46587c6986097d3626
4
+ data.tar.gz: 5f1a60c718f37fdae163f36b8575c36826f0fe511410e6981d7ca48d4f2c0256
5
5
  SHA512:
6
- metadata.gz: dda8bcf71ee7a008b7fac3c6ad0f83b25e3d4fb3c50078b7cae6e1d9d896fa1d3d88b18eacced38fe7ce2e7e6c1efd55c02dc6187934376ab03e7f28f7ed7af4
7
- data.tar.gz: f125a58684eeba263730397623dd1f3fa58b1168423960c88cb5a0d4f815f6312c18d470d558c8cb8f9a992d542b60637c2086dd4487b0b8737ea48db0c19015
6
+ metadata.gz: 4db91d3fccbeec97c69aaee403a9d861f4a7ab5837f66279e0102041ae51d58505bc21f9bfebd26b148c2ae41de1c8b53479885bd73eb1297995a437683ebb2d
7
+ data.tar.gz: f6468efb72bdbf3c1e04f00de6778ba43b4bbf839f1c17bec32eee0918fc2ac23049ef2c4579fff6c8827fbbfb761596430310e0a1243b0fea3437d7fbbf6ab3
data/README.md CHANGED
@@ -21,7 +21,8 @@ And then execute:
21
21
 
22
22
  Hai is a resource based api and those resources are ActiveRecord models. Keeping with this first principle, let's see how it can be used in your Ruby application.
23
23
 
24
- ## Action Modifications
24
+ <details>
25
+ <summary>Action Modifications </summary>
25
26
 
26
27
  If you want to modify any of the actions, you can add a Actions module to the
27
28
  model that you want to modify.
@@ -49,7 +50,10 @@ class Post < ApplicationRecord
49
50
  end
50
51
  end
51
52
  ```
52
- ## Policies
53
+ </details>
54
+
55
+ <details>
56
+ <summary> Policies</summary>
53
57
  Policies are handled in the same manner of Action Modifications. We will use the `Policies` module in the model to handle things like authorization.
54
58
 
55
59
  ```ruby
@@ -84,8 +88,10 @@ class Post < ApplicationRecord
84
88
  end
85
89
  end
86
90
  ```
91
+ </details>
87
92
 
88
- ## Graphql
93
+ <details>
94
+ <summary>Graphql</summary>
89
95
 
90
96
  Hai Graphql depends on `graphql-ruby` so if you don't have that installed and
91
97
  boostrapped, head over to [ their repo and do that now ](https://github.com/rmosolgo/graphql-ruby#installation).
@@ -128,8 +134,11 @@ module Types
128
134
  end
129
135
  end
130
136
  ```
137
+ </details>
138
+
139
+ <details>
131
140
 
132
- ## Rest
141
+ <summary>Rest</summary>
133
142
 
134
143
  This is even easier than adding Hai Graphql. Hai Rest is a dynamic engine that can be mounted with any namespace. You just have to mount it in your routes file like this:
135
144
 
@@ -192,6 +201,9 @@ Or all things combined
192
201
  #### Delete a user
193
202
  `DELETE <base_url>/rest/users/1`
194
203
 
204
+ </details>
205
+
206
+
195
207
  ## Development
196
208
 
197
209
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
@@ -53,6 +53,10 @@ module Hai
53
53
 
54
54
  private
55
55
 
56
+ def context
57
+ try(:super) || {}
58
+ end
59
+
56
60
  def model_class
57
61
  params[:model].classify.constantize
58
62
  end
@@ -0,0 +1,61 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/base'
3
+
4
+ module Hai
5
+ module Install
6
+ class GraphqlGenerator < Rails::Generators::Base
7
+ def rails_preload
8
+ Rails.application.eager_load!
9
+ end
10
+
11
+ def install_graphql_ruby
12
+ gem 'graphql'
13
+ run "bundle install"
14
+ run "rails generate graphql:install"
15
+ end
16
+
17
+ def add_types
18
+ hai_types = "hay_types(#{model_names.join(', ')})"
19
+ inject_into_file "app/graphql/#{app_name.underscore}_schema.rb", after: "class #{app_name}Schema < GraphQL::Schema" do <<~RUBY.indent(4)
20
+
21
+ include Hai::GraphQL::Types
22
+ hai_types(#{model_names.join(', ')})
23
+ RUBY
24
+ end
25
+ end
26
+
27
+ def add_queries
28
+ inject_into_file "app/graphql/types/query_type.rb", after: "include GraphQL::Types::Relay::HasNodesField" do <<~RUBY.indent(4)
29
+
30
+ include Hai::GraphQL
31
+ hai_query(#{model_names.join(', ')})
32
+ RUBY
33
+ end
34
+ end
35
+
36
+ def add_mutations
37
+ inject_into_file "app/graphql/types/mutation_type.rb", after: "class MutationType < Types::BaseObject" do <<~RUBY.indent(4)
38
+
39
+ include Hai::GraphQL
40
+ hai_mutation(#{model_names.join(', ')})
41
+ RUBY
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def model_names
48
+ ApplicationRecord.descendants.map(&:name)
49
+ end
50
+
51
+ def app_name
52
+ require File.expand_path("config/application", destination_root)
53
+ if Rails.application.class.respond_to?(:module_parent_name)
54
+ Rails.application.class.module_parent_name
55
+ else
56
+ Rails.application.class.parent_name
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/base'
3
+
4
+ module Hai
5
+ module Rest
6
+ class InstallGenerator < Rails::Generators::Base
7
+ def mount_engine
8
+ route <<-RUBY
9
+ mount Hai::Rest::Engine => "/rest"
10
+ RUBY
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/hai/create.rb CHANGED
@@ -14,7 +14,7 @@ module Hai
14
14
 
15
15
  return unauthorized_error unless check_policy(instance)
16
16
 
17
- instance.assign_attributes(**attrs)
17
+ instance.assign_attributes(**attrs) unless attrs.empty?
18
18
 
19
19
  run_action_modification(instance)
20
20
 
@@ -15,18 +15,21 @@ module Hai
15
15
  klass.description("Attributes for creating or updating a #{model}.")
16
16
  model.attribute_types.each do |attr, type|
17
17
  next if %w[id created_at updated_at].include?(attr)
18
+ next if attr.blank? # if the model has no other attributes
19
+
20
+ presence_validators = get_presence_validators(model)
18
21
 
19
22
  klass.argument(
20
23
  attr,
21
24
  Hai::GraphQL::TYPE_CAST[type.class] ||
22
25
  Hai::GraphQL::TYPE_CAST[type.class.superclass],
23
- required: false
26
+ required: presence_validators.include?(attr),
24
27
  )
25
28
  end
26
29
 
27
30
  klass.field(:result, ::Types.const_get("#{model}Type"))
28
31
 
29
- klass.define_method(:resolve) do |args|
32
+ klass.define_method(:resolve) do |args = {}|
30
33
  Hai::Create.new(model, context).execute(**args)
31
34
  end
32
35
  Hai::GraphQL::Types.const_set("Create#{model}", klass)
@@ -38,7 +41,18 @@ module Hai
38
41
  mutation: Hai::GraphQL::Types.const_get("Create#{model}")
39
42
  )
40
43
  end
44
+
45
+ private
46
+
47
+ def get_presence_validators(model)
48
+ model.validators.select do |v|
49
+ v.kind == :presence
50
+ end
51
+ .flat_map(&:attributes)
52
+ .map(&:to_s)
53
+ end
41
54
  end
42
55
  end
43
56
  end
44
57
  end
58
+
@@ -45,7 +45,8 @@ module Hai
45
45
 
46
46
  klass = Class.new(::Types::BaseObject)
47
47
  model.attribute_types.each do |attr, type|
48
- klass.send(:field, attr, Hai::GraphQL::TYPE_CAST[type.class])
48
+ next if defined?(model.get_restricted_attributes) && model.get_restricted_attributes.include?(attr.to_sym) # add test plz
49
+ klass.send(:field, attr, Hai::GraphQL::TYPE_CAST[type.class] || Hai::GraphQL::TYPE_CAST[type.class.superclass])
49
50
  rescue ArgumentError => e
50
51
  binding.pry
51
52
  end
@@ -80,7 +81,7 @@ module Hai
80
81
 
81
82
  klass.argument(
82
83
  attr,
83
- Hai::GraphQL::TYPE_CAST[type.class],
84
+ Hai::GraphQL::TYPE_CAST[type.class]|| Hai::GraphQL::TYPE_CAST[type.class.superclass],
84
85
  required: false
85
86
  )
86
87
  end
data/lib/hai/graphql.rb CHANGED
@@ -15,6 +15,7 @@ module Hai
15
15
  ActiveModel::Type::Integer => ::GraphQL::Types::Int,
16
16
  ActiveModel::Type::Float => ::GraphQL::Types::Float,
17
17
  ActiveModel::Type::String => ::GraphQL::Types::String,
18
+ ActiveRecord::Type::Text => ::GraphQL::Types::String,
18
19
  ActiveModel::Type::Boolean => ::GraphQL::Types::Boolean,
19
20
  ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter =>
20
21
  ::GraphQL::Types::ISO8601DateTime
@@ -23,6 +24,7 @@ module Hai
23
24
  ActiveModel::Type::Integer => Hai::GraphQL::Types::Arel::IntInputType,
24
25
  ActiveModel::Type::Float => Hai::GraphQL::Types::Arel::FloatInputType,
25
26
  ActiveModel::Type::String => Hai::GraphQL::Types::Arel::StringInputType,
27
+ ActiveRecord::Type::Text => Hai::GraphQL::Types::Arel::StringInputType,
26
28
  ActiveModel::Type::Boolean => Hai::GraphQL::Types::Arel::BooleanInputType,
27
29
  ActiveRecord::AttributeMethods::TimeZoneConversion::TimeZoneConverter =>
28
30
  Hai::GraphQL::Types::Arel::DateTimeInputType
@@ -33,15 +35,19 @@ module Hai
33
35
  end
34
36
 
35
37
  module ClassMethods
36
- def hai_query(model)
37
- Hai::GraphQL::ReadQueries.add(self, model)
38
- Hai::GraphQL::ListQueries.add(self, model)
38
+ def hai_query(*models)
39
+ models.each do |model|
40
+ Hai::GraphQL::ReadQueries.add(self, model)
41
+ Hai::GraphQL::ListQueries.add(self, model)
42
+ end
39
43
  end
40
44
 
41
- def hai_mutation(model)
42
- Hai::GraphQL::CreateMutations.add(self, model)
43
- Hai::GraphQL::UpdateMutations.add(self, model)
44
- Hai::GraphQL::DeleteMutations.add(self, model)
45
+ def hai_mutation(*models)
46
+ models.each do |model|
47
+ Hai::GraphQL::CreateMutations.add(self, model)
48
+ Hai::GraphQL::UpdateMutations.add(self, model)
49
+ Hai::GraphQL::DeleteMutations.add(self, model)
50
+ end
45
51
  end
46
52
  end
47
53
  end
data/lib/hai/read.rb CHANGED
@@ -34,7 +34,7 @@ module Hai
34
34
 
35
35
  private
36
36
 
37
- def check_read_policy
37
+ def check_read_policy(context)
38
38
  if model.const_defined?("Policies") && model::Policies.respond_to?(:read)
39
39
  model::Policies.read(context)
40
40
  else
@@ -42,7 +42,7 @@ module Hai
42
42
  end
43
43
  end
44
44
 
45
- def check_list_policy
45
+ def check_list_policy(context)
46
46
  if model.const_defined?("Policies") && model::Policies.respond_to?(:list)
47
47
  model::Policies.list(context)
48
48
  else
@@ -0,0 +1,17 @@
1
+ module Hai
2
+ module RestrictedAttributes
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def restricted_attributes(*attrs)
9
+ @@restricted_attributes = attrs
10
+ end
11
+
12
+ def get_restricted_attributes
13
+ @@restricted_attributes
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/hai/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hai
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.5"
5
5
  end
data/lib/hai.rb CHANGED
@@ -12,15 +12,18 @@ require_relative "hai/read"
12
12
  require_relative "hai/create"
13
13
  require_relative "hai/update"
14
14
  require_relative "hai/delete"
15
+ require_relative "hai/restricted_attributes"
15
16
 
16
17
  require_relative "hai/policies"
17
18
  require_relative "hai/action_mods"
18
19
  require "hai/railtie" if defined?(Rails)
20
+ require "generators/rest/install_generator" if defined?(Rails)
21
+ require "generators/install/graphql_generator" if defined?(Rails)
19
22
 
20
23
  module Hai
21
24
  class Error < StandardError
22
25
  end
23
- class Rest
26
+ module Rest
24
27
  class Engine < ::Rails::Engine
25
28
  isolate_namespace Hai
26
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - basicbrogrammer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-02-07 00:00:00.000000000 Z
11
+ date: 2023-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -82,6 +82,8 @@ files:
82
82
  - Rakefile
83
83
  - app/controllers/hai/rest_controller.rb
84
84
  - config/routes.rb
85
+ - lib/generators/install/graphql_generator.rb
86
+ - lib/generators/rest/install_generator.rb
85
87
  - lib/hai.rb
86
88
  - lib/hai/action_mods.rb
87
89
  - lib/hai/create.rb
@@ -97,6 +99,7 @@ files:
97
99
  - lib/hai/policies.rb
98
100
  - lib/hai/railtie.rb
99
101
  - lib/hai/read.rb
102
+ - lib/hai/restricted_attributes.rb
100
103
  - lib/hai/tasks/graphql/filter_type.rake
101
104
  - lib/hai/tasks/hai.rake
102
105
  - lib/hai/types/arel/boolean_input_type.rb