ruby-on-railsrubyrails-activerecordcounter-cache

Getting couter_cache error when saving record in rails


I'm getting an error when trying to create a vote on items in my rails application. It seems to be related to the counter cache.

error

#<ArgumentError: wrong number of arguments (given 3, expected 1..2)>

error.backtrace

["/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/callbacks.rb:451:in `increment!'",
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/draper-4.0.1/lib/draper/automatic_delegation.rb:12:in `method_missing'", 
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/associations/belongs_to_association.rb:91:in `update_counters'", 
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/associations/belongs_to_association.rb:54:in `increment_counters'", 
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/counter_cache.rb:169:in `block in _create_record'", 
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/counter_cache.rb:192:in `block in each_counter_cached_associations'", 
"/Users/antarr/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3.2/lib/active_record/counter_cache.rb:191:in 

app/models/vote.rb

# == Schema Information
#
# Table name: votes
#
#  id           :bigint           not null, primary key
#  stance       :integer          default("Unsure")
#  votable_type :string
#  created_at   :datetime         not null
#  updated_at   :datetime         not null
#  user_id      :integer
#  votable_id   :integer
#
# Indexes
#
#  index_votes_on_user_id                      (user_id)
#  index_votes_on_votable_id_and_votable_type  (votable_id,votable_type)
#

class Vote < ApplicationRecord
  attr_accessor :get_verified

  enum stance: { 'Unsure' => 0, 'Yes' => 1, 'No' => 2 }

  belongs_to :user, counter_cache: true

  validates :user_id, uniqueness: { scope: %i[votable_type votable_id] }

  belongs_to :votable, polymorphic: true
  validates :votable, presence: true

  scope :verified, -> { where('user_id in ( select user_id from verifications )') }
  scope :yays, -> { where(stance: true) }
  scope :nays, -> { where(stance: false) }
  scope :undecided, -> { where(stance: nil) }
end

app/controllers/votes_controller.rb

class WeVote::VotesController < WeVoteController
  load_and_authorize_resource

  def create
    @vote.user = current_user_or_guest
    @vote.save!
    if @vote.get_verified == 'true'
      redirect_to new_verification_path
    else
      redirect_to request.referer
    end
  rescue ArgumentError => e
    byebug
    Rails.logger.error(e)
    redirect_to request.referer, notice: { alert: e }
  end

  def destroy
    @vote.destroy
    redirect_to request.referer
  end

private

  def vote_params
    params.require(:vote).permit(:votable_type, :votable_id, :stance, :get_verified)
  end
end

Solution

  • The key to your issue is the second line of your backtrace, in which you can see that the draper gem is intercepting unknown messages.

    That particular method is looking out for specific calls, and if it doesn't need to act upon the message it's intercepting, it attempts to direct them back to the main application.

    Unfortunately, the manner in which it's doing so isn't compatible with your version of Ruby, which I suspect is version 3. Ruby's internal handling of method arguments changed between versions 2.x and 3.x, and the released version of Draper relied upon the 2.x implementation.

    This issue in the Draper repo matches what you're seeing in your code base.

    Until a formal fix is released, you can update your Gemfile to point directly to the Draper repo rather than the cut gem version:

    gem 'draper', github: 'drapergem/draper'