Reputation: 77
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.
- @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.
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
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
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