Skip to content

Arel::Expression.count clashes with String.count #149

Closed
dancinglightning opened this Issue Nov 18, 2012 · 11 comments

6 participants

@dancinglightning

module Arel
module Expressions
def count distinct = false
..
gets included into SqlLiteral < String , and as such overrides the built in function.

This results in the fact that arel asts can't be yamld , because psyc calls the original count with 2 args (see below).

Probably not a major issue for anyone, just would help to study those trees.
Unfortunately I haven't got any idea how to fix this, but I thought I'd let someone know anyway.

ArgumentError: wrong number of arguments (2 for 1)
.rvm/gems/ruby-1.9.3-p286/bundler/gems/arel-890eaf4784fb/lib/arel/expressions.rb:3:in count'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:225:in
binary?'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:234:in visit_String'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:292:in block in visit_Hash'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in visit_Hash'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in block in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in
visit_Object'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in
block in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in visit_Object'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in
accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in block in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in
each'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in dump_ivars'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in
visit_Object'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in accept'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:67:in
push'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych.rb:242:in dump'
.rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/psych/core_ext.rb:14:in
psych_to_yaml'
rails/phoenix/lib/active_record/connection_adapters/phoenix_visitor.rb:30:in `accept'
.
.
.
the accept does a to_yaml on the ast tree, below

Arel::Nodes::SelectStatement:0x00000102900080 @cores=[#, @right=[]>, @top=#, @set_quantifier=nil, @projections=[#, name="*">], @wheres=[#, name="id">, @right="?">]>], @groups=[], @having=nil, @windows=[]>], @orders=[], @limit=#, @lock=nil, @offset=nil, @with=nil>

(above sort of shows why I want to use to_yaml)

@jamilbk
jamilbk commented Dec 19, 2012

I'm getting this too -- not sure what's causing it. It's a bit elusive to track down.

@dancinglightning

It comes from trying to output an ast with to_yaml. I'm not sure if it happens at all in standard rails code, I only got it when trying to debug how arel trees look like.

@jamilbk
jamilbk commented Dec 19, 2012

Ahh, thanks for that heads up. Yeah, I'm getting the error in mailer views, but only when I deliver the mail. I guess I'll have to preload my models before passing them to the mailer views...

@mdesantis

Hello,

I confirm I have this bug, using ruby 1.9.3/rails 3.0.2 and ruby 2.0.0/rails 4.0.0.beta1:

$ rails r "YAML.dump Arel::Nodes::SqlLiteral.new('asd')"
/home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0.beta1/lib/rails/commands/runner.rb:53:in `eval': wrong number of arguments (2 for 0..1) (ArgumentError)
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:250:in `binary?'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:262:in `visit_String'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:128:in `accept'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb:92:in `push'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/2.0.0/psych.rb:244:in `dump'
  from (eval):1:in `<top (required)>'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0.beta1/lib/rails/commands/runner.rb:53:in `eval'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0.beta1/lib/rails/commands/runner.rb:53:in `<top (required)>'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0.beta1/lib/rails/commands.rb:86:in `require'
  from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0.beta1/lib/rails/commands.rb:86:in `<top (required)>'
  from bin/rails:4:in `require'
  from bin/rails:4:in `<main>'

This is a big problem for me, 'cause I use delayed jobs in order to send an email when the Rails app raises an exception, and the jobs fail every time the env/exception contains an Arel condition.

I'm trying to find a temporarly solution; at the moment, I wrote this:

# config/initializers/job_test.rb
module ArelNodesSqlLiteralYAMLDumpFix
  def binary?(string)
    string = string.to_s if defined?(Arel) && string.is_a?(Arel::Nodes::SqlLiteral)
    super(string)
  end
end

module Psych
  module Visitors
    class YAMLTree
      prepend ArelNodesSqlLiteralYAMLDumpFix
    end
  end
end

which makes DelayedJob happy:

# config/initializers/job_test.rb

...

class SqlLiteralJob < Struct.new(:sql_literal)
  def perform
    p sql_literal, sql_literal.class
  end
end

Delayed::Job.enqueue SqlLiteralJob.new(Arel::Nodes::SqlLiteral.new('asd'))
$ rake jobs:work 
[Worker(host:host pid:14222)] Starting job worker
"asd"
String
[Worker(host:host pid:14222)] SqlLiteralJob completed after 0.0755
[Worker(host:host pid:14222)] 1 jobs processed at 6.3364 j/s, 0 failed ...

But, as you see, p sql_literal.class returns String, so maybe I am doing something wrong... does anyone know a better solution?

@mdesantis

Is this an acceptable solution? It works for me:

module Arel
  module Nodes
    class SqlLiteral < String
      def encode_with(coder)
        coder['string'] = to_s
      end
      def init_with(coder)
        clear << coder['string']
      end
    end
  end
end
@lrbalt
lrbalt commented May 13, 2013

I have the same problem while migrating to Rails 4.0.0.rc1

The solution of @ProGNOMmers works for me

@petervandenabeele

Ruby 1.9.3 , Rails 4.0.1

I am not entirely sure if this is related to this issue or a different issue (if so, I can open a new issue). Documented in more detail in harley/auditable#14 (comment) and below.

In essence, running YAML.dump(log_data) where log_data is a hash that contains this key value pair:

log_data #=> {... , :order_items=>#<ActiveRecord::Associations::CollectionProxy [#<OrderItem order_id: "a6be89c0-e073-4689-80a4-c8fcbc30c90b", ...>]}

The serialization of the ActiveRecord::Associations::CollectionProxy object fails with

     ArgumentError:
       wrong number of arguments (2 for 1)
     # /Users/peter_v/.rvm/gems/ruby-1.9.3-p448@...../gems/arel-4.0.1/lib/arel/expressions.rb:3:in `count'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:225:in `binary?'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:234:in `visit_String'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in `block in dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in `visit_Object'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:313:in `block in visit_Array'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:313:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:313:in `visit_Array'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:293:in `block in visit_Hash'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in `visit_Hash'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in `block in dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in `visit_Object'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in `block in dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in `visit_Object'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:449:in `block in dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:447:in `dump_ivars'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:125:in `visit_Object'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:293:in `block in visit_Hash'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in `each'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:291:in `visit_Hash'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:103:in `accept'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych/visitors/yaml_tree.rb:67:in `push'
     # /Users/peter_v/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/psych.rb:242:in `dump'
     # ./lib/log_to_audit_file.rb:40:in `log_message'

I tried the fix above by @ProGNOMmers but it did not resolve the issue for me, so maybe this is a different issue?

If I reify the ActiveRecord::Associations::CollectionProxy object by calling to_a on it, then the YAML.dump works as expected (the hash value for :order_items then becomes [#<OrderItem order_id: "7597bb03-beed-433c-a703-843c52cc4856", ..>]

@rafaelfranca
Ruby on Rails member

@petervandenabeele could you try with arel 4-0-stable branch? I beleave this bug was fixed there.

@petervandenabeele

@rafaelfranca Thanks. Yes switching to arel branch 4-0-stable fixed the issue for me. That means the issue I was having was really related to #216

@rafaelfranca
Ruby on Rails member

Yes. Thank you for confirming.

@mdesantis

Fixed here too :+1:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.