Git Product home page Git Product logo

Comments (7)

mrkamel avatar mrkamel commented on May 26, 2024

Hi,

as you see within the sql output, ActiveRecord auto-assigns the following aliases:

LEFT OUTER JOIN "users" ON "users"."id" = "jobs"."customer_id"
LEFT OUTER JOIN "users" "technicians_jobs" ON "technicians_jobs"."id" = "jobs"."technician_id"
LEFT OUTER JOIN "users" "authors_jobs" ON "authors_jobs"."id" = "jobs"."author_id"

Thus, users => customer, technicians_jobs => technician, authors_jobs => author.
Unfortunately, SearchCop can't rewrite those names (yet). Thus, you have 2 options:

Option a)

Do the join yourself using a scope {} block. The rest can stay as is.

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['customer.name', 'customer.email', 'customer.phone']
  attributes :technician => ['technician.name', 'technician.email', 'technician.phone']
  attributes :author     => ['author.name', 'author.email', 'author.phone']

  scope do
    joins("left outer join users customer on customer.id = jobs.customer_id").joins("left outer join users technician on technician.id = jobs.technician_id").joins("left outer join users author on author.id = jobs.author_id")
  end
end

Don't forget to additionally preload customer, technichian and author in your controller to avoid N+1 in your views.

Option b)

Use the aliases auto-assigned by ActiveRecord and tell SearchCop how to map them to your models:

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['users.name', 'users.email', 'users.phone']
  attributes :technician => ['technicians_jobs.name', 'technicians_jobs.email', 'technicians_jobs.phone']
  attributes :author     => ['authors_jobs.name', 'authors_jobs.email', 'authors_jobs.phone']

  aliases :technicians_jobs => :user, :authors_jobs => :user
end

I'd be glad to know if this works for you and which option you'll choose ...

from search_cop.

mbajur avatar mbajur commented on May 26, 2024

Thanks for your fast reply, mrkamel! I would love to use option b. I have tried your code but right now, the produced SQL query looks like this: https://gist.github.com/mbajur/e20ea5d26f8060606621

There are no joins for technicians_jobs nor authors_jobs so the query throws an exception. It's probably something trivial but, to be honest, i have no idea what's going on in here so i'm not sure what can i possibly do by myself to fix that. Sorry for this, it's probably caused by late night hours and sharp deadline. However, i WOULD LOVE to use search_cop for allmost all of my future projects cause it's perfect. Just that small glitch...


Edit: I have also tried option a and the generated query is: https://gist.github.com/mbajur/bbd560f4a1713bf68b37 (so it's obviously wrong, the where part)

from search_cop.

mrkamel avatar mrkamel commented on May 26, 2024

Ok, sry. For option B) you have to alias your associations (technician and author) instead of user. Otherwise SearchCop only eager loads user. That's the reason for the missing joins in your SQL output.

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['users.name', 'users.email', 'users.phone']
  attributes :technician => ['technicians_jobs.name', 'technicians_jobs.email', 'technicians_jobs.phone']
  attributes :author     => ['authors_jobs.name', 'authors_jobs.email', 'authors_jobs.phone']

  aliases :technicians_jobs => :technician, :authors_jobs => :author
end

Regarding option A), an alias definition is missing. Try this one instead:

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['customers.name', 'customers.email', 'customers.phone']
  attributes :technician => ['technicians.name', 'technicians.email', 'technicians.phone']
  attributes :author     => ['authors.name', 'authors.email', 'authors.phone']

  scope do
    joins("left outer join users customers on customers.id = jobs.customer_id").joins("left outer join users technicians on technicians.id = jobs.technician_id").joins("left outer join users authors on authors.id = jobs.author_id")
  end

  aliases :customers => :customer, :technicians => :technician, :authors => :author
end

from search_cop.

mbajur avatar mbajur commented on May 26, 2024

Yes! That's it! Now it's working just fine. Thank you for your time, mrkamel! :)

Just a small thing - for option B - users in attributes :customer should be singular

from search_cop.

mrkamel avatar mrkamel commented on May 26, 2024

Yeah, you should probably change it even to customers_jobs and subsequently add the alias.
Otherwise SearchCop assumes you're referencing the :user association.

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['customers_jobs.name', 'customers_jobs.email', 'customers_jobs.phone']
  attributes :technician => ['technicians_jobs.name', 'technicians_jobs.email', 'technicians_jobs.phone']
  attributes :author     => ['authors_jobs.name', 'authors_jobs.email', 'authors_jobs.phone']

  aliases :customers_jobs => :customer, :technicians_jobs => :technician, :authors_jobs => :author
end

from search_cop.

mrkamel avatar mrkamel commented on May 26, 2024

However, ActiveRecord will probably use users as alias name, as long as you don't reference the user association itself. Thus:

search_scope :search do
  attributes :status, :customer_id, :technician_id, :author_id, :ro_number,
             :end_behaviour, :ro_value, :created_at

  attributes :customer   => ['users.name', 'users.email', 'users.phone']
  attributes :technician => ['technicians_jobs.name', 'technicians_jobs.email', 'technicians_jobs.phone']
  attributes :author     => ['authors_jobs.name', 'authors_jobs.email', 'authors_jobs.phone']

  aliases :users => :customer, :technicians_jobs => :technician, :authors_jobs => :author
end

from search_cop.

mrkamel avatar mrkamel commented on May 26, 2024

Well, that's the reason i'd prefer option A) for such a case. Consistent and nice naming.

from search_cop.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.