Search code examples
ruby-on-railspostgresqlactiverecordrakerake-task

How do I get Active Record query that works in Rails console working in a rake task?


I have an active record query that works fine in the console but does not work when I use it in a rake task

Here is the beginning of my rake task:

namespace :attendees do
  desc "Migrate sms plans to receive_sms attribute for attendees"
  task migrate_sms_plans: :environment do
    attendees_with_sms_plans = Attendee.select('attendees.id, attendees.phone, attendees.local_phone').joins(:plans).where('plans.name = ?', "Yes! SMS!")

Why does the select statement works in my rails console but give me the following error when I use it in the rake task, and how do I fix it:

ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  function count(integer, character varying, character varying) does not exist
LINE 1: SELECT COUNT(attendees.id, attendees.phone, attendees.local_...
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Turned out the error was not the select statement, but in the next line:

puts <<-TEXT
    Going to migrate #{attendees_with_sms_plans.count} attendees from "Yes! SMS!" plan to receive_sms: true attribute on Attendee Model
TEXT

which I fixed by changing to:

puts <<-TEXT
    Going to migrate #{attendees_with_sms_plans.to_a.count} attendees from "Yes! SMS!" plan to receive_sms: true attribute on Attendee Model
TEXT

Solution

  • Alright so far as guessed the error: -

    attendees_with_sms_plans = Attendee.select('attendees.id, attendees.phone, attendees.local_phone').joins(:plans).where('plans.name = ?', "Yes! SMS!")
    

    attendees_with_sms_plans will results as Attendee::ActiveRecord_Relation

    and on calling attendees_with_sms_plans.count will results into

    ERROR: function count(integer, character varying, character varying) does not exist

    which means that Postgres does not support count()with more than one column

    So the solution is you can use size() instead if count() like so: -

    attendees_with_sms_plans.size