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

Fix undefined method error at EnvironmentLoader #175

Merged
merged 2 commits into from
Feb 14, 2016

Conversation

h3poteto
Copy link
Contributor

When I use Shoryuken::EnvironmentLoader#load in Rails3, I got an raised error below.

/vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/shoryuken-2.0.3/lib/shoryuken/environment_loader.rb:44:in `config_file_options': undefined method `deep_symbolize_keys' for #<Hash:0x007f657fb98048> (NoMethodError)
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/shoryuken-2.0.3/lib/shoryuken/environment_loader.rb:20:in `load'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/shoryuken-2.0.3/lib/shoryuken/environment_loader.rb:6:in `load'
    from /vagrant/crowdworks/config/initializers/shoryuken.rb:17:in `<top (required)>'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:245:in `load'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:245:in `block in load'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:236:in `load_dependency'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:245:in `load'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/engine.rb:593:in `block (2 levels) in <class:Engine>'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/engine.rb:592:in `each'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/engine.rb:592:in `block in <class:Engine>'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/initializable.rb:30:in `instance_exec'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/initializable.rb:30:in `run'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/initializable.rb:55:in `block in run_initializers'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/initializable.rb:54:in `each'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/initializable.rb:54:in `run_initializers'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/application.rb:136:in `initialize!'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/railtie/configurable.rb:30:in `method_missing'
    from /vagrant/crowdworks/config/environment.rb:5:in `<top (required)>'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:251:in `require'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:251:in `block in require'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:236:in `load_dependency'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/activesupport-3.2.22/lib/active_support/dependencies.rb:251:in `require'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/application.rb:103:in `require_environment!'
    from /vagrant/crowdworks/vendor/bundle/ruby/2.1.0/gems/railties-3.2.22/lib/rails/commands.rb:40:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

This is because ActiveSupport v3.2 does not define Hash#deep_symbolize_keys.
So, I've added closely check hash methods in core_ext.rb.

@Senjai
Copy link
Contributor

Senjai commented Jan 27, 2016

This is not a reasonable way to solve this problem.

You are correct in your assertion that 3.2 doesnt define the method: https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/hash/keys.rb

But calling methods on hashes till any specific one of them fails, so we redefine them all is not a good idea. Instead bump the version of active support, or add a check to the version of active support which has the problem and define it conditionally if the version does not bring in the correct method.

Please try again.

def deep_symbolize_keys
keys.each do |key|
value = delete(key)
self[(key.to_sym rescue key) || key] = value

Choose a reason for hiding this comment

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

Avoid using rescue in its modifier form.

@h3poteto
Copy link
Contributor Author

It is good idea that I add a check to the version of active support, but active support is not written in gemspec. So, require will fail when someone use this outside Rails.
I guess that shoryuken is used outside Rails.

Therefore, I add method_defined? for each Hash methods after call active support.

@Senjai
Copy link
Contributor

Senjai commented Jan 28, 2016

@h3poteto

ActiveSupport::VERSION::MAJOR # 3
ActiveSupport::VERSION::MINOR # 2
# e.g. 3.2

@h3poteto
Copy link
Contributor Author

ActiveSupport::VERSION::MAJOR will raise NameError: uninitialized constant outside Rails.

We should not use …

@phstc
Copy link
Collaborator

phstc commented Jan 30, 2016

@h3poteto @Senjai actually I think we don't need deep_symbolize_keys, we only use it here. And most YAMLs are written in this way:

key: "value"

Not wrapping the keys with quotes:

"key": "value"

So, maybe the fix would be to remove deep_symbolize_keys and review all references of Shoryuken.options to make sure it's using a symbol instead of a string as a key. wdyt?

@h3poteto
Copy link
Contributor Author

h3poteto commented Feb 2, 2016

YAML parser did not construe key as symbol, if YAMLs are written in this way:

key: "value"

and YAML.load return string as a key:

YAML.load("aws:\n access_key_id: hoge\n")
=> {"aws"=>{"access_key_id"=>"hoge"}}

But, when YAMLs are written in this way:

:key: "value"

YAML.load return symbol.

YAML.load(":aws:\n :access_key_id: hoge\n")
=> {:aws=>{:access_key_id=>"hoge"}}

So, if everyone use symbol syntax for yaml like this:

:key: "value"

we can remove deep_symbolize_keys. I think that we should not remove deep_symbolize_keys, because maybe many developers did not use symbol syntax for yaml.

@phstc
Copy link
Collaborator

phstc commented Feb 2, 2016

@h3poteto interesting, great point! Because of this - I thought that symbol as the default, as Sidekiq uses YAML.load and retrieve the options passing symbols.

But based on this:

YAML.load("aws:\n access_key_id: hoge\n")
=> {"aws"=>{"access_key_id"=>"hoge"}}

I would remove deep_symbolize_keys and review all places that use Shoryuken.options to make sure that they are passing a string key instead of symbol.

wdyt?

@h3poteto
Copy link
Contributor Author

h3poteto commented Feb 3, 2016

@phstc Thank you for proposal.
I checked yaml parser in Sidekiq.
Sidekiq recommend symbol syntax for yaml in wiki, and Sidekiq ignore a string key like this:

YAML.load("aws:\n access_key_id: hoge\n")
=> {"aws"=>{"access_key_id"=>"hoge"}}

I considered this.

I thought that like below:

we should not remove deep_symbolize_keys, because maybe many developers did not use symbol syntax for yaml

but, now I think that we can remove deep_symbolize_keys and we should announce new shoryuken.yml about symbol syntax for yaml in README and wiki like Sidekiq.

Maybe, developers will read README, when developers start to use shoryuken.
And existing developers will read release note or new README, when upgrade shoryuken.

So, developers will detect new shoryuken.yml and can use symbol syntax for yaml like this:

:aws:
  :access_key_id: hoge

I think that symbol syntax is fine with developers.

What do you think?

@phstc phstc merged commit 34d20a1 into ruby-shoryuken:master Feb 14, 2016
@phstc
Copy link
Collaborator

phstc commented Feb 14, 2016

hi @h3poteto

I personally prefer:

aws:
  access_key_id: hoge

But in favor of styling preferences in something that widely used YAML, backwards compatibility with previous versions of Shoryuken and simplicity, I merged your change, and I've also added some specs.

Thanks a lot for your PR and all researched! 🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants