Tag: RVM

Upgrading to Rails 4.1 from Rails 4.0 – Ruby on Rails

Upgrading to Ruby on Rails 4.1 was much easier than moving from 3.2 to 4.0. Maybe because I try to keep all the apps up-2-date, maybe because Rails guys didn't change much stuff ;) (or maybe both). Either way, lets get through it.

Paperclip - String based terminators are deprecated, please use a lambda

DEPRECATION WARNING: String based terminators are deprecated, please use a lambda. 
(called from has_attached_file at app/config/initializers/paperclip_extensions.rb:22)

Well this one is really simple - just update Paperclip gem:

bundle update paperclip

More about this issue here.

The ability to pass in strings as a class name to set_fixture_class
will be removed

Next deprecation warning:

DEPRECATION WARNING: The ability to pass in strings as a class name to `set_fixture_class`
 will be removed in Rails 4.2. Use the class itself instead. 
(called from block in initialize at gems/activerecord-4.1.0/lib/active_record/fixtures.rb:465)

It you use Rspec you probably won't see this issue at all (or if you don't use fixtures). One of my apps unfortunately still does. Solution to this is really simple. Instead of:

set_fixture_class scanlation_categories:  'Scanlation::Category'
set_fixture_class scanlation_chapters:    'Scanlation::Chapter'
set_fixture_class scanlation_pages:       'Scanlation::Page'

use the class name itself (not its string version):

set_fixture_class scanlation_categories:  Scanlation::Category
set_fixture_class scanlation_chapters:    Scanlation::Chapter
set_fixture_class scanlation_pages:       Scanlation::Page

NameError: undefined method `_run_suite' for class `Test::Unit::Runner'

MiniTest::Unit::TestCase is now Minitest::Test. From /unit/testcase.rb:8:in `<module:Unit>'
rake aborted!
NameError: undefined method `_run_suite' for class `Test::Unit::Runner'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
app/test/test_helper.rb:23:in `<top (required)>'

Just get rid of this line from your test/test_helper.rb file:

require 'test/unit'

cannot load such file -- polyamorous (LoadError)

in `require': cannot load such file -- polyamorous (LoadError)
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /ransack/lib/ransack/adapters/active_record/context.rb:3:in `<top (required)>'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack-d51c78f9071f/lib/ransack/adapters/active_record.rb:4:in `<top (required)>'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from /activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack-d51c78f9071f/lib/ransack.rb:24:in `<top (required)>'
from /bundler-1.5.2/lib/bundler/runtime.rb:76:in `require'
from /bundler-1.5.2/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
from /bundler-1.5.2/lib/bundler/runtime.rb:72:in `each'
from /bundler-1.5.2/lib/bundler/runtime.rb:72:in `block in require'
from /bundler-1.5.2/lib/bundler/runtime.rb:61:in `each'
from /bundler-1.5.2/lib/bundler/runtime.rb:61:in `require'
from /bundler-1.5.2/lib/bundler.rb:131:in `require'
from app/config/application.rb:6:in `<top (required)>'
from app/config/environment.rb:1:in `require'
from app/config/environment.rb:1:in `<top (required)>'
from app/spec/spec_helper.rb:21:in `require'
from app/spec/spec_helper.rb:21:in `<top (required)>'
from app/spec/controllers/portal/announcements_controller_spec.rb:1:in `require'
from app/spec/controllers/portal/announcements_controller_spec.rb:1:in `<top (required)>'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `load'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `block in load_spec_files'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `each'
from /rspec-core-3.0.0.beta2/lib/rspec/core/configuration.rb:932:in `load_spec_files'
from /rspec-core-3.0.0.beta2/lib/rspec/core/command_line.rb:21:in `run'
from /rspec-core-3.0.0.beta2/lib/rspec/core/runner.rb:100:in `run'
from /rspec-core-3.0.0.beta2/lib/rspec/core/runner.rb:31:in `invoke'
from /rspec-core-3.0.0.beta2/exe/rspec:4:in `<top (required)>'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/rspec:23:in `load'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/rspec:23:in `<main>'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/ruby_executable_hooks:15:in `eval'
from /home/mencio/.rvm/gems/ruby-2.1.0@senpuu/bin/ruby_executable_hooks:15:in `<main>'

To remove this issue, upgrade your Ransack, MetaSearch and Squeel gems to newest versions and/or add this to your Gemfile:

gem 'polyamorous', github: 'activerecord-hackery/polyamorous'

 undefined method `reverse!' for #<ActiveRecord::Relation []>
Shared Example Group: "has valid single" 
called from ./spec/controllers/episodes_controller_spec.rb:13
./lib/system/active_record/nearable.rb:54:in `near'
./app/views/portal/episodes/show.html.haml:43:in `block in _app_views_episodes_show_html_haml'
./app/views/portal/episodes/show.html.haml:1:in `_app_views_episodes_show_html_haml'
./app/controllers/application_controller.rb:68:in `respond_with'
./app/controllers/portal/base_controller.rb:64:in `respond_with'
./app/controllers/portal/episodes_controller.rb:13:in `show'
./spec/support/macros/controllers/actions.rb:80:in `block (4 levels) in <module:Actions>'

With ActiveRecord 4.1, you can't call reverse! directly on ActiveRecord::Relation. Example:

# This will throw an error
@articles = Article.limit(10).order('created_at DESC').reverse!

Instead you have to cast ActiveRecord::Relation to an array:

@articles = Article.limit(10).order('created_at DESC').to_a.reverse!

Keep in mind, that casting with to_a will deprive you from all benefits of lazy loading with Rails relations so use it carefully. But on the other hand, reverse! on ActiveRecord::Relation did the same, so if you used it and it was ok, than feel free ;)

Undefined method `graft' for class ActiveRecord::Associations::JoinDependency

gems/activesupport-4.1.0/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method': 
undefined method `graft' for class `ActiveRecord::Associations::JoinDependency' (NameError)
activesupport-4.1.0/lib/active_support/core_ext/module/aliasing.rb:32:in `alias_method_chain'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:7:in `block in included'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:5:in `class_eval'
from gems/polyamorous-0.6.4/lib/polyamorous/join_dependency.rb:5:in `included'
from gems/polyamorous-0.6.4/lib/polyamorous.rb:20:in `include'
from gems/polyamorous-0.6.4/lib/polyamorous.rb:20:in `<top (required)>'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/ransack/lib/ransack/adapters/active_record/context.rb:3:in `<top (required)>'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `block in require'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:232:in `load_dependency'
from gems/activesupport-4.1.0/lib/active_support/dependencies.rb:247:in `require'

Just install the newest version of ransack gem.

gem 'ransack', github: 'ernie/ransack'

Scoped order and limit are ignored, it's forced to be batch order and batch size

This is quite logical - you can't have some of orders when batching (for example a RAND()). That's why ActiveRecord is ignoring it. Just keep that in mind ;)


Token.2.1.0 :001 > Token.order('RAND()').find_each{}
W, [2014-05-09T11:26:46.601539 #11569]  WARN -- : 
Scoped order and limit are ignored, it's forced to be batch order and batch size
D, [2014-05-09T11:26:46.698603 #11569] DEBUG -- :   
Token Load (3.7ms)  SELECT  "accounts".* FROM "accounts"   ORDER BY "accounts"."id" ASC LIMIT 1000

Other issues

Well to be honest I didn't have any more issues. I've decided to remove Squeel gem from all of my projects, since it is not currently maintained. Thanks to that I've finally got rid of this irritating deprecation warning:

DEPRECATION WARNING: Core extensions are deprecated and will be removed in Squeel 2.0.
 (called from /app/config/initializers/squeel.rb:2:in `block in <top (required)>')


Rails 4.1 is not a big step, although it is a required one if you want to upgrade to 4.2 in the future. If you have decent test coverage level, you should not have big issues with this upgrade.

Rack/Ruby on Rails: ArgumentError: invalid byte sequence in UTF-8

# Quick test - just copy-paste this: ?%28t%B3odei%29 into your app url - if app crashes, you should read stuff below ;)

If you're here, than probably you've encountered this weird issue:

ArgumentError: invalid byte sequence in UTF-8

you might even have a backtrace like this:

rack-1.5.2/lib/rack/utils.rb:104→ normalize_params
rack-1.5.2/lib/rack/utils.rb:96→ block in parse_nested_query
rack-1.5.2/lib/rack/utils.rb:93→ each
rack-1.5.2/lib/rack/utils.rb:93→ parse_nested_query
rack-1.5.2/lib/rack/request.rb:373→ parse_query
actionpack-4.0.4/lib/action_dispatch/http/request.rb:321→ parse_query
rack-1.5.2/lib/rack/request.rb:188→ GET
actionpack-4.0.4/lib/action_dispatch/http/request.rb:274→ GET
actionpack-4.0.4/lib/action_dispatch/http/parameters.rb:16→ parameters
actionpack-4.0.4/lib/action_dispatch/http/filter_parameters.rb:37→ filtered_parameters
activesupport-4.0.4/lib/active_support/cache/strategy/local_cache.rb:83→ call
rack-1.5.2/lib/rack/sendfile.rb:112→ call
railties-4.0.4/lib/rails/engine.rb:511→ call
railties-4.0.4/lib/rails/application.rb:97→ call
railties-4.0.4/lib/rails/railtie/configurable.rb:30→ method_missing
puma-2.7.1/lib/puma/configuration.rb:68→ call
puma-2.7.1/lib/puma/server.rb:486→ handle_request
puma-2.7.1/lib/puma/server.rb:357→ process_client
puma-2.7.1/lib/puma/server.rb:250→ block in run
puma-2.7.1/lib/puma/thread_pool.rb:92→ call
puma-2.7.1/lib/puma/thread_pool.rb:92→ block in spawn_thread

First of all, this issue is not super-important. It's not a security issue as well. It's just an invalid byte sequence in your request url. Either way it would be good to fix it, even for a sole purpose of getting rid of this from our bug tracker.

But before we do anything with this, how can we determine, that our URL is an invalid UTF-8? We can use URI decode method for that:

# With an invalid byte sequence
url = 'http://senpuu.net/?techniki,Sawarabi_no_Mai_%28taniec_m%B3odej_paproci%29'
URI.decode(url).force_encoding('UTF-8').valid_encoding? #=> false

# and with a valid one
url = 'http://www.senpuu.net/aktualnosci'
URI.decode(url).force_encoding('UTF-8').valid_encoding? #=> true

So, how can we handle this? Well we need to catch it in middleware before anything else wants to process it. I think, that in such cases we should just raise 400 error - bad request, since this is not something that we expect. Middleware like this can be really simple:

class Utf8Sanitizer

  def initialize(app)
    @app = app

  def call(env)
    SANITIZE_ENV_KEYS.each do |key|
      string = env[key].to_s
      valid = URI.decode(string).force_encoding('UTF-8').valid_encoding?
      # Don't accept requests with invalid byte sequence
      return [ 400, { }, [ 'Bad request' ] ] unless valid


and after that you just put into your config/application.rb this:

  config.middleware.use Utf8Sanitizer

and you're resistant to this issue.

## Update

It seems that there's a gem called utf8-cleaner that sanitizes non-utf8 strings. It has one issue - instead of rising 400 error it just removes invalid bytes but still - it's way better that nothing. If you just want to get rid of this problem, put this into your gemfile:

gem 'utf8-cleaner'

## Update 2
I've got a response from Rack guys and it seems that it's more like a Rails issue than a Rack one:
Raggi stated here that:

It is a web servers responsibility to translate IO to valid binary representations for the application layer. This isn't the whole picture though, in this case, the webserver has done that - the webserver does not know the encoding of the URI...

It is the responsibility of the IETF to define the validity of URI data in various encodings (not done), and so it is not entirely valid for web servers to make no assumptions for this field for the above...

Rack itself uses a binary regular expression here, which expects binary input strings. This is our response to the above subtleties. In normal operation (say, Webrick + Rack), this error is not raised...

The reason that this error is raised in your application is:

You have middleware in your stack that is forcing this string to UTF-8, even when it is not valid UTF-8. The code that is doing this is bugged.


s = "a=\xff"
# => "a=\xFF"
# => "a=\xFF"
# => true
# => {"a"=>"\xFF"}
# => "a=\xFF"
# => false
ArgumentError: invalid byte sequence in UTF-8
        from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `split'
        from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/lib/ruby/gems/2.0.0/gems/rack-1.5.2/lib/rack/utils.rb:93:in `parse_nested_query'
        from (irb):21
        from /usr/local/google/home/raggi/.rbenv/versions/2.0.0-p247/bin/irb:12:in `<main>'

This is a rails bug. Calls to force_encoding should always assert that their output is valid.

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑