Home > OS >  Rails - find_by and where is not working as expected
Rails - find_by and where is not working as expected

Time:09-24

Rails version - 6.0.3.6

I have one table subscription_attempts and it has one column attempt_token which is unique random token for each record and it is generated based on rails's enter image description here

When i tried to do this query with where got below exception

SubscriptionAttempt.where('id = ?', '5HqBToVVbFVL4T6TLzuuKju8')

ActiveRecord::StatementInvalid (PG::InvalidTextRepresentation: ERROR:  invalid input syntax for type bigint: "5HqBToVVbFVL4T6TLzuuKju8")
LINE 1: ...empts".* FROM "subscription_attempts" WHERE (id = '5HqBToVVb...

I am assuming this is not how these methods should behave. It should give a nil result if the value is not matching with database value. Can someone please give me the solution to this problem?

CodePudding user response:

ActiveRecord automatically does some type casting before querying the database. You can read more about it here. Basically, since ActiveRecord knows that the id column is an integer, it will cast the value passed to find_by(id: value) to an integer and:

> '5HqBToVVbFVL4T6TLzuuKju8'.to_i
=> 5

Try switching the order:

def random_method(value)
  find_by(attempt_token: value) || find_by(id: value)
end

This is still not a 100% bullet proof in case you have an instance with an attempt_token of "1234" and another instance with an id of 1234. The former will always be returned even if you meant to fetch the latter.

Another solution would be to prepend a constant prefix to your attempt_token:

ATTEMPT_TOKEN_PREFIX = 'at_'.freeze

def attempt_token_with_prefix
  # provide this value to the user instead of just providing the raw attempt_token
  "#{ATTEMPT_TOKEN_PREFIX}#{attempt_token}"
end

def random_method(value)
  if value.starts_with?(ATTEMPT_TOKEN_PREFIX)
    find_by(attempt_token: value[ATTEMPT_TOKEN_PREFIX.length..])
  else
    find_by(id: value)
  end
end

  • Related