Rails find_by with OR
-
14-06-2021 - |
题
I have a named scope set up in my rails application that is used to locate a record either by its ID (directly from the index view) or a UUID (from an email - basically only so that users can't enter in any ID and view a record)
scope :by_uuid, lambda { |id| where('id = ? OR uuid = ?', id, id) }
This is used in the show action, so the ID comes from the url, like
services/114
services/74c083c0-8c29-012f-1c87-005056b42f8a
This works great, until you get a UUID such as 74c083c0-8c29-012f-1c87-005056b42f8a This, rails unfortunately converts to the int value and we get services/74 AS WELL AS the record with the correct UUID
Adding a .first to the scope will not help because the order could be different for each record, so that does not work.
Is there a way to prevent rails from converting the ID like this and taking the string literally? Obviously, there will not be a record with an ID that matches that, but if it goes willy-nilly with the integer values of the string passed to it, we could get anything back.
Using the dynamic finders, such as
Service.find_by_uuid
or
Service.find_by_id
work as intended, however we need to be able to retrieve a record using the UUID OR the ID in the same method (show).
Is there a way to do something like
Service.find_by_id_or_uuid
解决方案
We fixed this issue with the following change to the scope:
scope :by_uuid, lambda { |id| where('binary id = ? OR uuid = ?', id, id) }
This ensures that the id string is taken by its binary value instead of being converted into an int. However, this will ONLY WORK WITH MYSQL BASED APPS