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

use Thor option parser in server commands parse #26977

Merged
merged 2 commits into from Dec 29, 2016
Merged

Conversation

y-yagi
Copy link
Member

@y-yagi y-yagi commented Nov 5, 2016

Summary

In master, when start rails server with arguments, it will fail.

$ ./bin/rails -v
Rails 5.1.0.alpha
$ ./bin/rails s -p 3001
/home/yaginuma/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/thor-0.19.1/lib/thor/base.rb:483:in `handle_argument_error': ERROR: "rails server" was called with arguments ["-p", "3001"] (Thor::InvocationError)
Usage: "bin/rails server [options]"
	from /home/yaginuma/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/thor-0.19.1/lib/thor/command.rb:34:in `rescue in run'
	from /home/yaginuma/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/thor-0.19.1/lib/thor/command.rb:21:in `run'
	from /home/yaginuma/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/thor-0.19.1/lib/thor/invocation.rb:126:in `invoke_command'
	from /home/yaginuma/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/thor-0.19.1/lib/thor.rb:359:in `dispatch'
	from /home/yaginuma/program/rails/master_y_yagi/rails/railties/lib/rails/command/base.rb:61:in `perform'
	from /home/yaginuma/program/rails/master_y_yagi/rails/railties/lib/rails/command.rb:34:in `invoke'
	from /home/yaginuma/program/rails/master_y_yagi/rails/railties/lib/rails/commands.rb:16:in `<top (required)>'
	from ./bin/rails:9:in `require' 

The ServerCommand inherits Thor, but it does not use Thor is the
parse of the argument.
Therefore, if leave the argument of Thor as it is, it becomes an error by the
argument checking of Thor.
To avoid it, to clear the argument of Thor.

Fixes #26964

@rails-bot
Copy link

r? @pixeltrix

(@rails-bot has picked a reviewer for you, use r? to override)

@y-yagi
Copy link
Member Author

y-yagi commented Nov 5, 2016

r? @kaspth

@rails-bot rails-bot assigned kaspth and unassigned pixeltrix Nov 5, 2016
@rafaelfranca
Copy link
Member

Can we use the Thor option parser instead of reimplementing it?

@y-yagi
Copy link
Member Author

y-yagi commented Nov 6, 2016

If I am not mistaken, it is possible. I will try.

@y-yagi y-yagi force-pushed the fix_26964 branch 2 times, most recently from 794b098 to 4597b09 Compare November 7, 2016 13:20
@arthurnn
Copy link
Member

arthurnn commented Nov 7, 2016

r? @rafaelfranca

@rails-bot rails-bot assigned rafaelfranca and unassigned kaspth Nov 7, 2016
def initialize(*)
super
def initialize(options = nil)
super(options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not only super work here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. See my comment about Rack::Server interop.

DEFAULT_PID_PATH = File.expand_path("tmp/pids/server.pid").freeze

class_option :port, aliases: "-p", type: :numeric,
desc: "Runs Rails on the specified port.", banner: :port
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the default in the description?

class_option :port, aliases: "-p", type: :numeric,
desc: "Runs Rails on the specified port.", banner: :port
class_option :binding, aliases: "-b", type: :string,
desc: "Binds Rails to the specified IP.", banner: :IP
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing about the default

private

def parse_arguments(args)
Rails::Command::ServerCommand.class_eval do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can asset those things only initializing a command object. Rails::Command::ServerCommand.new should expose everything you can.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, I had to do something similar for the other commands. But if we can make it happen, great 👍

end

def environment
options[:environment] || (ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a Rails::Command.environment method for this.

end

def restart_command
"bin/rails server #{ARGV.join(' ')}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the command infrastructure guarantees argv to be unharmed. We should add one test that uses every option and ensures every one option is present in the rerun command.

ensure
ARGV.replace original_args
end

private

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

private

def parse_arguments(args)
Rails::Command::ServerCommand.class_eval do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, I had to do something similar for the other commands. But if we can make it happen, great 👍

class_option :daemon, aliases: "-d", type: :boolean, default: false,
desc: "Runs server as a Daemon."
class_option :environment, aliases: "-e", type: :string,
desc: "Specifies the environment to run this server under (test/development/production).", banner: :name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(development/test/production) is the usual order we'd write this in.

@@ -89,18 +41,6 @@ def middleware
Hash.new([])
end

def default_options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I didn't pursue writing these options using Thor in the first place was that Rails::Server interops with Rack::Server in certain ways as seen by the super here.

Thus, since some of the methods you removed were also public, I figured they were part of Rails::Server's public API and to remove them we'd need to go through a deprecation cycle.

cc @rafaelfranca

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for pointing out!
I fixed that Rails::Server's public API can be used as before. How about that?

def initialize(*)
super
def initialize(options = nil)
super(options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not. See my comment about Rack::Server interop.

options
end

def option_parser(options) # :nodoc:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a method that's overriden from Rack::Server.

@y-yagi y-yagi assigned kaspth and unassigned rafaelfranca Nov 7, 2016
@y-yagi y-yagi changed the title clear the args of Thor when start rails server use Thor option parser in server commands parse Nov 13, 2016
@rafaelfranca rafaelfranca dismissed their stale review November 14, 2016 01:26

@kasper's the best person to review this.

@guilleiguaran
Copy link
Member

./bin/rails runner is failing for me using this branch when passing a second arg (the arg for the command that I'm trying to run with runner)

@guilleiguaran
Copy link
Member

My bad, looks like this PR is fixing only the rails server command not the rails runner one

@kaspth
Copy link
Contributor

kaspth commented Nov 18, 2016

@guilleiguaran correct. I'll handle the runner command not working with multiple args like it used to.

@y-yagi
Copy link
Member Author

y-yagi commented Dec 6, 2016

I was misunderstanding. Option parser is necessary even in the rack server. Therefore, I restored Rails::Server::Options.

Copy link
Contributor

@kaspth kaspth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think we're getting close ✌️

end

def restart_command
"bin/rails server #{ARGV.join(' ')}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful when mentioning ARGV in commands. I think this should be:

"bin/rails server #{@server} #{args.join(" ")}"

(Note that it needs to use double quoted strings here too.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this context, the args variable does not contain any arguments.
Therefore, kept the argument in the constructor and used it.

# Require application after server sets environment to propagate
# the --environment option.
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
end
end

def server_options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Thor any public instance method is a command, so we'd need to wrap this in a no_commands do block.

def initialize(*)
super
def initialize(options = nil)
@default_options = options.nil? ? {} : options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this? @default_options = options || {}


def option_parser(options) # :nodoc:
OptionParser.new do |opts|
opts.banner = "Usage: rails server [puma, thin etc] [options]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we port over the server argument with this:

argument :server, optional: true, banner: '[puma, thin etc]'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If argument used, need to specify the "server" argument twice to specify server(e.g. ./bin/rails server server webrick).
Therefore, override .banner instead.

The `ServerCommand` inherits Thor, but currently does not use Thor
option parser.
Therefore, if leave the argument of Thor as it is, it becomes an error by
the argument checking of Thor.
To avoid it, to use the Thor option parser instead of reimplementing it.

Fixes rails#26964
@y-yagi
Copy link
Member Author

y-yagi commented Dec 24, 2016

Thanks for reviewing! I updated commit!

@kaspth kaspth merged commit e983948 into rails:master Dec 29, 2016
@kaspth
Copy link
Contributor

kaspth commented Dec 29, 2016

Way cool, thanks!

@y-yagi
Copy link
Member Author

y-yagi commented Dec 30, 2016

Thanks!!

@y-yagi y-yagi deleted the fix_26964 branch December 30, 2016 11:29
@DougMaisells
Copy link

DougMaisells commented Nov 21, 2017

I am running Rails 5.1.1 and I get an error that looks like the same thing. What am I missing?
rails s –p 5000
/Users/douglas.maisells/.rvm/gems/ruby-2.3.1@chronus/gems/thor-0.19.4/lib/thor/base.rb:484:in handle_argument_error': ERROR: "rails server" was called with arguments ["5000"] (Thor::InvocationError) Usage: "rails server [puma, thin etc] [options]" from /Users/douglas.maisells/.rvm/gems/ruby-2.3.1@chronus/gems/thor-0.19.4/lib/thor/command.rb:34:in rescue in run'

To fix this, I worked another dev and we updated the Gemfile.lock and I changed, under railties, thor (~> 0.20.0), then I ran #bundle update thor , then I was able to execute the rails command above.

tgxworld pushed a commit to tgxworld/rails that referenced this pull request Jun 18, 2018
`optparse` is unused since rails#26977.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants