ihara2525/marks — pull request #8 by k0kubun (2014-12-10 13:21:18+00:00)
Title: Add preload_marker query method

## Problem

`marked_by?` tends to execute N+1 count query. Currently we have no way to avoid this.
It has a bad influence on performance.

```ruby
> Topic.limit(3).map{ |topic| topic.marked_by?(user, :agree) }
# Topic Load (0.2ms) SELECT "topics".* FROM "topics" LIMIT 3
# (0.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "marks_marks" ON "marks_marks"."marker_id" = "users"."id" AND "marks_marks"."marker_type" = 'User' WHERE (marks_marks.mark_type = 'Agree' AND markable_type = 'Topic' AND markable_id = 1)
# (0.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "marks_marks" ON "marks_marks"."marker_id" = "users"."id" AND "marks_marks"."marker_type" = 'User' WHERE (marks_marks.mark_type = 'Agree' AND markable_type = 'Topic' AND markable_id = 2)
# (0.1ms) SELECT COUNT(*) FROM "users" INNER JOIN "marks_marks" ON "marks_marks"."marker_id" = "users"."id" AND "marks_marks"."marker_type" = 'User' WHERE (marks_marks.mark_type = 'Agree' AND markable_type = 'Topic' AND markable_id = 3)
=> [true, false, false]
```

## Solution

I propose `preload_marker` method to resolve it, which acts like `preload` or `includes` method. With this method, you can eargerly load `marked_by?` result without N+1 count query.

```ruby
Topic.limit(3).preload_marker(user, :agree).map{ |topic| topic.marked_by?(user, :agree) }
# Topic Load (0.2ms) SELECT "topics".* FROM "topics" LIMIT 3
# (0.2ms) SELECT "marks_marks"."markable_id" FROM "marks_marks" WHERE "marks_marks"."markable_type" = 'Topic' AND "marks_marks"."markable_id" IN (1, 2, 3) AND "marks_marks"."marker_type" = 'User' AND "marks_marks"."marker_id" = 1 AND "marks_marks"."mark_type" = 'Agree'
=> [true, false, false]
```

If you don't call `preload_marker` on relation, it behaves as the same as before.