SORA
SORA

Reputation: 77

How can I include wildcards in Ruby include? to query for non-exact (but similar) matches?

I'm making a dating app. Each user has his own traits (UserTraits) and the traits he desires in others (DesiredTraits). A user can check if his traits match those desired by another user.

@user's desired trait show view (current_user checks a desired trait of @user)

- @current_user_traits = UserTrait.where("user = ?", current_user)
- @user_desired_trait = DesiredTrait.find(params[:id])

- if @current_user_traits.map {|a| a.trait_name}.include? @user_desired_trait.trait_name
  @matching_traits = UserTrait.where("user = ? AND trait_name LIKE ?", current_user, "%#{@user_desired_trait.trait_name}%")
- else 
  | "Sorry, you don't have traits desired by User"

However, this only fills @matching_traits if there is an exact match between @current_user_trait.trait_name and @user_desired_trait.trait_name, as I don't know how to put wildcards in the include? query.


Update:

There are 2 traits models which belong to a user: UserTraits and DesiredTraits.

I used grep on an array, but it only returns true if the string is the same or if the string in grep is shorter than the one in the array:

- if @current_user_traits.map {|a| a.trait_name}.grep(/#{@user_desired_trait.trait_name}/)

How can I do a basic "full text search fuzzy query" on the array from the view (like what LIKE does)?

Upvotes: 1

Views: 2123

Answers (2)

max
max

Reputation: 102046

The underlying problem here is poor database design. You should use one table to store the normalized traits and a seperate table to join users and traits.

class User < ApplicationRecord
  has_many :user_traits
  has_many :traits, through: :user_traits
end

class Trait < ApplicationRecord
  has_many :user_traits
  has_many :users, through: :user_traits
end

class UserTrait < ApplicationRecord
  belongs_to :user
  belongs_to :trait
end

The whole point here is that you use ids instead of slow searches on a text column - it also avoids duplicate data. Another big issue is that your approach will not support localization.

If you want to check if a user has a trait you would just do:

user.traits.include?(trait)

This is basically the same method you would use for tags, categories or any kind of classification.

Upvotes: 1

gwcodes
gwcodes

Reputation: 5690

If you're happy with a wildcard match that works the same way as LIKE in SQL, then it's worth noting that you can grep an Enumberable.

So say you have a list of traits that some would find desirable:

traits = ["funny", "smart", "has adorable dimples"]

And you wanted to search for "adorable":

trait_name = "adorable"
traits.grep /#{trait_name}/
#=> ["has adorable dimples"]

traits.grep(/#{trait_name}/).any?
#=> will return true/false, just like include?

Upvotes: 2

Related Questions