1

I have a tagging system in rails using postgres' array data type. I'm trying to write a scope that will return any posts that include a tag. So far I have this scope working:

scope :with_tag, ->(tag) { where("tags @> ARRAY[?]", tag) }

I want to extend this scope so that I can query on multiple tags at the same time, ideally something like:

Post.with_tags(['some', 'tags', 'to', 'query'])

Which would return any Post that have one of those tags. I've thought about making a class method to handle iterating over the input array:

def self.with_tags(args)
  # start with empty activerecord relation
  # want to output AR relation
  results = Post.none
  args.each do |tag|
    results = results.concat(Post.with_tag(tag))
  end
  results.flatten
end

but this approach smells funny to me because it's creating a new query for each argument. It also doesn't return an ActiveRecord::Relation because of flatten, which I would really like to have as the output.

Can I accomplish what I'm after in a scope with an OR query?

2
  • 1
    You're really trying to do an array intersection right? You have an array of strings in the tags column and an array of strings in the Ruby args variable and you want rows where those arrays overlap? Commented Dec 31, 2014 at 18:25
  • Yes, I think. Except I want all of the tags that contain any of the values in args, they do not need to match all of the args Commented Dec 31, 2014 at 18:27

1 Answer 1

9

I'm not running the code but I think the && operator does what you want:

scope :with_tags, ->(tags) { where("tags && ARRAY[?]", tags) }
1
  • is there any ability to perform case-insensitive search? Commented Oct 20, 2017 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.