/
schema.cr
130 lines (103 loc) · 4.2 KB
/
schema.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
require "./schema/**"
module Marten
module CLI
abstract class Generator
# Allows to generate schemas.
class Schema < Generator
help "Generate a schema."
footer_description(
<<-FOOTER_DESCRIPTION
Description:
Generates a schema with the specified name and field definitions. The schema will be
generated in the app specified by the --app option or in the main app if no app is
specified.
Field definitions can be specified using the following formats:
name:type
name:type:modifier:modifier
Where `name` is the name of the field and `type` is the type of the field.
`modifier` is an optional field modifier. Field modifiers are used to specify additional
(but non-mandatory) field options. For example: `name:string:optional` will produce a
string field whose `required` option is set to `false`.
Examples:
Generate a schema in the main app:
$ marten gen schema ArticleSchema title:string body:string
Generate a schema in the blog app:
$ marten gen schema ArticleSchema title:string body:string --app admin
Generate a schema with a parent class:
$ marten gen schema ArticleSchema title:string body:string --parent BaseSchema
FOOTER_DESCRIPTION
)
@app_label : String? = nil
@schema_arguments = [] of String
@schema_name = ""
@no_timestamps = false
@parent : String? = nil
def setup
command.on_argument(:name, "Name of the schema to generate") { |v| @schema_name = v }
command.on_unknown_argument(:field_definitions, "Field definitions of the schema to generate") do |v|
@schema_arguments << v
end
command.on_option_with_arg(
:app,
arg: "app",
description: "Target app where the schema should be created"
) do |v|
@app_label = v
end
command.on_option_with_arg(
:parent,
arg: "parent",
description: "Parent class name for the generated schema"
) do |v|
@parent = v
end
end
def run : Nil
# Fetch the specified app or default to the main one.
app_config = (l = app_label).nil? ? Marten.apps.main : Marten.apps.get(l)
# Validate the schema name.
if schema_name.empty?
command.print_error_and_exit("A schema name must be specified")
elsif !schema_name.matches?(/^[A-Z]/)
command.print_error_and_exit("The schema name must be CamelCase")
end
# Add the "Schema" suffix if missing, which is a best practice.
unless schema_name.ends_with?("Schema")
self.schema_name += "Schema"
end
# Extract field definitions.
begin
field_definitions = @schema_arguments.map { |a| FieldDefinition.from_argument(a) }
rescue ex : ArgumentError
command.print_error_and_exit(ex.message)
end
# Generate the schema.
print_generation_message(app_config, schema_name)
context = Context.new(
app_config: app_config,
name: schema_name,
field_definitions: field_definitions,
parent: parent,
)
create_app_files(app_config, Templates.app_files(context))
rescue ex : Apps::Errors::AppNotFound
command.print_error_and_exit(ex.message)
end
private getter app_label
private getter schema_name
private getter parent
private getter? no_timestamps
private setter schema_name
private def print_generation_message(app_config, schema_name)
if app_config.main?
command.print("Generating schema #{command.style(schema_name, mode: :bold)}...\n\n")
else
command.print(
"Generating schema #{command.style(schema_name, mode: :bold)} in app " \
"#{command.style(app_config.label, mode: :bold)}...\n\n")
end
end
end
end
end
end