undefined method `to_sql' for :name:Symbol #360

Closed
aaroncraigongithub opened this Issue Feb 26, 2014 · 10 comments

Projects

None yet

3 participants

@aaroncraigongithub

The following code works:

venues = Venue.where('emails LIKE ?', "%#{ email }%")
render json: { venues: venues.paginate(page: @page, per_page: @per_page) }

This code throws a NoMethodError:

venues = Venue.includes(:users).where('emails LIKE ?', "%#{ email }%").references(:users)
render json: { venues: venues.paginate(page: @page, per_page: @per_page) }

Removing the pagination call also works

venues = Venue.includes(:users).where('emails LIKE ?', "%#{ email }%").references(:users)
render json: { venues: venues }

So I'm assuming this issue is coming from some interaction between will_paginate and includes().

@mislav
Owner

Your activerecord version? bundle show activerecord

@mislav
Owner

Also, a full stack trace would be helpful

@aaroncraigongithub

Here's a backtrace:

     NoMethodError:
       undefined method `to_sql' for :name:Symbol
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/schema_statements.rb:479:in `block in distinct'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/schema_statements.rb:477:in `map'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/schema_statements.rb:477:in `distinct'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/finder_methods.rb:248:in `construct_limited_ids_condition'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/finder_methods.rb:237:in `apply_join_dependency'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/finder_methods.rb:226:in `construct_relation_for_association_find'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/finder_methods.rb:205:in `find_with_associations'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation.rb:585:in `exec_queries'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation.rb:471:in `load'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation.rb:220:in `to_a'
     # ./vendor/bundle/ruby/2.1.0/gems/will_paginate-3.0.5/lib/will_paginate/active_record.rb:127:in `block in to_a'
     # ./vendor/bundle/ruby/2.1.0/gems/will_paginate-3.0.5/lib/will_paginate/collection.rb:96:in `create'
     # ./vendor/bundle/ruby/2.1.0/gems/will_paginate-3.0.5/lib/will_paginate/active_record.rb:126:in `to_a'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation.rb:573:in `inspect'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:16:in `rescue in collect'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/relation/delegation.rb:12:in `collect'
     # ./app/controllers/venues_controller.rb:163:in `search'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/abstract_controller/base.rb:189:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/metal/rendering.rb:10:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/abstract_controller/callbacks.rb:18:in `block in process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:433:in `_run__772677588__process_action__callbacks'
     # ./vendor/bundle/ruby/2.1.0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/abstract_controller/callbacks.rb:17:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/metal/rescue.rb:29:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/activesupport-4.0.0/lib/active_support/notifications.rb:159:in `block in instrument'
     # ./vendor/bundle/ruby/2.1.0/gems/activesupport-4.0.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # ./vendor/bundle/ruby/2.1.0/gems/activesupport-4.0.0/lib/active_support/notifications.rb:159:in `instrument'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/abstract_controller/base.rb:136:in `process'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/abstract_controller/rendering.rb:44:in `process'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/test_case.rb:569:in `process'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/test_case.rb:64:in `process'
     # ./vendor/bundle/ruby/2.1.0/gems/actionpack-4.0.0/lib/action_controller/test_case.rb:475:in `post'
     # ./spec/controllers/venues_controller_spec.rb:483:in `block (3 levels) in <top (required)>'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:114:in `instance_eval'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:114:in `block in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-rails-2.14.1/lib/rspec/rails/example/controller_example_group.rb:158:in `call'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-rails-2.14.1/lib/rspec/rails/example/controller_example_group.rb:158:in `block (2 levels) in <module:ControllerExampleGroup>'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:247:in `instance_eval_with_args'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/hooks.rb:106:in `block (2 levels) in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:179:in `call'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:179:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-rails-2.14.1/lib/rspec/rails/adapters.rb:68:in `block (2 levels) in <module:MinitestLifecycleAdapter>'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_exec'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/extensions/instance_eval_with_args.rb:16:in `instance_eval_with_args'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:247:in `instance_eval_with_args'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/hooks.rb:106:in `block (2 levels) in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/hooks.rb:108:in `call'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/hooks.rb:108:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/hooks.rb:446:in `run_hook'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:340:in `run_around_each_hooks'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:256:in `with_around_each_hooks'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example.rb:111:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:390:in `block in run_examples'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:386:in `map'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:386:in `run_examples'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:371:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:372:in `block in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:372:in `map'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/example_group.rb:372:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/command_line.rb:28:in `block (2 levels) in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/command_line.rb:28:in `map'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/command_line.rb:28:in `block in run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/reporter.rb:58:in `report'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/command_line.rb:25:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/runner.rb:80:in `run'
     # ./vendor/bundle/ruby/2.1.0/gems/rspec-core-2.14.7/lib/rspec/core/runner.rb:17:in `block in autorun'
bundle show activerecord

# [PATH]/vendor/bundle/ruby/2.1.0/gems/activerecord-4.0.0
@dfpfernandez

I couldn't reproduce it with same activerecord version.

@aaroncraigongithub

Are the PostgreSQL versions the same? Mine is:

psql (PostgreSQL) 9.3.3
@dfpfernandez

Yes, I'm testing with the same version of postgres, activerecord and ruby. Could you try this with a clean project?

@aaroncraigongithub

Sorry, my initial post was misleading.

Upon further investigation, the error comes out when I add a reorder clause to the query.

Here is everything you need to reproduce the error in a clean installation:

migration:

# 20140305191809_create_tables.rb
class CreateTables < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email

      t.timestamps
    end

    create_table :venues do |t|
      t.string :name
      t.string :emails
      t.boolean :deleted

      t.timestamps
    end

    create_table :users_venues do |t|
      t.belongs_to :user
      t.belongs_to :venue

      t.timestamps
    end
  end
end

Venue model:

# venue.rb
class Venue < ActiveRecord::Base
  has_and_belongs_to_many :users
  serialize :emails,          JSON

  def Venue.find_by_email(email)
    Venue
      .includes(:users)
      .where("users.email = ? OR venues.emails LIKE ?", email, "%#{ email }%")
      .references(:users)
  end
end

Venues controller:

# venues_controller.rb
class VenuesController < ApplicationController

  def index
    venues = Venue.where('deleted IS NULL OR deleted = ?', false)
    venues = venues.find_by_email(params[:email])
    venues = venues.reorder(:name)
    render json: venues.paginate(page: 1, per_page: 25).collect { |v| v }
  end
end

Rspec for the controller:

# venues_controller_rspec.rb
require 'spec_helper'

describe VenuesController do
  let(:valid_attributes) { { "email" => "MyString" } }
  let(:valid_session) { {} }

  describe "GET index" do
    it "assigns all venues as @venues" do
      5.times do |i|
        venue = Venue.create! emails: ["venue#{ i }@example.com"], deleted: false, name: "Test venue #{ i }"
        venue.users.create! email: "user#{ i }@example.com"
      end

      get :index, email: 'example'
      JSON.parse(response.body).should be_a_kind_of(Array)
    end
  end
end
@dfpfernandez

I was researching in activerecord and I found that the problem was how to set the order. If you use venues.reorder('name') instead of venues.reorder(:name) works. Also probe with mysql2 and works both ways. Now I started to work to find a solution.

@dfpfernandez

It was an activerecord bug but was fixed. If you use the last version of rails your application should work.

@mislav
Owner

@vairix-dfernandez Thanks. @aaroncraigongithub: Try venues.reorder('name').

Closing as invalid.

@mislav mislav closed this Mar 7, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment