我正在试图弄清楚如何将多个范围链接在一起。我要做的是有一个搜索框,它将params [:user_search]传递给控制器,该控制器调用用户模型中的by_keyword范围。 by_keyword范围正在我现在的工作,但我想让它也搜索我所有的其他范围。因此,基本上,by_keyword范围应查询用户输入的任何关键字的所有范围。
在我的users_controller索引操作
中 if params[:user_search].present?
@users = @users.by_keyword(params[:user_search])
end
在我的用户模型中
scope :by_keyword, -> (keyword) { where('experience LIKE ? OR current_job_title LIKE ?', "%#{keyword}%", "%#{keyword}%" ).order(updated_at: :desc) if keyword.present? }
我想找到一种方法将所有这些链接到by_keyword范围
# these scopes call child classes of User such as skills, languages, patents, etc...
scope :by_skill, -> (sk) { joins(:skills).distinct.where( 'skills.name LIKE ?', "%#{sk}%" ).order(updated_at: :desc) if sk.present? }
scope :by_language, -> (lang) { joins(:languages).distinct.where( 'languages.language LIKE ?', "%#{lang}%" ).order(updated_at: :desc) if lang.present? }
scope :by_certification_or_cert_authority, -> (cert) { joins(:certifications).distinct.where( 'certifications.certification_name LIKE ? OR certifications.certification_authority LIKE ?', "%#{cert}%", "%#{cert}%" ).order(updated_at: :desc) if cert.present? }
scope :by_education_level, -> (ed) { joins(:qualifications).distinct.where( 'qualifications.education LIKE ?', "%#{ed}%" ).order(updated_at: :desc) if ed.present? }
scope :by_university_major, -> (maj) { joins(:qualifications).distinct.where( 'qualifications.university_major LIKE ?', "%#{maj}%" ).order(updated_at: :desc) if maj.present? }
我读过http://guides.rubyonrails.org/active_record_querying.html#scopes
他们给出的例子就是这个,但我不知道如何用超过2个链接在一起的范围来做到这一点。
class Article < ApplicationRecord
scope :published, -> { where(published: true) }
scope :published_and_commented, -> { published.where("comments_count > 0") }
end
答案 0 :(得分:0)
你可以通过在用户控制器中创建一个调用send的函数并给它一个像here
这样的数组来实现。在用户模型中
def self.send_chain(methods)
methods.inject(self, :send)
end
然后将其称为
User.send_chain(["by_skill", "by_language"])
如果你必须发送params,你可以这样做:
scopes = ["by_skill", "by_language"]
parameters = ["clever", "English"]
result = []
scopes.each_with_index do |scope, index|
result = result + User.send(scope, parameters[index])
end
希望这有帮助。
答案 1 :(得分:0)
试试这个:
scope :all_clild, -> (val) { |val| by_skill(val).or.by_language(val).or.by_certification_or_cert_authority(val).........# all other scopes}
merged_scope = by_keyword.merge(all_clild)
答案 2 :(得分:0)
我能够将参数传递给像这样的范围
scope :by_keyword, -> (k) { by_skill(k) | by_language(k) | by_certification_or_cert_authority(k) | by_education_level(k) | by_university_major(k)}
我不确定这是否真的被认为是“链接”他们。我猜这可能有更好的方法,如果有,请告诉我。
它正在进行大量的查询,所以我不确定这是否是明智的,即使这么多的范围被称为它们的方式。这是搜索术语“CCNA”时的结果
User Load (0.5ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "skills" ON "skills"."user_id" = "users"."id" WHERE (skills.name LIKE '%CCNA%') ORDER BY "users"."updated_at" DESC
User Load (0.5ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "languages" ON "languages"."user_id" = "users"."id" WHERE (languages.language LIKE '%CCNA%') ORDER BY "users"."updated_at" DESC
User Load (0.6ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "certifications" ON "certifications"."user_id" = "users"."id" WHERE (certifications.certification_name LIKE '%CCNA%' OR certifications.certification_authority LIKE '%CCNA%') ORDER BY "users"."updated_at" DESC
User Load (0.5ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "qualifications" ON "qualifications"."user_id" = "users"."id" WHERE (qualifications.education LIKE '%CCNA%') ORDER BY "users"."updated_at" DESC
User Load (0.5ms) SELECT DISTINCT "users".* FROM "users" INNER JOIN "qualifications" ON "qualifications"."user_id" = "users"."id" WHERE (qualifications.university_major LIKE '%CCNA%') ORDER BY "users"."updated_at" DESC
同样从安全角度来看,我不确定允许用户输入触及这么多表的一个查询是否一件好事。