简体   繁体   中英

Rails find records tagged with multiple tags | undefined method 'where' for Array

So I want to build a jobsboard, with jobs which are tagable. I want to implement it by myself, so I followed this tutorial: https://www.sitepoint.com/tagging-scratch-rails/

all works, but i want to get not only all jobs which are tagged with one tag (the tutorial has a method for that tagged_with(name) ) but instead I want to get all jobs which are tagged with multiple tags.

So i added a method to the job.rb model as followed:

def self.tagged_with_tags(tags)
    jobs = []
    tags.each do |tag|
        Jobtag.where(name: tag).first.jobs.map do |j|
            jobs.push(j) unless jobs.include?(j)
            puts j
        end
    end
    jobs
end

That seems to work, but I want to query the returned array further like:

@jobs = Job.tagged_with_tags(@tags).where(category: 'Full-Budget').order('created_at desc')

And here I get this Error: undefined method 'where' for #<Array:0x007fb1b0a25c10>


Here are my models:

job.rb

class Job < ActiveRecord::Base
    has_many :taggings
    has_many :jobtags, through: :taggings

    def all_jobtags=(names)
        self.jobtags = names.split(",").map do |name|
            Jobtag.where(name: name.strip.downcase).first_or_create!
        end
    end

    def all_jobtags
        self.jobtags.map(&:name).join(", ")
    end

    def self.tagged_with(name)
        Jobtag.find_by_name!(name.downcase).jobs
    end

    # Needs work:
    def self.tagged_with_tags(tags)
        jobs = []
        tags.each do |tag|
            Jobtag.where(name: tag).first.jobs.map do |j|
                jobs.push(j) unless jobs.include?(j)
                puts j
            end
        end
        jobs
    end

end

Jobtag.rb

class Jobtag < ActiveRecord::Base
    has_many :taggings
    has_many :jobs, through: :taggings
end

Tagging.rb

class Tagging < ActiveRecord::Base
    belongs_to :job
    belongs_to :jobtag
end

You can get the desired result with active record joins query. Iterating through each job objects and pushing it to array is less efficient.

@tags = ['tag_name1', 'tag_name2']

Something like this:

@jobs = Job.joins(:jobtags).where(jobtags: { name: @tags }).
          where(category: 'Full-Budget').
          order('created_at desc')

Update

If you want to fetch jobs which have all the tags listed in @tags array, check count of jobtags in the same query.

@jobs = Job.joins(:jobtags).where(jobtags: { name: @tags }).
          group('jobs.id').
          having('count(jobs.id) = ?', @tags.size).
          where(category: 'Full-Budget').
          order('created_at desc')

Hope it helps !

要使用.where您需要有一个 ActiveRecord 集合。

Job.joins(:job_tags).where("jobs_tags: { name: "name of tag or array of tag names").where(category: 'Full-Budget').order('created_at desc')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM