rails-code-generator 0.1.0 → 0.1.2

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.
Files changed (22) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/rails_code_generator/resources/resources_generator.rb +6 -0
  3. data/lib/generators/rails_code_generator/resources/templates/bulk/build.rb.tt +1 -0
  4. data/lib/generators/rails_code_generator/resources/templates/bulk/create_spec.rb.tt +1 -1
  5. data/lib/generators/rails_code_generator/resources/templates/bulk/create_validator.rb.tt +1 -1
  6. data/lib/generators/rails_code_generator/resources/templates/bulk/update.rb.tt +1 -1
  7. data/lib/generators/rails_code_generator/resources/templates/bulk/update_spec.rb.tt +1 -2
  8. data/lib/generators/rails_code_generator/resources/templates/bulk/update_validator.rb.tt +1 -1
  9. data/lib/generators/rails_code_generator/resources/templates/shared/index_spec.rb.tt +1 -1
  10. data/lib/generators/rails_code_generator/resources/templates/shared/normalizer.rb.tt +7 -0
  11. data/lib/generators/rails_code_generator/resources/templates/single/build.rb.tt +1 -0
  12. data/lib/generators/rails_code_generator/resources/templates/single/controller.rb.tt +2 -2
  13. data/lib/generators/rails_code_generator/resources/templates/single/create_spec.rb.tt +1 -1
  14. data/lib/generators/rails_code_generator/resources/templates/single/create_validator.rb.tt +1 -1
  15. data/lib/generators/rails_code_generator/resources/templates/single/destroy_spec.rb.tt +1 -2
  16. data/lib/generators/rails_code_generator/resources/templates/single/update.rb.tt +1 -0
  17. data/lib/generators/rails_code_generator/resources/templates/single/update_spec.rb.tt +1 -2
  18. data/lib/generators/rails_code_generator/resources/templates/single/update_validator.rb.tt +1 -1
  19. data/lib/rails/code/generator/model_attributes.rb +123 -0
  20. data/lib/rails/code/generator/version.rb +1 -1
  21. data/lib/rails/code/generator.rb +1 -0
  22. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae730a9fa958ca9c87a6208933bf17a6ae68abcb59ffa7ca8a5a38e11433d619
4
- data.tar.gz: 7961f74bcae4ef3f11a5881f0e9443ece5efac17e08839f7c5cc4530ca2765d3
3
+ metadata.gz: 3e0a15856855079249ca288614458381ad6f14bf2a82da4a993fbf77a0581562
4
+ data.tar.gz: 5d2c2227de1cc9a03d4eb5de84a378f0dd4579433dde1cb78186481af6bcc807
5
5
  SHA512:
6
- metadata.gz: 9e11301d2a0d69a8f36d8be68f2474a6579b5e3a71349169cd04f44b3f56dda8eb5258e680963355c73bee12f8b4b190ec32f9143535cf0de8935d7912336040
7
- data.tar.gz: 72dab9e9cef3b342762ca8478a46e0c0ec778f2d4804e8c79995b4863bed5e6c5e13bbed8e39d4f44fa473c6a017caabe0b4e37d04459bd83db705e7bf0c0a20
6
+ metadata.gz: 1f05b2b9aad986e3762bd1bdd5b10ff1189ca9dbb0677703f3c8aa24bdd5d788ad03a721a54bb420b9d8a8b580888f768f6ff8562789f0b40b49851f2ca4fbd1
7
+ data.tar.gz: 62c9137dc2f4b00eaea6b56fa6d04feba68b7e153aa7f845b096e562d6c2d175bc167f9077d14fc0859e74f2caf24381bbe02188e8f51e66e2c92bdd814d85b5
@@ -3,10 +3,12 @@
3
3
  require "rails/generators"
4
4
  require "rails/generators/named_base"
5
5
  require "rails/code/generator/naming"
6
+ require "rails/code/generator/model_attributes"
6
7
 
7
8
  module RailsCodeGenerator
8
9
  class ResourcesGenerator < Rails::Generators::NamedBase
9
10
  include Rails::Code::Generator::Naming
11
+ include Rails::Code::Generator::ModelAttributes
10
12
 
11
13
  class_option :bulk, type: :boolean, default: false, desc: "Generate bulk endpoints"
12
14
 
@@ -29,6 +31,10 @@ module RailsCodeGenerator
29
31
  File.join("app/validators", table_name, "update_validator.rb")
30
32
  end
31
33
 
34
+ def create_normalizer
35
+ template "shared/normalizer.rb", File.join("app/normalizers", "#{table_name}_normalizer.rb")
36
+ end
37
+
32
38
  def create_request_specs
33
39
  template "shared/index_spec.rb", File.join("spec/requests", table_name, "index_spec.rb")
34
40
  template "shared/show_spec.rb", File.join("spec/requests", table_name, "show_spec.rb")
@@ -3,6 +3,7 @@
3
3
  module <%= resource_module_name %>
4
4
  class Build
5
5
  PERMITTED_ATTRIBUTES = [
6
+ <%= permitted_attributes_list %>
6
7
  ].freeze
7
8
 
8
9
  def self.call params
@@ -10,7 +10,7 @@ RSpec.describe "[POST] /<%= route_path %>", type: :request do
10
10
  Given(:params) {
11
11
  {
12
12
  <%= table_name %>: {
13
- # TODO: add attributes
13
+ <%= request_params_attributes_list %>
14
14
  },
15
15
  }.to_json
16
16
  }
@@ -4,7 +4,7 @@ module <%= resource_module_name %>
4
4
  class CreateValidator < BaseValidator
5
5
  params do
6
6
  required(:<%= table_name %>).maybe :hash do
7
- # TODO: add attributes
7
+ <%= validator_attributes_list %>
8
8
  end
9
9
  end
10
10
  end
@@ -3,7 +3,7 @@
3
3
  module <%= resource_module_name %>
4
4
  class Update
5
5
  PERMITTED_ATTRIBUTES = [
6
- :id,
6
+ <%= permitted_attributes_list(include_id: true) %>
7
7
  ].freeze
8
8
 
9
9
  def self.call params
@@ -11,7 +11,7 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
11
11
  Given(:params) {
12
12
  {
13
13
  <%= table_name %>: {
14
- name: "Changed <%= singular_name %> name",
14
+ <%= request_params_attributes_list %>
15
15
  },
16
16
  }.to_json
17
17
  }
@@ -21,6 +21,5 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
21
21
  Then { expect(response).to be_successful }
22
22
  And { expect(response_body[:data]).not_to be_empty }
23
23
  And { expect(response_body[:errors]).to be_empty }
24
- And { expect(response_body.dig(:data, :name)).to eq "Changed <%= singular_name %> name" }
25
24
  end
26
25
  end
@@ -4,7 +4,7 @@ module <%= resource_module_name %>
4
4
  class UpdateValidator < BaseValidator
5
5
  params do
6
6
  required(:<%= table_name %>).maybe :hash do
7
- # TODO: add attributes
7
+ <%= validator_attributes_list %>
8
8
  end
9
9
  end
10
10
  end
@@ -5,7 +5,7 @@ require "rails_helper"
5
5
  RSpec.describe "[GET] /<%= route_path %>", type: :request do
6
6
  Given(:path) { "/<%= route_path %>" }
7
7
  Given(:user) { create :user }
8
- Given(:<%= singular_name %>) { create :<%= singular_name %> }
8
+ Given!(:<%= singular_name %>) { create :<%= singular_name %> }
9
9
 
10
10
  context "with authenticated user and valid params" do
11
11
  When { get path, headers: api_auth_headers(user) }
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class <%= resource_normalizer_class %> < BaseResponseNormalizer
4
+ attributes(
5
+ <%= normalizer_attributes_list(include_id: true) %>
6
+ )
7
+ end
@@ -3,6 +3,7 @@
3
3
  module <%= resource_module_name %>
4
4
  class Build
5
5
  PERMITTED_ATTRIBUTES = [
6
+ <%= permitted_attributes_list %>
6
7
  ].freeze
7
8
 
8
9
  def self.call params
@@ -20,7 +20,7 @@ class <%= resource_controller_class %> < ApplicationController
20
20
  def create
21
21
  validator = <%= resource_module_name %>::CreateValidator.call params
22
22
  errors = ValidationErrorFormatter.call validator
23
- validated_params = validator.to_h
23
+ validated_params = validator.to_h[:<%= singular_name %>]
24
24
 
25
25
  if errors.empty?
26
26
  <%= singular_name %> = <%= resource_module_name %>::Build.call validated_params
@@ -33,7 +33,7 @@ class <%= resource_controller_class %> < ApplicationController
33
33
  def update
34
34
  validator = <%= resource_module_name %>::UpdateValidator.call params
35
35
  errors = ValidationErrorFormatter.call validator
36
- validated_params = validator.to_h
36
+ validated_params = validator.to_h[:<%= singular_name %>]
37
37
 
38
38
  if errors.empty?
39
39
  <%= singular_name %> = <%= class_name %>.find params[:id]
@@ -10,7 +10,7 @@ RSpec.describe "[POST] /<%= route_path %>", type: :request do
10
10
  Given(:params) {
11
11
  {
12
12
  <%= singular_name %>: {
13
- # TODO: add attributes
13
+ <%= request_params_attributes_list %>
14
14
  },
15
15
  }.to_json
16
16
  }
@@ -4,7 +4,7 @@ module <%= resource_module_name %>
4
4
  class CreateValidator < BaseValidator
5
5
  params do
6
6
  required(:<%= singular_name %>).maybe :hash do
7
- # TODO: add attributes
7
+ <%= validator_attributes_list %>
8
8
  end
9
9
  end
10
10
  end
@@ -10,7 +10,6 @@ RSpec.describe "[DELETE] /<%= route_path %>/:id", type: :request do
10
10
  context "with authenticated user" do
11
11
  When { delete path, headers: api_auth_headers(user) }
12
12
 
13
- Then { expect(response_body[:errors]).to be_empty }
14
- And { expect(response).to be_successful }
13
+ Then { expect(response).to be_successful }
15
14
  end
16
15
  end
@@ -3,6 +3,7 @@
3
3
  module <%= resource_module_name %>
4
4
  class Update
5
5
  PERMITTED_ATTRIBUTES = [
6
+ <%= permitted_attributes_list %>
6
7
  ].freeze
7
8
 
8
9
  def self.call <%= singular_name %>, params
@@ -11,7 +11,7 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
11
11
  Given(:params) {
12
12
  {
13
13
  <%= singular_name %>: {
14
- name: "Changed <%= singular_name %> name",
14
+ <%= request_params_attributes_list %>
15
15
  },
16
16
  }.to_json
17
17
  }
@@ -21,6 +21,5 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
21
21
  Then { expect(response).to be_successful }
22
22
  And { expect(response_body[:data]).not_to be_empty }
23
23
  And { expect(response_body[:errors]).to be_empty }
24
- And { expect(response_body.dig(:data, :name)).to eq "Changed <%= singular_name %> name" }
25
24
  end
26
25
  end
@@ -4,7 +4,7 @@ module <%= resource_module_name %>
4
4
  class UpdateValidator < BaseValidator
5
5
  params do
6
6
  required(:<%= singular_name %>).maybe :hash do
7
- # TODO: add attributes
7
+ <%= validator_attributes_list %>
8
8
  end
9
9
  end
10
10
  end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rails
4
+ module Code
5
+ module Generator
6
+ module ModelAttributes
7
+ EXCLUDED_COLUMNS = %w[id created_at updated_at].freeze
8
+
9
+ DRY_TYPE_MAP = {
10
+ "string" => :string,
11
+ "text" => :string,
12
+ "citext" => :string,
13
+ "integer" => :integer,
14
+ "bigint" => :integer,
15
+ "float" => :float,
16
+ "decimal" => :decimal,
17
+ "boolean" => :bool,
18
+ "date" => :date,
19
+ "datetime" => :time,
20
+ "timestamp" => :time,
21
+ "timestamptz" => :time,
22
+ "json" => :hash,
23
+ "jsonb" => :hash,
24
+ "uuid" => :string,
25
+ }.freeze
26
+
27
+ FAKER_EXPRESSION_MAP = {
28
+ "string" => "Faker::Lorem.word",
29
+ "text" => "Faker::Lorem.paragraph",
30
+ "citext" => "Faker::Lorem.word",
31
+ "integer" => "Faker::Number.number(digits: 5)",
32
+ "bigint" => "Faker::Number.number(digits: 5)",
33
+ "float" => "Faker::Number.decimal(l_digits: 2).to_f",
34
+ "decimal" => "Faker::Number.decimal(l_digits: 2)",
35
+ "boolean" => "Faker::Boolean.boolean",
36
+ "date" => "Faker::Date.forward(days: 30)",
37
+ "datetime" => "Faker::Time.forward(days: 30)",
38
+ "timestamp" => "Faker::Time.forward(days: 30)",
39
+ "timestamptz" => "Faker::Time.forward(days: 30)",
40
+ "json" => "{}",
41
+ "jsonb" => "{}",
42
+ "uuid" => "Faker::Internet.uuid",
43
+ }.freeze
44
+
45
+ def model_attributes
46
+ @model_attributes ||= fetch_model_attributes
47
+ end
48
+
49
+ def permitted_attributes_list(include_id: false)
50
+ names = model_attribute_names
51
+ names = [:id, *names] if include_id
52
+ format_symbol_list(names)
53
+ end
54
+
55
+ def normalizer_attributes_list(include_id: false)
56
+ names = model_attribute_names
57
+ names = [:id, *names] if include_id
58
+ return " # TODO: add attributes" if names.empty?
59
+
60
+ format_symbol_list(names, indent: 4)
61
+ end
62
+
63
+ def validator_attributes_list
64
+ return " # TODO: add attributes" if model_attributes.empty?
65
+
66
+ model_attributes.map { |attribute| validator_line_for(attribute) }.join("\n")
67
+ end
68
+
69
+ def request_params_attributes_list(indent: 10)
70
+ padding = " " * indent
71
+ return "#{padding}# TODO: add attributes" if model_attributes.empty?
72
+
73
+ model_attributes.map { |attribute| "#{padding}#{attribute[:name]}: #{faker_expression_for(attribute)}," }.join("\n")
74
+ end
75
+
76
+ private
77
+
78
+ def model_attribute_names
79
+ model_attributes.map { |attribute| attribute[:name].to_sym }
80
+ end
81
+
82
+ def format_symbol_list(names, indent: 6)
83
+ padding = " " * indent
84
+ names.map { |name| "#{padding}:#{name}," }.join("\n")
85
+ end
86
+
87
+ def validator_line_for(attribute)
88
+ name = attribute[:name]
89
+ dry_type = attribute[:dry_type]
90
+
91
+ if dry_type
92
+ " optional(:#{name}).maybe :#{dry_type}"
93
+ else
94
+ " optional(:#{name})"
95
+ end
96
+ end
97
+
98
+ def faker_expression_for(attribute)
99
+ FAKER_EXPRESSION_MAP.fetch(attribute[:type], "Faker::Lorem.word")
100
+ end
101
+
102
+ def fetch_model_attributes
103
+ klass = class_name.constantize
104
+ return [] unless klass.respond_to?(:columns)
105
+
106
+ klass.columns.filter_map do |column|
107
+ next if EXCLUDED_COLUMNS.include?(column.name)
108
+
109
+ type = column.type.to_s
110
+
111
+ {
112
+ name: column.name,
113
+ type: type,
114
+ dry_type: DRY_TYPE_MAP[type],
115
+ }
116
+ end
117
+ rescue StandardError
118
+ []
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -3,7 +3,7 @@
3
3
  module Rails
4
4
  module Code
5
5
  module Generator
6
- VERSION = "0.1.0"
6
+ VERSION = "0.1.2"
7
7
  end
8
8
  end
9
9
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative "generator/version"
4
4
  require_relative "generator/naming"
5
+ require_relative "generator/model_attributes"
5
6
 
6
7
  module Rails
7
8
  module Code
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-code-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Sweat
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-31 00:00:00.000000000 Z
11
+ date: 2026-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -49,6 +49,7 @@ files:
49
49
  - lib/generators/rails_code_generator/resources/templates/bulk/update_spec.rb.tt
50
50
  - lib/generators/rails_code_generator/resources/templates/bulk/update_validator.rb.tt
51
51
  - lib/generators/rails_code_generator/resources/templates/shared/index_spec.rb.tt
52
+ - lib/generators/rails_code_generator/resources/templates/shared/normalizer.rb.tt
52
53
  - lib/generators/rails_code_generator/resources/templates/shared/show_spec.rb.tt
53
54
  - lib/generators/rails_code_generator/resources/templates/single/build.rb.tt
54
55
  - lib/generators/rails_code_generator/resources/templates/single/controller.rb.tt
@@ -60,6 +61,7 @@ files:
60
61
  - lib/generators/rails_code_generator/resources/templates/single/update_spec.rb.tt
61
62
  - lib/generators/rails_code_generator/resources/templates/single/update_validator.rb.tt
62
63
  - lib/rails/code/generator.rb
64
+ - lib/rails/code/generator/model_attributes.rb
63
65
  - lib/rails/code/generator/naming.rb
64
66
  - lib/rails/code/generator/railtie.rb
65
67
  - lib/rails/code/generator/version.rb