rails-code-generator 0.1.2 → 0.1.3

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: 3e0a15856855079249ca288614458381ad6f14bf2a82da4a993fbf77a0581562
4
- data.tar.gz: 5d2c2227de1cc9a03d4eb5de84a378f0dd4579433dde1cb78186481af6bcc807
3
+ metadata.gz: a58785634e9cb4a0e9ea51de9e3feed6953434eda056000455672489d3220b4f
4
+ data.tar.gz: d52276ce775667bb11a6802d5ee12a389587c0a29e2e42020503b276f242f90d
5
5
  SHA512:
6
- metadata.gz: 1f05b2b9aad986e3762bd1bdd5b10ff1189ca9dbb0677703f3c8aa24bdd5d788ad03a721a54bb420b9d8a8b580888f768f6ff8562789f0b40b49851f2ca4fbd1
7
- data.tar.gz: 62c9137dc2f4b00eaea6b56fa6d04feba68b7e153aa7f845b096e562d6c2d175bc167f9077d14fc0859e74f2caf24381bbe02188e8f51e66e2c92bdd814d85b5
6
+ metadata.gz: 97f6426558b8e1ddc60c35af5c931a1e12e628abdb7ca73cbd8641818242958e7179a9e8809e0d65c7d82e90d36e16a1a8654c5379c225cffaddc9f4a3561bfd
7
+ data.tar.gz: 88383886534fdc4954d7bf5b1a7291460324da0d1efec697879df8a7653d9ead08320b538e332471cbe9ac745c8cd294e71a3981459a98e40af4ae8db8b6c262
@@ -35,6 +35,10 @@ module RailsCodeGenerator
35
35
  template "shared/normalizer.rb", File.join("app/normalizers", "#{table_name}_normalizer.rb")
36
36
  end
37
37
 
38
+ def create_factory
39
+ template "shared/factory.rb", File.join("spec/factories", "#{singular_name}.rb")
40
+ end
41
+
38
42
  def create_request_specs
39
43
  template "shared/index_spec.rb", File.join("spec/requests", table_name, "index_spec.rb")
40
44
  template "shared/show_spec.rb", File.join("spec/requests", table_name, "show_spec.rb")
@@ -5,6 +5,7 @@ require "rails_helper"
5
5
  RSpec.describe "[POST] /<%= route_path %>", type: :request do
6
6
  Given(:path) { "/<%= route_path %>" }
7
7
  Given(:user) { create :user }
8
+ <%= request_spec_association_givens %>
8
9
 
9
10
  context "with valid params" do
10
11
  Given(:params) {
@@ -6,6 +6,7 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
6
6
  Given(:path) { "/<%= route_path %>/" + <%= singular_name %>.id.to_s }
7
7
  Given(:<%= singular_name %>) { create :<%= singular_name %> }
8
8
  Given(:user) { create :user }
9
+ <%= request_spec_association_givens %>
9
10
 
10
11
  context "with authenticated user & valid params" do
11
12
  Given(:params) {
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :<%= singular_name %> do
5
+ <%= factory_definition_body %>
6
+ end
7
+ end
@@ -5,6 +5,7 @@ require "rails_helper"
5
5
  RSpec.describe "[POST] /<%= route_path %>", type: :request do
6
6
  Given(:path) { "/<%= route_path %>" }
7
7
  Given(:user) { create :user }
8
+ <%= request_spec_association_givens %>
8
9
 
9
10
  context "with valid params" do
10
11
  Given(:params) {
@@ -6,6 +6,7 @@ RSpec.describe "[PATCH] /<%= route_path %>/:id", type: :request do
6
6
  Given(:path) { "/<%= route_path %>/#{<%= singular_name %>.id}" }
7
7
  Given(:<%= singular_name %>) { create :<%= singular_name %> }
8
8
  Given(:user) { create :user }
9
+ <%= request_spec_association_givens %>
9
10
 
10
11
  context "with authenticated user & valid params" do
11
12
  Given(:params) {
@@ -5,6 +5,7 @@ module Rails
5
5
  module Generator
6
6
  module ModelAttributes
7
7
  EXCLUDED_COLUMNS = %w[id created_at updated_at].freeze
8
+ AUTH_USER_ASSOCIATION = "user"
8
9
 
9
10
  DRY_TYPE_MAP = {
10
11
  "string" => :string,
@@ -70,7 +71,20 @@ module Rails
70
71
  padding = " " * indent
71
72
  return "#{padding}# TODO: add attributes" if model_attributes.empty?
72
73
 
73
- model_attributes.map { |attribute| "#{padding}#{attribute[:name]}: #{faker_expression_for(attribute)}," }.join("\n")
74
+ model_attributes.map { |attribute| "#{padding}#{attribute[:name]}: #{param_expression_for(attribute)}," }.join("\n")
75
+ end
76
+
77
+ def request_spec_association_givens
78
+ associations_for_givens.map { |association|
79
+ " Given(:#{association[:name]}) { create :#{association[:factory]} }"
80
+ }.join("\n")
81
+ end
82
+
83
+ def factory_definition_body
84
+ lines = factory_association_lines + factory_attribute_lines
85
+ return " # TODO: add attributes" if lines.empty?
86
+
87
+ lines.join("\n")
74
88
  end
75
89
 
76
90
  private
@@ -79,6 +93,34 @@ module Rails
79
93
  model_attributes.map { |attribute| attribute[:name].to_sym }
80
94
  end
81
95
 
96
+ def model_associations
97
+ model_attributes.filter_map { |attribute| attribute[:association] }
98
+ .uniq { |association| association[:name] }
99
+ end
100
+
101
+ def associations_for_givens
102
+ model_associations.reject { |association| association[:name] == AUTH_USER_ASSOCIATION }
103
+ end
104
+
105
+ def factory_association_lines
106
+ model_associations.map { |association|
107
+ " association :#{association[:name]}, factory: :#{association[:factory]}"
108
+ }
109
+ end
110
+
111
+ def factory_attribute_lines
112
+ attributes = model_attributes.reject { |attribute| attribute[:association] }
113
+ return [] if attributes.empty?
114
+
115
+ width = attributes.map { |attribute| attribute[:name].length }.max
116
+
117
+ attributes.map { |attribute|
118
+ name = attribute[:name].ljust(width)
119
+ expression = FAKER_EXPRESSION_MAP.fetch(attribute[:type], "Faker::Lorem.word")
120
+ " #{name} { #{expression} }"
121
+ }
122
+ end
123
+
82
124
  def format_symbol_list(names, indent: 6)
83
125
  padding = " " * indent
84
126
  names.map { |name| "#{padding}:#{name}," }.join("\n")
@@ -95,7 +137,10 @@ module Rails
95
137
  end
96
138
  end
97
139
 
98
- def faker_expression_for(attribute)
140
+ def param_expression_for(attribute)
141
+ association = attribute[:association]
142
+ return "#{association[:name]}.id" if association
143
+
99
144
  FAKER_EXPRESSION_MAP.fetch(attribute[:type], "Faker::Lorem.word")
100
145
  end
101
146
 
@@ -103,6 +148,8 @@ module Rails
103
148
  klass = class_name.constantize
104
149
  return [] unless klass.respond_to?(:columns)
105
150
 
151
+ associations_by_fk, polymorphic_fks = belongs_to_association_maps(klass)
152
+
106
153
  klass.columns.filter_map do |column|
107
154
  next if EXCLUDED_COLUMNS.include?(column.name)
108
155
 
@@ -112,11 +159,59 @@ module Rails
112
159
  name: column.name,
113
160
  type: type,
114
161
  dry_type: DRY_TYPE_MAP[type],
115
- }
162
+ association: association_for_column(column.name, associations_by_fk, polymorphic_fks),
163
+ }.compact
116
164
  end
117
165
  rescue StandardError
118
166
  []
119
167
  end
168
+
169
+ def belongs_to_association_maps(klass)
170
+ return [{}, []] unless klass.respond_to?(:reflect_on_all_associations)
171
+
172
+ associations_by_fk = {}
173
+ polymorphic_fks = []
174
+
175
+ klass.reflect_on_all_associations(:belongs_to).each do |reflection|
176
+ foreign_key = reflection.foreign_key.to_s
177
+
178
+ if reflection.options[:polymorphic]
179
+ polymorphic_fks << foreign_key
180
+ next
181
+ end
182
+
183
+ associations_by_fk[foreign_key] = {
184
+ name: reflection.name.to_s,
185
+ factory: factory_name_for(reflection),
186
+ }
187
+ rescue StandardError
188
+ next
189
+ end
190
+
191
+ [associations_by_fk, polymorphic_fks]
192
+ rescue StandardError
193
+ [{}, []]
194
+ end
195
+
196
+ def factory_name_for(reflection)
197
+ reflection.klass.model_name.singular
198
+ rescue StandardError
199
+ reflection.name.to_s
200
+ end
201
+
202
+ def association_for_column(column_name, associations_by_fk, polymorphic_fks)
203
+ return if polymorphic_fks.include?(column_name)
204
+ return associations_by_fk[column_name] if associations_by_fk.key?(column_name)
205
+ return unless column_name.end_with?("_id")
206
+
207
+ association_name = column_name.delete_suffix("_id")
208
+ return if association_name.empty?
209
+
210
+ {
211
+ name: association_name,
212
+ factory: association_name,
213
+ }
214
+ end
120
215
  end
121
216
  end
122
217
  end
@@ -3,7 +3,7 @@
3
3
  module Rails
4
4
  module Code
5
5
  module Generator
6
- VERSION = "0.1.2"
6
+ VERSION = "0.1.3"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-code-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Sweat
@@ -48,6 +48,7 @@ files:
48
48
  - lib/generators/rails_code_generator/resources/templates/bulk/update.rb.tt
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
+ - lib/generators/rails_code_generator/resources/templates/shared/factory.rb.tt
51
52
  - lib/generators/rails_code_generator/resources/templates/shared/index_spec.rb.tt
52
53
  - lib/generators/rails_code_generator/resources/templates/shared/normalizer.rb.tt
53
54
  - lib/generators/rails_code_generator/resources/templates/shared/show_spec.rb.tt