Skip to content

Instantly share code, notes, and snippets.

@AlxGolubev
Last active April 7, 2017 17:25
Show Gist options
  • Save AlxGolubev/075c4471c7b6f2548bff to your computer and use it in GitHub Desktop.
Save AlxGolubev/075c4471c7b6f2548bff to your computer and use it in GitHub Desktop.

Revisions

  1. @llait llait renamed this gist Oct 4, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. @llait llait revised this gist Jul 15, 2015. No changes.
  3. @llait llait revised this gist Jul 7, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Associations Rails
    Original file line number Diff line number Diff line change
    @@ -15,13 +15,13 @@ Post.find_by_sql "SELECT p.name, c.author FROM posts p, comments c WHERE p.id =

    Для того чтобы избежать `select(n+1)` в данном случае необзодимо использовать:

    #Rails 3
    # Rails 3
    ```
    @users = User.find_by_sql(some_condition)
    ActiveRecord::Associations::Preloader.new(@users, :posts).run
    ```

    #Rails 4
    # Rails 4

    ```
    @users = User.find_by_sql(some_condition)
  4. @llait llait revised this gist Jul 6, 2015. No changes.
  5. @llait llait revised this gist Jul 6, 2015. No changes.
  6. @llait llait revised this gist Jul 6, 2015. No changes.
  7. @llait llait renamed this gist Jul 6, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  8. @llait llait revised this gist Jul 6, 2015. No changes.
  9. @llait llait revised this gist Jul 6, 2015. No changes.
  10. @llait llait created this gist Jul 6, 2015.
    44 changes: 44 additions & 0 deletions Associations Rails.
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,44 @@
    При выполнении сложных запросов, часто бывает необходимо выполнить предзагрузку данных об ассоциациях какой либо модели.
    Обычно сложные запросы выполняються через `find_by_sql`, например

    ```
    Post.find_by_sql "SELECT p.name, c.author FROM posts p, comments c WHERE p.id = c.post_id"
    > [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]
    ```

    Чтобы при вывзове ассоциаций объектов избежать проблемы с `select(n+1)` запросами в Rails существует eager-loading, например:

    ```
    @users = User.where(status: 'activated').includes(:posts)
    ```
    Благодаря такой конструкции при вызове `@users.first.posts` не будет произведен еще один дополнительный запрос для подгрузки постов, но это не работает с `find_by_sql`, так как этот метод вернет массив, а не `ActiveRecord::Relation` объект.

    Для того чтобы избежать `select(n+1)` в данном случае необзодимо использовать:

    #Rails 3
    ```
    @users = User.find_by_sql(some_condition)
    ActiveRecord::Associations::Preloader.new(@users, :posts).run
    ```

    #Rails 4

    ```
    @users = User.find_by_sql(some_condition)
    ActiveRecord::Associations::Preloader.new.preload(@users, :posts)
    ```
    В качестве первого аргумента выступает массив записей, второго - желаемая ассоциация.
    Также существует возможность в качестве параметров передать массив ассоциаций или хещ с ассоциациями ассоциация, например:

    ```
    @users = User.find_by_sql(some_condition)

    #Array of associations
    ActiveRecord::Associations::Preloader.new.preload(@users, %i(posts images))

    #Hash to eager load associations of associations
    ActiveRecord::Associations::Preloader.new.preload(@users, {posts: :comments})

    #Or combination of array and hash
    ActiveRecord::Associations::Preloader.new.preload(@users, [:images, { posts: :comments }])
    ```