Tag: ActiveModel

State Machine gem and Rails (ActiveModel) 4.1 – NoMethodError – protected method ‘around_validation’ called for StateMachine

State machine is a great gem, unfortunately it's not working with Rails 4.1. If you upgrade your app and try to use it, you'll end up with following error:

NoMethodError - protected method `around_validation' called for #<StateMachine::Machine:0x007fd4ea002c80>:
  activesupport (4.1.4) lib/active_support/callbacks.rb:447:in `public_send'
  activesupport (4.1.4) lib/active_support/callbacks.rb:447:in `block in make_lambda'
  activesupport (4.1.4) lib/active_support/callbacks.rb:298:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:298:in `block in halting'
  activesupport (4.1.4) lib/active_support/callbacks.rb:86:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:86:in `run_callbacks'
  activemodel (4.1.4) lib/active_model/validations/callbacks.rb:111:in `run_validations!'
  activemodel (4.1.4) lib/active_model/validations.rb:317:in `valid?'
  activerecord (4.1.4) lib/active_record/validations.rb:70:in `valid?'
  activerecord (4.1.4) lib/active_record/validations.rb:77:in `perform_validations'
  activerecord (4.1.4) lib/active_record/validations.rb:57:in `save!'
  activerecord (4.1.4) lib/active_record/attribute_methods/dirty.rb:29:in `save!'
  activerecord (4.1.4) lib/active_record/transactions.rb:273:in `block in save!'
  activerecord (4.1.4) lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:208:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
  activerecord (4.1.4) lib/active_record/transactions.rb:273:in `save!'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:487:in `block in save!'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:502:in `block (2 levels) in around_save'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:150:in `block in run_actions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:170:in `catch_exceptions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:148:in `run_actions'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:133:in `run_callbacks'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:212:in `run_callbacks'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block (2 levels) in perform'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `catch'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block in perform'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:186:in `within_transaction'
  state_machine (1.2.0) lib/state_machine/transition_collection.rb:62:in `perform'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:502:in `block in around_save'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:530:in `block in transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
  activerecord (4.1.4) lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
  activerecord (4.1.4) lib/active_record/transactions.rb:208:in `transaction'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:529:in `transaction'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:501:in `around_save'
  state_machine (1.2.0) lib/state_machine/integrations/active_record.rb:487:in `save!'
  activerecord (4.1.4) lib/active_record/validations.rb:41:in `create!'
  app/models/concerns/channel/tracked.rb:139:in `find_or_create_channel'
  app/models/concerns/channel/tracked.rb:128:in `track'
  app/controllers/reporting/tracked_channels_controller.rb:20:in `create'
  actionpack (4.1.4) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.1.4) lib/abstract_controller/base.rb:189:in `process_action'
  actionpack (4.1.4) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.1.4) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
  activesupport (4.1.4) lib/active_support/callbacks.rb:113:in `call'
  activesupport (4.1.4) lib/active_support/callbacks.rb:113:in `call'

Here's a fix. Just put it into your initializers:

# Stathe machine
module StateMachine
  # Extensions for integrations of state machine
  module Integrations
    # ActiveModel extension that fixes the non-public around_validation error
    module ActiveModel
      send :public, :around_validation
    end
  end
end

Note: It works also for any non-Rails, ActiveModel based apps.

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'

ActionView::Template::Error:
 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 ;)

Example:

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)>')

Summary

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.

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑