belt 0.2.13 → 0.2.14
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/lib/belt/cli/generate_command.rb +141 -20
- data/lib/belt/version.rb +1 -1
- data/lib/templates/generate/controller.rb.erb +58 -3
- data/lib/templates/generate/model.rb.erb +12 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 45b24007aa3cc00eb76d188f6958cf3db681c0a5365aff6419183064b36af8c8
|
|
4
|
+
data.tar.gz: 9dc9e908e5c46be7ec2ee2b835fd08be862de554a6c1ccafe04c9003d5245274
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 017ed10dec340386b86ed3f398225c53764f70845c3938c878bfa9033c0b81d53fb34797aca786258097a692fcaf7a7a72bbf22b8ba0a8e111982bd2d847b18a
|
|
7
|
+
data.tar.gz: ad9e69adcda08161b2992b3899822931c7144cba29ea5d3ef7e12d175c13d8572d9d0de50491959e2280cd3fb2509e814d85d2e9ed36ddf6964fff431f3b4d20
|
|
@@ -18,7 +18,7 @@ module Belt
|
|
|
18
18
|
|
|
19
19
|
include AppDetection
|
|
20
20
|
|
|
21
|
-
FIELD_TYPES = %w[string text integer float boolean date datetime].freeze
|
|
21
|
+
FIELD_TYPES = %w[string text integer float boolean date datetime references].freeze
|
|
22
22
|
|
|
23
23
|
GENERATOR_HELP = {
|
|
24
24
|
'scaffold' => {
|
|
@@ -30,7 +30,7 @@ module Belt
|
|
|
30
30
|
],
|
|
31
31
|
examples: [
|
|
32
32
|
['belt g scaffold post title body:text'],
|
|
33
|
-
['belt g scaffold comment
|
|
33
|
+
['belt g scaffold comment post:references body:text'],
|
|
34
34
|
['belt g scaffold task --skip-views'],
|
|
35
35
|
['belt g scaffold post title body:text --force']
|
|
36
36
|
],
|
|
@@ -44,6 +44,16 @@ module Belt
|
|
|
44
44
|
infrastructure/modules/app/dynamodb.tf DynamoDB table generated
|
|
45
45
|
frontend/src/pages/<names>/ React pages (if frontend exists)
|
|
46
46
|
|
|
47
|
+
Nested Resources:
|
|
48
|
+
Use `<parent>:references` to create a nested resource. This will:
|
|
49
|
+
- Add `belongs_to :<parent>` in the child model
|
|
50
|
+
- Add `has_many :<children>` in the parent model (if it exists)
|
|
51
|
+
- Generate a GSI on `<parent>_id` for efficient queries
|
|
52
|
+
- Nest routes under the parent (e.g., /posts/{post_id}/comments)
|
|
53
|
+
- Scope the controller index action to the parent
|
|
54
|
+
|
|
55
|
+
Example: `belt g scaffold comment post:references body:text`
|
|
56
|
+
|
|
47
57
|
Alias: `belt g resource` works the same way.
|
|
48
58
|
NOTES
|
|
49
59
|
},
|
|
@@ -132,7 +142,13 @@ module Belt
|
|
|
132
142
|
|
|
133
143
|
def self.parse_field(arg)
|
|
134
144
|
name, type = arg.split(':', 2)
|
|
135
|
-
|
|
145
|
+
type ||= 'string'
|
|
146
|
+
|
|
147
|
+
if %w[references belongs_to].include?(type)
|
|
148
|
+
{ name: name, type: 'references', referenced_model: name }
|
|
149
|
+
else
|
|
150
|
+
{ name: name, type: type }
|
|
151
|
+
end
|
|
136
152
|
end
|
|
137
153
|
|
|
138
154
|
RESERVED_NAMES = %w[
|
|
@@ -259,6 +275,7 @@ module Belt
|
|
|
259
275
|
@singular_name = Belt::Inflector.singularize(@name)
|
|
260
276
|
@resource_name = Belt::Inflector.pluralize(@singular_name)
|
|
261
277
|
@class_name = Belt::Inflector.classify(@singular_name)
|
|
278
|
+
@references, @regular_fields = @fields.partition { |f| f[:type] == 'references' }
|
|
262
279
|
end
|
|
263
280
|
|
|
264
281
|
def generate
|
|
@@ -327,6 +344,7 @@ module Belt
|
|
|
327
344
|
generate_controller
|
|
328
345
|
inject_routes
|
|
329
346
|
inject_schema
|
|
347
|
+
inject_parent_associations
|
|
330
348
|
sync_tables
|
|
331
349
|
generate_views_if_frontend
|
|
332
350
|
puts "\n✓ Scaffold '#{@singular_name}' generated!"
|
|
@@ -337,11 +355,16 @@ module Belt
|
|
|
337
355
|
puts " #{find_contracts_file_path || 'config/contracts.rb'} (updated)"
|
|
338
356
|
puts " lambda/lib/routes/#{@app_name}_routes.rb (updated)"
|
|
339
357
|
puts " frontend/src/pages/#{@resource_name}/ (views)" if Dir.exist?('frontend/src')
|
|
358
|
+
@references.each do |ref|
|
|
359
|
+
parent_model_path = "lambda/models/#{ref[:referenced_model]}.rb"
|
|
360
|
+
puts " #{parent_model_path} (updated — added has_many)" if File.exist?(parent_model_path)
|
|
361
|
+
end
|
|
340
362
|
end
|
|
341
363
|
|
|
342
364
|
def generate_model_standalone
|
|
343
365
|
generate_model
|
|
344
366
|
inject_schema
|
|
367
|
+
inject_parent_associations
|
|
345
368
|
sync_tables
|
|
346
369
|
end
|
|
347
370
|
|
|
@@ -363,6 +386,59 @@ module Belt
|
|
|
363
386
|
|
|
364
387
|
content = File.read(routes_file)
|
|
365
388
|
tables_arg = @fields.any? ? ", tables: [:#{@resource_name}]" : ''
|
|
389
|
+
|
|
390
|
+
# If this resource has a reference to a parent that already has routes, nest it
|
|
391
|
+
parent_ref = @references.find do |ref|
|
|
392
|
+
parent_resource = Belt::Inflector.pluralize(ref[:referenced_model])
|
|
393
|
+
content.match?(/resources :#{Regexp.escape(parent_resource)}\b/)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
if parent_ref
|
|
397
|
+
inject_nested_route(content, routes_file, parent_ref, tables_arg)
|
|
398
|
+
else
|
|
399
|
+
inject_top_level_route(content, routes_file, tables_arg)
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# Also update route manifest
|
|
403
|
+
inject_route_manifest
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def inject_nested_route(content, routes_file, parent_ref, tables_arg)
|
|
407
|
+
parent_resource = Belt::Inflector.pluralize(parent_ref[:referenced_model])
|
|
408
|
+
resource_line = "resources :#{@resource_name}#{tables_arg}"
|
|
409
|
+
|
|
410
|
+
# Find the parent resources line and convert to a block if needed
|
|
411
|
+
parent_pattern = /^(\s*)resources :#{Regexp.escape(parent_resource)}\b([^\n]*?)(?:\s*do\s*)?$/
|
|
412
|
+
|
|
413
|
+
if content.match?(/resources :#{Regexp.escape(parent_resource)}\b[^\n]*\bdo\b/)
|
|
414
|
+
# Parent already has a block — insert before its closing end
|
|
415
|
+
# Match the parent block: resources :parent do ... end
|
|
416
|
+
block_pattern = /^(\s*)(resources :#{Regexp.escape(parent_resource)}\b[^\n]*do\s*\n)(.*?)^\1(end)/m
|
|
417
|
+
if content.match?(block_pattern)
|
|
418
|
+
content.sub!(block_pattern) do
|
|
419
|
+
indent = ::Regexp.last_match(1)
|
|
420
|
+
opener = ::Regexp.last_match(2)
|
|
421
|
+
body = ::Regexp.last_match(3)
|
|
422
|
+
closer = ::Regexp.last_match(4)
|
|
423
|
+
"#{indent}#{opener}#{body}#{indent} #{resource_line}\n#{indent}#{closer}"
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
else
|
|
427
|
+
# Parent is a single line — convert to block form
|
|
428
|
+
content.sub!(parent_pattern) do
|
|
429
|
+
indent = ::Regexp.last_match(1)
|
|
430
|
+
parent_line_rest = ::Regexp.last_match(2).rstrip
|
|
431
|
+
"#{indent}resources :#{parent_resource}#{parent_line_rest} do\n" \
|
|
432
|
+
"#{indent} #{resource_line}\n" \
|
|
433
|
+
"#{indent}end"
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
File.write(routes_file, content)
|
|
438
|
+
puts " update #{routes_file}"
|
|
439
|
+
end
|
|
440
|
+
|
|
441
|
+
def inject_top_level_route(content, routes_file, tables_arg)
|
|
366
442
|
resource_line = "resources :#{@resource_name}#{tables_arg}"
|
|
367
443
|
|
|
368
444
|
# If this resource already exists in routes (force mode), replace it
|
|
@@ -377,17 +453,14 @@ module Belt
|
|
|
377
453
|
content.sub!('# resources :posts', resource_line)
|
|
378
454
|
else
|
|
379
455
|
# Find the target namespace block and insert before its closing `end`
|
|
380
|
-
# Match: `namespace :<name> do` ... `end` (the first `end` at the same indent level)
|
|
381
456
|
namespace_pattern = /^(\s*)namespace :#{Regexp.escape(@app_name)}\b[^\n]*do\s*\n(.*?)^\1end/m
|
|
382
457
|
|
|
383
458
|
if content.match?(namespace_pattern)
|
|
384
459
|
content.sub!(namespace_pattern) do |match|
|
|
385
460
|
indent = ::Regexp.last_match(1)
|
|
386
|
-
# Insert the resource line before the namespace's closing `end`
|
|
387
461
|
match.sub(/^(#{indent})end\z/m, "#{indent} #{resource_line}\n#{indent}end")
|
|
388
462
|
end
|
|
389
463
|
else
|
|
390
|
-
# Fallback: find any single namespace block and insert into it
|
|
391
464
|
single_ns_pattern = /^(\s*)namespace :\w+\b[^\n]*do\s*\n(.*?)^\1end/m
|
|
392
465
|
if content.match?(single_ns_pattern)
|
|
393
466
|
content.sub!(single_ns_pattern) do |match|
|
|
@@ -395,7 +468,6 @@ module Belt
|
|
|
395
468
|
match.sub(/^(#{indent})end\z/m, "#{indent} #{resource_line}\n#{indent}end")
|
|
396
469
|
end
|
|
397
470
|
else
|
|
398
|
-
# No namespace block found at all — insert at top level before final end
|
|
399
471
|
content.sub!(/^(\s*end\s*)\z/m, " #{resource_line}\n\\1")
|
|
400
472
|
end
|
|
401
473
|
end
|
|
@@ -403,9 +475,6 @@ module Belt
|
|
|
403
475
|
|
|
404
476
|
File.write(routes_file, content)
|
|
405
477
|
puts " update #{routes_file}"
|
|
406
|
-
|
|
407
|
-
# Also update route manifest
|
|
408
|
-
inject_route_manifest
|
|
409
478
|
end
|
|
410
479
|
|
|
411
480
|
def inject_route_manifest
|
|
@@ -414,15 +483,38 @@ module Belt
|
|
|
414
483
|
|
|
415
484
|
id_param = "#{@singular_name}_id"
|
|
416
485
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
"
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
486
|
+
# Determine if this is nested under a parent
|
|
487
|
+
parent_ref = @references.first
|
|
488
|
+
if parent_ref
|
|
489
|
+
parent_resource = Belt::Inflector.pluralize(parent_ref[:referenced_model])
|
|
490
|
+
parent_singular = parent_ref[:referenced_model]
|
|
491
|
+
parent_id_param = "#{parent_singular}_id"
|
|
492
|
+
path_prefix = "/#{parent_resource}/{#{parent_id_param}}"
|
|
493
|
+
|
|
494
|
+
new_routes = [
|
|
495
|
+
"{ verb: 'GET', path: '#{path_prefix}/#{@resource_name}', " \
|
|
496
|
+
"controller: '#{@resource_name}', action: 'index' }",
|
|
497
|
+
"{ verb: 'POST', path: '#{path_prefix}/#{@resource_name}', " \
|
|
498
|
+
"controller: '#{@resource_name}', action: 'create' }",
|
|
499
|
+
"{ verb: 'GET', path: '#{path_prefix}/#{@resource_name}/{#{id_param}}', " \
|
|
500
|
+
"controller: '#{@resource_name}', action: 'show' }",
|
|
501
|
+
"{ verb: 'PUT', path: '#{path_prefix}/#{@resource_name}/{#{id_param}}', " \
|
|
502
|
+
"controller: '#{@resource_name}', action: 'update' }",
|
|
503
|
+
"{ verb: 'DELETE', path: '#{path_prefix}/#{@resource_name}/{#{id_param}}', " \
|
|
504
|
+
"controller: '#{@resource_name}', action: 'destroy' }"
|
|
505
|
+
]
|
|
506
|
+
else
|
|
507
|
+
new_routes = [
|
|
508
|
+
"{ verb: 'GET', path: '/#{@resource_name}', controller: '#{@resource_name}', action: 'index' }",
|
|
509
|
+
"{ verb: 'POST', path: '/#{@resource_name}', controller: '#{@resource_name}', action: 'create' }",
|
|
510
|
+
"{ verb: 'GET', path: '/#{@resource_name}/{#{id_param}}', " \
|
|
511
|
+
"controller: '#{@resource_name}', action: 'show' }",
|
|
512
|
+
"{ verb: 'PUT', path: '/#{@resource_name}/{#{id_param}}', " \
|
|
513
|
+
"controller: '#{@resource_name}', action: 'update' }",
|
|
514
|
+
"{ verb: 'DELETE', path: '/#{@resource_name}/{#{id_param}}', " \
|
|
515
|
+
"controller: '#{@resource_name}', action: 'destroy' }"
|
|
516
|
+
]
|
|
517
|
+
end
|
|
426
518
|
|
|
427
519
|
existing_content = File.read(manifest_file)
|
|
428
520
|
constant = @app_name.upcase
|
|
@@ -456,7 +548,8 @@ module Belt
|
|
|
456
548
|
content = File.read(schema_file)
|
|
457
549
|
|
|
458
550
|
# Generate OpenAPI-style model block for API response contracts
|
|
459
|
-
response_fields = @
|
|
551
|
+
response_fields = @references.map { |ref| " string :#{ref[:referenced_model]}_id" }
|
|
552
|
+
response_fields += @regular_fields.map { |f| " #{schema_type_for(f[:type])} :#{f[:name]}" }
|
|
460
553
|
response_fields << ' string :created_at'
|
|
461
554
|
response_fields << ' string :updated_at'
|
|
462
555
|
|
|
@@ -488,10 +581,38 @@ module Belt
|
|
|
488
581
|
when 'boolean' then 'boolean'
|
|
489
582
|
when 'date' then 'date'
|
|
490
583
|
when 'datetime' then 'datetime'
|
|
584
|
+
when 'references' then 'string'
|
|
491
585
|
else 'string'
|
|
492
586
|
end
|
|
493
587
|
end
|
|
494
588
|
|
|
589
|
+
def inject_parent_associations
|
|
590
|
+
@references.each do |ref|
|
|
591
|
+
parent_model_path = "lambda/models/#{ref[:referenced_model]}.rb"
|
|
592
|
+
next unless File.exist?(parent_model_path)
|
|
593
|
+
|
|
594
|
+
content = File.read(parent_model_path)
|
|
595
|
+
has_many_line = " has_many :#{@resource_name}, foreign_key: '#{ref[:referenced_model]}_id', " \
|
|
596
|
+
"index: '#{Belt::Inflector.classify(ref[:referenced_model])}Index'"
|
|
597
|
+
|
|
598
|
+
next if content.include?("has_many :#{@resource_name}")
|
|
599
|
+
|
|
600
|
+
# Insert after the last belongs_to/has_many line, or after class declaration
|
|
601
|
+
if content.match?(/^\s*(has_many|belongs_to)\s+:/)
|
|
602
|
+
content.sub!(/^(\s*(?:has_many|belongs_to)\s+:[^\n]+\n)(?!.*(?:has_many|belongs_to))/m) do |match|
|
|
603
|
+
"#{match}#{has_many_line}\n"
|
|
604
|
+
end
|
|
605
|
+
elsif content.match?(/^class\s+\w+\s*<\s*\w+/)
|
|
606
|
+
content.sub!(/^(class\s+\w+\s*<\s*\w+.*\n)/) do |match|
|
|
607
|
+
"#{match}#{has_many_line}\n\n"
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
File.write(parent_model_path, content)
|
|
612
|
+
puts " update #{parent_model_path} (added has_many :#{@resource_name})"
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
|
|
495
616
|
def sync_tables
|
|
496
617
|
Belt::CLI::TablesCommand.sync_all_environments
|
|
497
618
|
end
|
data/lib/belt/version.rb
CHANGED
|
@@ -4,6 +4,58 @@ require_relative 'application_controller'
|
|
|
4
4
|
|
|
5
5
|
module <%= @module_name %>Controllers
|
|
6
6
|
class <%= @class_name %>sController < ApplicationController
|
|
7
|
+
<% if @references.any? -%>
|
|
8
|
+
<% parent = @references.first -%>
|
|
9
|
+
<% parent_resource = Belt::Inflector.pluralize(parent[:referenced_model]) -%>
|
|
10
|
+
<% parent_class = Belt::Inflector.classify(parent[:referenced_model]) -%>
|
|
11
|
+
# GET /<%= parent_resource %>/:id/<%= @resource_name %>
|
|
12
|
+
def index
|
|
13
|
+
@<%= @resource_name %> = <%= @class_name %>.where(<%= parent[:referenced_model] %>_id: params[:<%= parent[:referenced_model] %>_id], index: '<%= Belt::Inflector.classify(parent[:referenced_model]) %>Index')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# POST /<%= parent_resource %>/:id/<%= @resource_name %>
|
|
17
|
+
def create
|
|
18
|
+
@<%= @singular_name %> = <%= @class_name %>.new(<%= (["#{parent[:referenced_model]}_id: params[:#{parent[:referenced_model]}_id]"] + @regular_fields.map { |f| "#{f[:name]}: params[:#{f[:name]}]" }).join(', ') %>)
|
|
19
|
+
|
|
20
|
+
if @<%= @singular_name %>.save
|
|
21
|
+
response_status :created
|
|
22
|
+
else
|
|
23
|
+
error_response(@<%= @singular_name %>.errors.full_messages.join(', '), :unprocessable_entity)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# GET /<%= parent_resource %>/:id/<%= @resource_name %>/:<%= @singular_name %>_id
|
|
28
|
+
def show
|
|
29
|
+
@<%= @singular_name %> = <%= @class_name %>.find(params[:<%= @singular_name %>_id])
|
|
30
|
+
return error_response('<%= @class_name %> not found', :not_found) unless @<%= @singular_name %>
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# PUT /<%= parent_resource %>/:id/<%= @resource_name %>/:<%= @singular_name %>_id
|
|
34
|
+
def update
|
|
35
|
+
@<%= @singular_name %> = <%= @class_name %>.find(params[:<%= @singular_name %>_id])
|
|
36
|
+
return error_response('<%= @class_name %> not found', :not_found) unless @<%= @singular_name %>
|
|
37
|
+
|
|
38
|
+
attrs = {}
|
|
39
|
+
<% @regular_fields.each do |field| -%>
|
|
40
|
+
attrs[:<%= field[:name] %>] = params[:<%= field[:name] %>] if params.key?(:<%= field[:name] %>)
|
|
41
|
+
<% end -%>
|
|
42
|
+
|
|
43
|
+
if @<%= @singular_name %>.update(attrs)
|
|
44
|
+
# implicit response
|
|
45
|
+
else
|
|
46
|
+
error_response(@<%= @singular_name %>.errors.full_messages.join(', '), :unprocessable_entity)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# DELETE /<%= parent_resource %>/:id/<%= @resource_name %>/:<%= @singular_name %>_id
|
|
51
|
+
def destroy
|
|
52
|
+
<%= @singular_name %> = <%= @class_name %>.find(params[:<%= @singular_name %>_id])
|
|
53
|
+
return error_response('<%= @class_name %> not found', :not_found) unless <%= @singular_name %>
|
|
54
|
+
|
|
55
|
+
<%= @singular_name %>.destroy
|
|
56
|
+
head :no_content
|
|
57
|
+
end
|
|
58
|
+
<% else -%>
|
|
7
59
|
# GET /<%= @resource_name %>
|
|
8
60
|
def index
|
|
9
61
|
@<%= @resource_name %> = <%= @class_name %>.all
|
|
@@ -11,7 +63,7 @@ module <%= @module_name %>Controllers
|
|
|
11
63
|
|
|
12
64
|
# POST /<%= @resource_name %>
|
|
13
65
|
def create
|
|
14
|
-
@<%= @singular_name %> = <%= @class_name %>.new(<%= @
|
|
66
|
+
@<%= @singular_name %> = <%= @class_name %>.new(<%= @regular_fields.map { |f| "#{f[:name]}: params[:#{f[:name]}]" }.join(', ') %>)
|
|
15
67
|
|
|
16
68
|
if @<%= @singular_name %>.save
|
|
17
69
|
response_status :created
|
|
@@ -32,11 +84,13 @@ module <%= @module_name %>Controllers
|
|
|
32
84
|
return error_response('<%= @class_name %> not found', :not_found) unless @<%= @singular_name %>
|
|
33
85
|
|
|
34
86
|
attrs = {}
|
|
35
|
-
<% @
|
|
87
|
+
<% @regular_fields.each do |field| -%>
|
|
36
88
|
attrs[:<%= field[:name] %>] = params[:<%= field[:name] %>] if params.key?(:<%= field[:name] %>)
|
|
37
89
|
<% end -%>
|
|
38
90
|
|
|
39
|
-
|
|
91
|
+
if @<%= @singular_name %>.update(attrs)
|
|
92
|
+
# implicit response
|
|
93
|
+
else
|
|
40
94
|
error_response(@<%= @singular_name %>.errors.full_messages.join(', '), :unprocessable_entity)
|
|
41
95
|
end
|
|
42
96
|
end
|
|
@@ -49,5 +103,6 @@ module <%= @module_name %>Controllers
|
|
|
49
103
|
<%= @singular_name %>.destroy
|
|
50
104
|
head :no_content
|
|
51
105
|
end
|
|
106
|
+
<% end -%>
|
|
52
107
|
end
|
|
53
108
|
end
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
class <%= @class_name %> < ApplicationRecord
|
|
4
|
-
|
|
4
|
+
<% @references.each do |ref| -%>
|
|
5
|
+
belongs_to :<%= ref[:referenced_model] %>
|
|
6
|
+
<% end -%>
|
|
7
|
+
<% if @references.any? && (@regular_fields.any? || @references.any?) -%>
|
|
8
|
+
|
|
9
|
+
<% end -%>
|
|
10
|
+
<% @references.each do |ref| -%>
|
|
11
|
+
attr_accessor :<%= ref[:referenced_model] %>_id
|
|
12
|
+
<% end -%>
|
|
13
|
+
<% @regular_fields.each do |field| -%>
|
|
14
|
+
attr_accessor :<%= field[:name] %>
|
|
15
|
+
<% end -%>
|
|
5
16
|
end
|