Home > Mobile >  Create one relation from different scopes in Rails
Create one relation from different scopes in Rails

Time:12-08

I have a method which get the scope and produce the link to filtered page. This link looks like number of reports

def other_total_reports(subjects, action, due_in = nil, locale_clause = nil)
    scopes = []

    scopes << due_in if due_in

    count = scopes.inject(subjects) { |obj, method| obj.public_send(method) }.count
   
    link_to count, { controller: 'user_reports', action: action, filter: filter }, class: ("overdue" if due_in == (:overdue)), target: "_blank"
end

Should count total unprocessed reports but the total number was not quite accurate because of some filters on different relations(scopes), so when I pass subjects

UserReports.unprocessed

it didn't works well. To get the correct number I must combine the specific scopes which was already counted and pass as subjects

UserReports.unprocessed.videos, UserReports.unprocessed.public_chats, UserReports.unprocessed.answers_only, UserBlockLog.unprocessed.photos, UserReports.unprocessed.questions_only.questions_reasons, UserReports.unprocessed.profiles.profiles_reasons

Later this scope must be used, so it should be an ActiveRecord::Relation which excludes arrays methods. Thank you guys for help!

CodePudding user response:

Found this way as solution:

    total = UserReports.unprocessed.videos, 
            UserReports.unprocessed.public_chats, 
            UserReports.unprocessed.answers_only, 
            UserReports.unprocessed.photos, 
            UserReports.unprocessed.questions_only.questions_reasons, 
            UserReports.unprocessed.profiles.profiles_reasons

    @reports_total = UserReports.where(id: total.map(&:id))

CodePudding user response:

If you scopes have 'where' clauses only, you can use "or" to join your scopes into only one record

scopes.each_with_object(subjects).inject(nil) do |memo, (scope, original_record)|
  # Applies the scope to your record
  result = original_record.public_send(scope)
  # You can`t apply your "or" if you don't have any of your scopes applied already
  # So we skip the first iteraction
  next result unless memo

  memo.or(result)
end

If your scopes do have more clauses than 'where', you can use ActiveRecord::QueryMethods#includes_values to include all your scopes "includes" values to use the "include" clause at least

If the other clauses are too complex to join like 'select', 'from', or 'group by', than it would have to adapt each one of them to maybe use an "union" in each scope, and even then, 'group by' clauses for example would not work well, so specify in your question how complex are your scopes if your problem is still not solved

  • Related