Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate and Destroy nested actions via CLI #835

Merged
merged 2 commits into from Oct 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/hanami/cli/commands/destroy/action.rb
Expand Up @@ -19,7 +19,7 @@ class Action < Command
# @api private
def call(app:, action:, **options)
app = Utils::String.underscore(app)
controller, action = controller_and_action(action)
*controller, action = controller_and_action(action)
action_name = controller_and_action_name(controller, action)

context = Context.new(app: app, controller: controller, action: action, action_name: action_name, options: options)
Expand Down Expand Up @@ -57,7 +57,13 @@ def controller_and_action(name)
# @api private
def controller_and_action_name(controller, action)
# FIXME: extract this separator
[controller, action].join("#")
[namespaced_controller(controller), action].join("#")
end

# @since 1.1.0
# #api private
def namespaced_controller(controller)
controller.join("/")
end

# @since 1.1.0
Expand Down
27 changes: 21 additions & 6 deletions lib/hanami/cli/commands/generate/action.rb
Expand Up @@ -30,10 +30,11 @@ class Action < Command
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength
def call(app:, action:, **options)
controller, action = controller_and_action_name(action)
http_method = route_http_method(action, options)
context = Context.new(app: app, controller: controller, action: action, test: options.fetch(:test), http_method: http_method, options: options)
context = context.with(template: project.template(context))
*controller, action = controller_and_action_name(action)
classified_controller_name = classified_controller(controller)
http_method = route_http_method(action, options)
context = Context.new(app: app, controller: controller, classified_controller_name: classified_controller_name, action: action, test: options.fetch(:test), http_method: http_method, options: options)
context = context.with(template: project.template(context))

assert_valid_app!(context)
assert_valid_route_url!(context)
Expand Down Expand Up @@ -193,7 +194,7 @@ def route_url(context)
# @since 1.1.0
# @api private
def route_resourceful_url(context)
"/#{context.controller}#{route_resourceful_url_suffix(context)}"
"/#{namespaced_controller(context)}#{route_resourceful_url_suffix(context)}"
end

# @since 1.1.0
Expand All @@ -215,7 +216,21 @@ def route_resourceful_url_suffix(context)
# @since 1.1.0
# @api private
def route_endpoint(context)
"#{context.controller}##{context.action}"
"#{namespaced_controller(context)}##{context.action}"
end

# @since 1.1.0
# @api private
def classified_controller(controller)
controller.
map { |controller_name| Utils::String.new(controller_name).classify }.
join("::")
end

# @since 1.1.0
# @api private
def namespaced_controller(context)
context.controller.join("/")
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/hanami/cli/commands/generate/action/action.erb
@@ -1,4 +1,4 @@
module <%= app.classify %>::Controllers::<%= controller.classify %>
module <%= app.classify %>::Controllers::<%= classified_controller_name %>
class <%= action.classify %>
include <%= app.classify %>::Action

Expand Down
@@ -1,7 +1,7 @@
require_relative '../../../spec_helper'

describe <%= app.classify %>::Controllers::<%= controller.classify %>::<%= action.classify %> do
let(:action) { <%= app.classify %>::Controllers::<%= controller.classify %>::<%= action.classify %>.new }
describe <%= app.classify %>::Controllers::<%= classified_controller_name %>::<%= action.classify %> do
let(:action) { <%= app.classify %>::Controllers::<%= classified_controller_name %>::<%= action.classify %>.new }
let(:params) { Hash[] }

it 'is successful' do
Expand Down
@@ -1,4 +1,4 @@
RSpec.describe <%= app.classify %>::Controllers::<%= controller.classify %>::<%= action.classify %> do
RSpec.describe <%= app.classify %>::Controllers::<%= classified_controller_name %>::<%= action.classify %> do
let(:action) { described_class.new }
let(:params) { Hash[] }

Expand Down
@@ -1,4 +1,4 @@
module <%= app.classify %>::Controllers::<%= controller.classify %>
module <%= app.classify %>::Controllers::<%= classified_controller_name %>
class <%= action.classify %>
include <%= app.classify %>::Action

Expand Down
2 changes: 1 addition & 1 deletion lib/hanami/cli/commands/generate/action/view.erb
@@ -1,4 +1,4 @@
module <%= app.classify %>::Views::<%= controller.classify %>
module <%= app.classify %>::Views::<%= classified_controller_name %>
class <%= action.classify %>
include <%= app.classify %>::View
end
Expand Down
@@ -1,9 +1,9 @@
require_relative '../../../spec_helper'

describe <%= app.classify %>::Views::<%= controller.classify %>::<%= action.classify %> do
describe <%= app.classify %>::Views::<%= classified_controller_name %>::<%= action.classify %> do
let(:exposures) { Hash[foo: 'bar'] }
let(:template) { Hanami::View::Template.new('<%= template %>') }
let(:view) { <%= app.classify %>::Views::<%= controller.classify %>::<%= action.classify %>.new(template, exposures) }
let(:view) { <%= app.classify %>::Views::<%= classified_controller_name %>::<%= action.classify %>.new(template, exposures) }
let(:rendered) { view.render }

it 'exposes #foo' do
Expand Down
@@ -1,4 +1,4 @@
RSpec.describe <%= app.classify %>::Views::<%= controller.classify %>::<%= action.classify %> do
RSpec.describe <%= app.classify %>::Views::<%= classified_controller_name %>::<%= action.classify %> do
let(:exposures) { Hash[foo: 'bar'] }
let(:template) { Hanami::View::Template.new('<%= template %>') }
let(:view) { described_class.new(template, exposures) }
Expand Down
24 changes: 24 additions & 0 deletions spec/integration/cli/destroy/action_spec.rb
Expand Up @@ -24,6 +24,30 @@
end
end

it "destroys namespaced action" do
with_project do
generate "action web api/books#index"
output = [
"subtract apps/web/config/routes.rb",
"remove spec/web/views/api/books/index_spec.rb",
"remove apps/web/templates/api/books/index.html.erb",
"remove apps/web/views/api/books/index.rb",
"remove apps/web/controllers/api/books/index.rb",
"remove spec/web/controllers/api/books/index_spec.rb"
]

run_command "hanami destroy action web api/books#index", output

expect('spec/web/controllers/api/books/index_spec.rb').to_not be_an_existing_file
expect('apps/web/controllers/api/books/index.rb').to_not be_an_existing_file
expect('apps/web/views/api/books/index.rb').to_not be_an_existing_file
expect('apps/web/templates/api/books/index.html.erb').to_not be_an_existing_file
expect('spec/web/views/api/books/index_spec.rb').to_not be_an_existing_file

expect('apps/web/config/routes.rb').to_not have_file_content(%r{get '/api/books', to: 'api/books#index'})
end
end

it "destroys action without view" do
with_project do
generate "action web home#ping --skip-view --url=/ping"
Expand Down
45 changes: 45 additions & 0 deletions spec/integration/cli/generate/action_spec.rb
Expand Up @@ -45,6 +45,51 @@ class Index
end
end

it "generates namespaced action" do
with_project('bookshelf_generate_action') do
output = [
"create spec/web/controllers/api/authors/index_spec.rb",
"create apps/web/controllers/api/authors/index.rb",
"create apps/web/views/api/authors/index.rb",
"create apps/web/templates/api/authors/index.html.erb",
"create spec/web/views/api/authors/index_spec.rb",
"insert apps/web/config/routes.rb"
]

run_command "hanami generate action web api/authors#index", output

#
# apps/web/controllers/api/authors/index.rb
#
expect('apps/web/controllers/api/authors/index.rb').to have_file_content <<-END
module Web::Controllers::Api::Authors
class Index
include Web::Action

def call(params)
end
end
end
END

#
# apps/web/views/api/authors/index.rb
#
expect('apps/web/views/api/authors/index.rb').to have_file_content <<-END
module Web::Views::Api::Authors
class Index
include Web::View
end
end
END

#
# apps/web/config/routes.rb
#
expect('apps/web/config/routes.rb').to have_file_content(%r{get '/api/authors', to: 'api/authors#index'})
end
end

it "fails with missing arguments" do
with_project('bookshelf_generate_action_without_args') do
output = <<-OUT
Expand Down