Skip to content

Commit

Permalink
add examples documenting new features
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Bessey committed Oct 30, 2017
1 parent 7b8cfa6 commit 5f21a87
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ that you can set version constraints properly.
#### [v1.0.4](https://github.com/exAspArk/batch-loader/compare/v1.0.3...v1.0.4)

* `Fixed`: Fix arity bug in `respond_to?` [#3](https://github.com/exAspArk/batch-loader/pull/3)
* `Added`: `default_value` override option.
* `Added`: `loader.call {}` block syntax, for memoizing repeat calls to the same item.

#### [v1.0.3](https://github.com/exAspArk/batch-loader/compare/v1.0.2...v1.0.3) – 2017-09-18

Expand Down
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ puts users # Users

But the problem here is that `load_posts` now depends on the child association and knows that it has to preload data for future use. And it'll do it every time, even if it's not necessary. Can we do better? Sure!

### Basic example
### Basic examples

With `BatchLoader` we can rewrite the code above:

Expand Down Expand Up @@ -125,6 +125,51 @@ puts users # Users SELECT * FROM users WHERE id IN

As we can see, batching is isolated and described right in a place where it's needed.

For batches where there is no item in response to a call, we normally return nil. However, you can use `default_value:` to return something else instead. This is particularly useful for 1:Many relationships, where you

```ruby
def load_posts(ids)
Post.where(id: ids)
end

def load_user(post)
BatchLoader.for(post.user_id).batch(default_value: NullUser.new) do |user_ids, loader|
User.where(id: user_ids).each { |user| loader.call(user.id, user) }
end
end

posts = load_posts([1, 2, 3])


users = posts.map do |post|
load_user(post)
end

puts users
```

For batches where the value is some kind of collection, such as an Array or Hash, `loader` also supports being called with a block, which yields the _current_ value, and returns the _next_ value. This is extremely useful for 1:Many relationships:

```ruby
def load_users(ids)
User.where(id: ids)
end

def load_comments(user)
BatchLoader.for(user.id).batch(default_value: []) do |comment_ids, loader|
Comment.where(user_id: user_ids).each do |comment|
loader.call(user.id) { |memo| memo.push(comment) }
end
end
end

users = load_users([1, 2, 3])

comments = users.map do |user|
load_comments(user)
end
```

### How it works

In general, `BatchLoader` returns a lazy object. Each lazy object knows which data it needs to load and how to batch the query. As soon as you need to use the lazy objects, they will be automatically loaded once without N+1 queries.
Expand Down

0 comments on commit 5f21a87

Please sign in to comment.