Search code examples
ruby-on-railsrails-activerecordruby-on-rails-6.1

Rails 6.1 | Is there a way to check which associations have already been joined to a scope?


I have a little framework for dynamically constructing queries in rails (v6.1.7.3) based upon a json request from the front-end. As the use-cases keep growing, one thing that has been a bit of a pain to manage generically is having a way to keep track of which associations have already been joined to a given query scope as well as the alias used for those associations (if applicable)

Is there a built-in mechanism that I can use to determine if a given association has already been joined? And is there a means of determining an association's alias?

Thanks!

scope = MyModel.where(...)
...
scope.joins!(:assoc)
...
# how to determine if :assoc has already been joined to scope?

Solution

  • Rails do it work for you, you don't need to check if some association is already used:

    self.joins_values |= args
    

    Here Array#| method is used. It returns the union of arrays, duplicates are removed:

    ary = [1]
    ary |= [1, 2]
    ary |= [2, 3]
    ary # => [1, 2, 3]
    

    But you can check it with joins_values or / and left_outer_joins_value method. These methods return array of associations (symbol array) and work such way:

    MyModel.joins(:assoc).where(condition).joins_values
    # => [:assoc]
    
    MyModel.where(condition).joins_values
    # => []
    
    MyModel.left_joins(:assoc).where(condition).left_outer_joins_values
    # => [:assoc]
    
    MyModel.where(condition).left_outer_joins_values
    # => []
    

    There are also includes_values, eager_load_values, preload_values methods:

    MyModel.includes(:assoc).where(condition).includes_values
    # => [:assoc]
    
    MyModel.where(condition).includes_values
    # => []
    
    MyModel.eager_load(:assoc).where(condition).eager_load_values
    # => [:assoc]
    
    MyModel.where(condition).eager_load_values
    # => []
    
    MyModel.preload(:assoc).where(condition).preload_values
    # => [:assoc]
    
    MyModel.where(condition).preload_values
    # => []