hanami-cli 2.2.0.beta2 → 2.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d62ed9aeff86f86693ffdf5acafb274e6e97a535a177bf46131c8c33141fc0e9
4
- data.tar.gz: 86da7248a20712451a83b8e5167870e34fd508f2e5f41a107d9bf3a4dea1d376
3
+ metadata.gz: e6ace925a2c5186088911d5df3d309d72ee0359e4691f70199c3f53f99db0fc3
4
+ data.tar.gz: 7fd1959ffcaf64ebc0b95a839a68ed1f052370ed6a7043863068087a1893489d
5
5
  SHA512:
6
- metadata.gz: affe042dfe0daf2dc93e1252b06d2d51dd5ea605c1287ad2500371bed6ee98e902cf9d19667458f86edadabb671f923b986bcd2a76a0e7d8821f4e0b9af6ecf6
7
- data.tar.gz: b1a097c66c10495ef31fd0783083d542ac6e7a5be7ab94f11b9e1a0d68dc865e04d6f970e08b88d33dd3939b47736cc8893989cb037d070d3c5d2ff86d35ccad
6
+ metadata.gz: 6133308e48b0623616598a23d1b0fe079b08f31e991791e6ae76867441eec1d25427deef5755e445fd8c3f2f2e294c143eeb58272e278721897ab290c48024cb
7
+ data.tar.gz: '068ad2b891fa99e16ff6c0be6931e98d708ce3c7bab67e0dd3fd354ef00f4bdb110ad84007592ccc98e65ebbe643f7e4420b0406f8b0b76500968a5571718398'
data/CHANGELOG.md CHANGED
@@ -2,6 +2,29 @@
2
2
 
3
3
  Hanami Command Line Interface
4
4
 
5
+ ## v2.2.0.rc1 - 2024-10-29
6
+
7
+ ### Added
8
+
9
+ - [Tim Riley, François Beausoleil] Generate a `config/db/seeds.rb` file in new apps (#255, #256)
10
+
11
+ ### Changed
12
+
13
+ - [Tim Riley] Add `--env` and `-e` options to all app commands, for setting the Hanami env (#246)
14
+ - [Tim Riley] Keep test database in sync by applying `hanami db` commands to both development and test databases when invoked in development environment (#247)
15
+ - [Kyle Plump] Add `--skip-route` flag to `generate action` and `generate slice` commands (#227)
16
+ - [Tim Riley] Include a `change do` block in generated migrations (#254)
17
+ - [Tim Riley] Generate MySQL database URL in `.env` that works with standard Homebrew MySQL installation (#249)
18
+ - [Tim Riley, Adam Lassek] Remove ROM extension boilerplate in operations generated by `hanami new` and `generate operation` (this is now applied automatically) (#240, #252)
19
+ - [François Beausoleil] Print a warning when running `db seed` but expected seeds files could not be found (#256)
20
+ - [Seb Wilgosz] Only register `generate` subcommands if the relevant gems are bundled (#242)
21
+ - [Anderson Saunders] When both IRB and pry are loaded, use IRB as the default engine for `hanami console` (#182)
22
+
23
+ ### Fixed
24
+
25
+ - [Tim Riley] Fix error dumping structure when there are no migrations (#244)
26
+ - [Tim Riley] Stop erroneous misconfigured DB warnings from `hanami db` commands when a database is configured once but shared across sliaces (#253)
27
+
5
28
  ## v2.2.0.beta2 - 2024-09-25
6
29
 
7
30
  ### Added
@@ -18,8 +18,8 @@ module Hanami
18
18
  # @api private
19
19
  ACTION_SEPARATOR = "." # TODO: rename to container key separator
20
20
 
21
- # Overloads {Hanami::CLI::Commands::App::Command#call} to ensure an appropriate `HANAMI_ENV`
22
- # environment variable is set.
21
+ # Overloads {Hanami::CLI::Commands::App::Command#call} to ensure an appropriate
22
+ # `HANAMI_ENV` environment variable is set.
23
23
  #
24
24
  # Uses an `--env` option if provided, then falls back to an already-set `HANAMI_ENV`
25
25
  # environment variable, and defaults to "development" in the absence of both.
@@ -27,6 +27,12 @@ module Hanami
27
27
  # @since 2.0.0
28
28
  # @api private
29
29
  module Environment
30
+ # @since 2.2.0
31
+ # @api private
32
+ def self.prepended(klass)
33
+ klass.option :env, desc: "App environment (development, test, production)", aliases: ["e"]
34
+ end
35
+
30
36
  # @since 2.0.0
31
37
  # @api private
32
38
  def call(*args, **opts)
@@ -37,7 +43,7 @@ module Hanami
37
43
  ENV["HANAMI_ENV"] = hanami_env
38
44
  Hanami::Env.load
39
45
 
40
- super(*args, **opts)
46
+ super
41
47
  end
42
48
  end
43
49
 
@@ -51,11 +51,7 @@ module Hanami
51
51
  private
52
52
 
53
53
  def resolve_engine(engine, opts)
54
- if engine
55
- ENGINES.fetch(engine).(app, opts)
56
- else
57
- ENGINES.map { |(_, loader)| loader.(app, opts) }.compact.first
58
- end
54
+ ENGINES.fetch(engine, ENGINES[DEFAULT_ENGINE]).call(app, opts)
59
55
  end
60
56
  end
61
57
  end
@@ -17,15 +17,23 @@ module Hanami
17
17
  option :app, required: false, type: :flag, default: false, desc: "Use app database"
18
18
  option :slice, required: false, desc: "Use database for slice"
19
19
 
20
+ # @api private
20
21
  attr_reader :system_call
21
22
 
23
+ # @api private
24
+ attr_reader :test_env_executor
25
+
22
26
  def initialize(
23
27
  out:, err:,
24
28
  system_call: SystemCall.new,
29
+ test_env_executor: InteractiveSystemCall.new(out: out, err: err),
30
+ nested_command: false,
25
31
  **opts
26
32
  )
27
33
  super(out: out, err: err, **opts)
28
34
  @system_call = system_call
35
+ @test_env_executor = test_env_executor
36
+ @nested_command = nested_command
29
37
  end
30
38
 
31
39
  def run_command(klass, ...)
@@ -34,9 +42,15 @@ module Hanami
34
42
  inflector: inflector,
35
43
  fs: fs,
36
44
  system_call: system_call,
45
+ test_env_executor: test_env_executor,
46
+ nested_command: true,
37
47
  ).call(...)
38
48
  end
39
49
 
50
+ def nested_command?
51
+ @nested_command
52
+ end
53
+
40
54
  private
41
55
 
42
56
  def databases(app: false, slice: nil, gateway: nil)
@@ -77,7 +91,7 @@ module Hanami
77
91
  end
78
92
  end
79
93
 
80
- def all_databases # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
94
+ def all_databases # rubocop:disable Metrics/AbcSize
81
95
  slices = [app] + app.slices.with_nested
82
96
 
83
97
  slice_gateways_by_database_url = slices.each_with_object({}) { |slice, hsh|
@@ -92,7 +106,9 @@ module Hanami
92
106
 
93
107
  slice_gateways_by_database_url.each_with_object([]) { |(url, slice_gateways), arr|
94
108
  slice_gateways_with_config = slice_gateways.select {
95
- _1[:slice].root.join("config", "db").directory?
109
+ migrate_dir = _1[:gateway] == :default ? "migrate" : "#{_1[:gateway]}_migrate"
110
+
111
+ _1[:slice].root.join("config", "db", migrate_dir).directory?
96
112
  }
97
113
 
98
114
  db_slice_gateway = slice_gateways_with_config.first || slice_gateways.first
@@ -102,7 +118,7 @@ module Hanami
102
118
  system_call: system_call
103
119
  )
104
120
 
105
- warn_on_misconfigured_database database, slice_gateways.map { _1.fetch(:slice) }
121
+ warn_on_misconfigured_database database, slice_gateways_with_config.map { _1.fetch(:slice) }
106
122
 
107
123
  arr << database
108
124
  }
@@ -126,7 +142,7 @@ module Hanami
126
142
 
127
143
  #{slices.map { "- " + _1.root.relative_path_from(_1.app.root).join("config", "db").to_s }.join("\n")}
128
144
 
129
- Migrating database using #{database.slice.slice_name.to_s.inspect} slice only.
145
+ Using config in #{database.slice.slice_name.to_s.inspect} slice only.
130
146
 
131
147
  STR
132
148
  elsif !database.db_config_dir?
@@ -140,6 +156,66 @@ module Hanami
140
156
  STR
141
157
  end
142
158
  end
159
+
160
+ # Invokes the currently executing `hanami` CLI command again, but with any `--env` args
161
+ # removed and the `HANAMI_ENV=test` env var set.
162
+ #
163
+ # This is called by certain `db` commands only, and runs only if the Hanami env is
164
+ # `:development`. This behavior important to streamline the local development
165
+ # experience, making sure that the test databases are kept in sync with operations run
166
+ # on the development databases.
167
+ #
168
+ # Spawning an entirely new process to change the env is a compromise approach until we
169
+ # can have an API for reinitializing the DB subsystem in-process with a different env.
170
+ def re_run_development_command_in_test
171
+ # Only invoke a new process if we've been called as `hanami`. This avoids awkward
172
+ # failures when testing commands via RSpec, for which the $0 is "/full/path/to/rspec".
173
+ return unless $0.end_with?("hanami")
174
+
175
+ # If this special env key is set, then a re-run has already been invoked. This would
176
+ # mean the current command is actually a nested command run by another db command. In
177
+ # this case, don't trigger a re-runs, because one is already in process.
178
+ return if nested_command?
179
+
180
+ # Re-runs in test are for development-env commands only.
181
+ return unless Hanami.env == :development
182
+
183
+ cmd = $0
184
+ cmd = "bundle exec #{cmd}" if ENV.key?("BUNDLE_BIN_PATH")
185
+
186
+ test_env_executor.call(
187
+ cmd, *argv_without_env_args,
188
+ env: {
189
+ "HANAMI_ENV" => "test",
190
+ "HANAMI_CLI_DB_COMMAND_RE_RUN_IN_TEST" => "true"
191
+ }
192
+ )
193
+ end
194
+
195
+ def re_running_in_test?
196
+ ENV.key?("HANAMI_CLI_DB_COMMAND_RE_RUN_IN_TEST")
197
+ end
198
+
199
+ # Returns the `ARGV` with every option argument included, but the `-e` or `--env` args
200
+ # removed.
201
+ def argv_without_env_args
202
+ new_argv = ARGV.dup
203
+
204
+ env_arg_index = new_argv.index {
205
+ _1 == "-e" || _1 == "--env" || _1.start_with?("-e=") || _1.start_with?("--env=")
206
+ }
207
+
208
+ if env_arg_index
209
+ # Remove the env argument
210
+ env_arg = new_argv.delete_at(env_arg_index)
211
+
212
+ # If the env argument is not in combined form ("--env foo" rather than "--env=foo"),
213
+ # then remove the following argument too
214
+ new_argv.delete_at(env_arg_index) if ["-e", "--env"].include?(env_arg)
215
+ end
216
+
217
+ new_argv
218
+ end
143
219
  end
144
220
  end
145
221
  end
@@ -29,6 +29,8 @@ module Hanami
29
29
  exit_codes.each do |code|
30
30
  break command_exit.(code) if code > 0
31
31
  end
32
+
33
+ re_run_development_command_in_test
32
34
  end
33
35
  end
34
36
  end
@@ -29,6 +29,8 @@ module Hanami
29
29
  exit_codes.each do |code|
30
30
  break exit code if code > 0
31
31
  end
32
+
33
+ re_run_development_command_in_test
32
34
  end
33
35
  end
34
36
  end
@@ -25,7 +25,16 @@ module Hanami
25
25
  end
26
26
  end
27
27
 
28
- run_command(Structure::Dump, app: app, slice: slice, gateway: gateway, command_exit: command_exit) if dump
28
+ # Only dump for the initial command, not a re-run of the command in test env
29
+ if dump && !re_running_in_test?
30
+ run_command(
31
+ Structure::Dump,
32
+ app: app, slice: slice, gateway: gateway,
33
+ command_exit: command_exit
34
+ )
35
+ end
36
+
37
+ re_run_development_command_in_test
29
38
  end
30
39
 
31
40
  private
@@ -58,7 +58,9 @@ module Hanami
58
58
  end
59
59
 
60
60
  # Finally, load the seeds for the slice overall, which is a once-per-slice operation.
61
- run_command(DB::Seed, app: app, slice: slice)
61
+ run_command(DB::Seed, app: app, slice: slice) unless re_running_in_test?
62
+
63
+ re_run_development_command_in_test
62
64
  end
63
65
  end
64
66
  end
@@ -25,7 +25,11 @@ module Hanami
25
25
  next if seeded_slices.include?(database.slice)
26
26
 
27
27
  seeds_path = database.slice.root.join(SEEDS_PATH)
28
- next unless seeds_path.file?
28
+
29
+ unless seeds_path.file?
30
+ out.puts "no seeds found at #{seeds_path.relative_path_from(database.slice.app.root)}"
31
+ next
32
+ end
29
33
 
30
34
  relative_seeds_path = seeds_path.relative_path_from(database.slice.app.root)
31
35
  measure "seed data loaded from #{relative_seeds_path}" do
@@ -31,8 +31,11 @@ module Hanami
31
31
  throw :dump_failed, false
32
32
  end
33
33
 
34
- File.open(database.structure_file, "a") do |f|
35
- f.puts "#{database.schema_migrations_sql_dump}\n"
34
+ migrations_sql = database.schema_migrations_sql_dump
35
+ if migrations_sql
36
+ File.open(database.structure_file, "a") do |f|
37
+ f.puts "#{migrations_sql}\n"
38
+ end
36
39
  end
37
40
 
38
41
  true
@@ -44,6 +44,8 @@ module Hanami
44
44
  exit_codes.each do |code|
45
45
  break command_exit.(code) if code > 0
46
46
  end
47
+
48
+ re_run_development_command_in_test
47
49
  end
48
50
  end
49
51
  end
@@ -55,11 +55,14 @@ module Hanami
55
55
  end
56
56
 
57
57
  def schema_migrations_sql_dump
58
- search_path = slice["db.gateway"].connection
58
+ migrations_sql = super
59
+ return unless migrations_sql
60
+
61
+ search_path = gateway.connection
59
62
  .fetch("SHOW search_path").to_a.first
60
63
  .fetch(:search_path)
61
64
 
62
- +"SET search_path TO #{search_path};\n\n" << super
65
+ +"SET search_path TO #{search_path};\n\n" << migrations_sql
63
66
  end
64
67
 
65
68
  private
@@ -25,6 +25,9 @@ module Hanami
25
25
  DEFAULT_SKIP_TESTS = false
26
26
  private_constant :DEFAULT_SKIP_TESTS
27
27
 
28
+ DEFAULT_SKIP_ROUTE = false
29
+ private_constant :DEFAULT_SKIP_ROUTE
30
+
28
31
  argument :name, required: true, desc: "Action name"
29
32
  option :url, required: false, type: :string, desc: "Action URL"
30
33
  option :http, required: false, type: :string, desc: "Action HTTP method"
@@ -41,6 +44,12 @@ module Hanami
41
44
  type: :flag,
42
45
  default: DEFAULT_SKIP_TESTS,
43
46
  desc: "Skip test generation"
47
+ option \
48
+ :skip_route,
49
+ required: false,
50
+ type: :flag,
51
+ default: DEFAULT_SKIP_ROUTE,
52
+ desc: "Skip route generation"
44
53
  option :slice, required: false, desc: "Slice name"
45
54
 
46
55
  # rubocop:disable Layout/LineLength
@@ -83,7 +92,8 @@ module Hanami
83
92
  http: nil,
84
93
  format: DEFAULT_FORMAT,
85
94
  skip_view: DEFAULT_SKIP_VIEW,
86
- skip_tests: DEFAULT_SKIP_TESTS, # rubocop:disable Lint/UnusedMethodArgument
95
+ skip_tests: DEFAULT_SKIP_TESTS, # rubocop:disable Lint/UnusedMethodArgument,
96
+ skip_route: DEFAULT_SKIP_ROUTE,
87
97
  slice: nil,
88
98
  context: nil,
89
99
  **
@@ -96,7 +106,7 @@ module Hanami
96
106
  raise InvalidActionNameError.new(name)
97
107
  end
98
108
 
99
- generator.call(app.namespace, controller, action, url, http, format, skip_view, slice, context: context)
109
+ generator.call(app.namespace, controller, action, url, http, format, skip_view, skip_route, slice, context: context)
100
110
  end
101
111
 
102
112
  # rubocop:enable Metrics/ParameterLists
@@ -21,13 +21,25 @@ module Hanami
21
21
  SKIP_DB_DEFAULT = false
22
22
  private_constant :SKIP_DB_DEFAULT
23
23
 
24
+ # @since 2.2.0
25
+ # @api private
26
+ DEFAULT_SKIP_ROUTE = false
27
+ private_constant :DEFAULT_SKIP_ROUTE
28
+
24
29
  # @since 2.2.0
25
30
  # @api private
26
31
  option :skip_db,
27
- type: :boolean,
32
+ type: :flag,
28
33
  required: false,
29
34
  default: SKIP_DB_DEFAULT,
30
35
  desc: "Skip database"
36
+ # @since 2.2.0
37
+ # @api private
38
+ option :skip_route,
39
+ type: :flag,
40
+ required: false,
41
+ default: DEFAULT_SKIP_ROUTE,
42
+ desc: "Skip route generation"
31
43
 
32
44
  example [
33
45
  "admin # Admin slice (/admin URL prefix)",
@@ -50,7 +62,8 @@ module Hanami
50
62
  def call(
51
63
  name:,
52
64
  url: nil,
53
- skip_db: SKIP_DB_DEFAULT
65
+ skip_db: SKIP_DB_DEFAULT,
66
+ skip_route: DEFAULT_SKIP_ROUTE
54
67
  )
55
68
  require "hanami/setup"
56
69
 
@@ -58,7 +71,7 @@ module Hanami
58
71
  name = inflector.underscore(Shellwords.shellescape(name))
59
72
  url = sanitize_url_prefix(name, url)
60
73
 
61
- generator.call(app, name, url, skip_db: skip_db)
74
+ generator.call(app, name, url, skip_db: skip_db, skip_route: skip_route)
62
75
  end
63
76
 
64
77
  private
@@ -41,16 +41,28 @@ module Hanami
41
41
  end
42
42
 
43
43
  register "generate", aliases: ["g"] do |prefix|
44
- prefix.register "action", Generate::Action
45
- prefix.register "component", Generate::Component
46
- prefix.register "migration", Generate::Migration
47
- prefix.register "operation", Generate::Operation
48
- prefix.register "part", Generate::Part
49
- prefix.register "relation", Generate::Relation
50
- prefix.register "repo", Generate::Repo
51
44
  prefix.register "slice", Generate::Slice
52
- prefix.register "struct", Generate::Struct
53
- prefix.register "view", Generate::View
45
+ prefix.register "component", Generate::Component
46
+
47
+ if Hanami.bundled?("hanami-controller")
48
+ prefix.register "action", Generate::Action
49
+ end
50
+
51
+ if Hanami.bundled?("dry-operation")
52
+ prefix.register "operation", Generate::Operation
53
+ end
54
+
55
+ if Hanami.bundled?("hanami-view")
56
+ prefix.register "view", Generate::View
57
+ prefix.register "part", Generate::Part
58
+ end
59
+
60
+ if Hanami.bundled?("hanami-db")
61
+ prefix.register "migration", Generate::Migration
62
+ prefix.register "relation", Generate::Relation
63
+ prefix.register "repo", Generate::Repo
64
+ prefix.register "struct", Generate::Struct
65
+ end
54
66
  end
55
67
  end
56
68
  end
@@ -21,12 +21,12 @@ module Hanami
21
21
 
22
22
  # @since 2.0.0
23
23
  # @api private
24
- def call(app, controller, action, url, http, format, skip_view, slice, context: nil)
24
+ def call(app, controller, action, url, http, format, skip_view, skip_route, slice, context: nil)
25
25
  context ||= ActionContext.new(inflector, app, slice, controller, action)
26
26
  if slice
27
- generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
27
+ generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context)
28
28
  else
29
- generate_for_app(controller, action, url, http, format, skip_view, context)
29
+ generate_for_app(controller, action, url, http, format, skip_view, skip_route, context)
30
30
  end
31
31
  end
32
32
 
@@ -72,15 +72,17 @@ module Hanami
72
72
  attr_reader :inflector
73
73
 
74
74
  # rubocop:disable Metrics/AbcSize
75
- def generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
75
+ def generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context)
76
76
  slice_directory = fs.join("slices", slice)
77
77
  raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
78
78
 
79
- fs.inject_line_at_block_bottom(
80
- fs.join("config", "routes.rb"),
81
- slice_matcher(slice),
82
- route(controller, action, url, http)
83
- )
79
+ if generate_route?(skip_route)
80
+ fs.inject_line_at_block_bottom(
81
+ fs.join("config", "routes.rb"),
82
+ slice_matcher(slice),
83
+ route(controller, action, url, http)
84
+ )
85
+ end
84
86
 
85
87
  fs.mkdir(directory = fs.join(slice_directory, "actions", controller))
86
88
  fs.write(fs.join(directory, "#{action}.rb"), t("slice_action.erb", context))
@@ -95,12 +97,14 @@ module Hanami
95
97
  end
96
98
  end
97
99
 
98
- def generate_for_app(controller, action, url, http, format, skip_view, context)
99
- fs.inject_line_at_class_bottom(
100
- fs.join("config", "routes.rb"),
101
- "class Routes",
102
- route(controller, action, url, http)
103
- )
100
+ def generate_for_app(controller, action, url, http, format, skip_view, skip_route, context)
101
+ if generate_route?(skip_route)
102
+ fs.inject_line_at_class_bottom(
103
+ fs.join("config", "routes.rb"),
104
+ "class Routes",
105
+ route(controller, action, url, http)
106
+ )
107
+ end
104
108
 
105
109
  fs.mkdir(directory = fs.join("app", "actions", controller))
106
110
  fs.write(fs.join(directory, "#{action}.rb"), t("action.erb", context))
@@ -137,6 +141,14 @@ module Hanami
137
141
  true
138
142
  end
139
143
 
144
+ # @api private
145
+ # @since 2.2.0
146
+ def generate_route?(skip_route)
147
+ return false if skip_route
148
+
149
+ true
150
+ end
151
+
140
152
  # @api private
141
153
  # @since 2.1.0
142
154
  def generate_restful_view?(view, directory)
@@ -56,6 +56,8 @@ module Hanami
56
56
  # Add your migration here.
57
57
  #
58
58
  # See https://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html for details.
59
+ change do
60
+ end
59
61
  end
60
62
  RUBY
61
63
  private_constant :FILE_CONTENTS
@@ -22,9 +22,11 @@ module Hanami
22
22
  def call(app, slice, url, context: nil, **opts)
23
23
  context ||= SliceContext.new(inflector, app, slice, url, **opts)
24
24
 
25
- fs.inject_line_at_class_bottom(
26
- fs.join("config", "routes.rb"), "class Routes", t("routes.erb", context).chomp
27
- )
25
+ if context.generate_route?
26
+ fs.inject_line_at_class_bottom(
27
+ fs.join("config", "routes.rb"), "class Routes", t("routes.erb", context).chomp
28
+ )
29
+ end
28
30
 
29
31
  fs.mkdir(directory = "slices/#{slice}")
30
32
 
@@ -54,6 +54,12 @@ module Hanami
54
54
  !options.fetch(:skip_db, false)
55
55
  end
56
56
 
57
+ # @since 2.2.0
58
+ # @api private
59
+ def generate_route?
60
+ !options.fetch(:skip_route, false)
61
+ end
62
+
57
63
  private
58
64
 
59
65
  attr_reader :slice
@@ -112,7 +112,7 @@ module Hanami
112
112
  elsif generate_postgres?
113
113
  "postgres://localhost/#{app}"
114
114
  elsif generate_mysql?
115
- "mysql2://localhost/#{app}"
115
+ "mysql2://root@localhost/#{app}"
116
116
  else
117
117
  raise "Unknown database option: #{database_option}"
118
118
  end
@@ -5,9 +5,5 @@ require "dry/operation"
5
5
 
6
6
  module <%= camelized_app_name %>
7
7
  class Operation < Dry::Operation
8
- <%- if generate_db? -%>
9
- # Provide `transaction do ... end` method for database transactions
10
- include Dry::Operation::Extensions::ROM
11
- <%- end -%>
12
8
  end
13
9
  end
@@ -0,0 +1,15 @@
1
+ # This seeds file should create the database records required to run the app.
2
+ #
3
+ # The code should be idempotent so that it can be executed at any time.
4
+ #
5
+ # To load the seeds, run `hanami db seed`. Seeds are also loaded as part of `hanami db prepare`.
6
+
7
+ # For example, if you have appropriate repos available:
8
+ #
9
+ # category_repo = Hanami.app["repos.category_repo"]
10
+ # category_repo.create(title: "General")
11
+ #
12
+ # Alternatively, you can use relations directly:
13
+ #
14
+ # categories = Hanami.app["relations.categories"]
15
+ # categories.insert(title: "General")
@@ -78,10 +78,11 @@ module Hanami
78
78
  fs.write("app/db/struct.rb", t("struct.erb", context))
79
79
  fs.write("app/structs/.keep", t("keep.erb", context))
80
80
 
81
- fs.write("config/db/migrate/.keep" , t("keep.erb", context))
81
+ fs.write("config/db/seeds.rb", t("seeds.erb", context))
82
+ fs.write("config/db/migrate/.keep", t("keep.erb", context))
82
83
 
83
84
  if context.generate_sqlite?
84
- fs.write("db/.keep" , t("keep.erb", context))
85
+ fs.write("db/.keep", t("keep.erb", context))
85
86
  end
86
87
  end
87
88
 
@@ -24,8 +24,8 @@ module Hanami
24
24
  AUTO_INDENT: true,
25
25
  PROMPT_I: "#{prompt}> ",
26
26
  PROMPT_N: "#{prompt}> ",
27
- PROMPT_S: "#{prompt} %l> ",
28
- PROMPT_C: "#{prompt} ?> ",
27
+ PROMPT_S: "#{prompt}%l ",
28
+ PROMPT_C: "#{prompt}* ",
29
29
  RETURN: "=> %s\n"
30
30
  }
31
31
 
@@ -6,6 +6,6 @@ module Hanami
6
6
  #
7
7
  # @api public
8
8
  # @since 2.0.0
9
- VERSION = "2.2.0.beta2"
9
+ VERSION = "2.2.0.rc1"
10
10
  end
11
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0.beta2
4
+ version: 2.2.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-25 00:00:00.000000000 Z
11
+ date: 2024-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -308,6 +308,7 @@ files:
308
308
  - lib/hanami/cli/generators/gem/app/relation.erb
309
309
  - lib/hanami/cli/generators/gem/app/repo.erb
310
310
  - lib/hanami/cli/generators/gem/app/routes.erb
311
+ - lib/hanami/cli/generators/gem/app/seeds.erb
311
312
  - lib/hanami/cli/generators/gem/app/settings.erb
312
313
  - lib/hanami/cli/generators/gem/app/struct.erb
313
314
  - lib/hanami/cli/generators/gem/app/types.erb
@@ -353,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
354
  - !ruby/object:Gem::Version
354
355
  version: '0'
355
356
  requirements: []
356
- rubygems_version: 3.5.16
357
+ rubygems_version: 3.5.22
357
358
  signing_key:
358
359
  specification_version: 4
359
360
  summary: Hanami CLI