Parameterized GraphQL Fields!?!?!

Do you love GraphQL, but lament the inability to query values that depend on passed-in parameters? Great news, there is a solution: Parameterized GraphQL Fields!

Consider a query which returns some fun things about the user. One of which is their favorites! Favorites can return different categories of a user’s favorite things. For example you could pass in ‘books’ as a category, and get a list of the user’s favorite books. Or ‘cuisines’ to get a list of the user’s favorite… well you see where this is going!

Here’s the frontend code:

query user($user_id: ID, $category?: String) {
 user(user_id: $user_id) {
    id
    full_name
    favorites(category: $category)
  }
}

And the backend code, using graphql-ruby.

field :favorites, FavoriteType, 'Favorite things belonging to the user' do
argument :category, types.String
    resolve ->(user, args, ctx) {
      return user.favorites.where(category: args[:category])
    }
end

It’s just that easy—you really can have it all!

Update multiple records at once with Active Record

Have you ever found that you needed to update more than one record at a time? Rails has an elegant solution for this:

update_all

Updates all records in the current relation with details given. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks or validations. However, values passed to update_all will still go through Active Record’s normal type casting and serialization.

Say you are working with a library book tracking system. One user has returned three books today.

# user with id 100 checked out books:
  User.find(100).books.checked_out
> [
   #<Book id:1, title: 'The Hobbit', status: 'checked_out', user_id: 100>, 
   #<Book id:2, title: 'Children of Time', status: 'checked_out', user_id: 100>,
   #<Book id:3, title: 'The Count of Monte Cristo', status: 'checked_out', user_id: 100>
  ]

You could update each record individually using the commonly used update active record function, however rails also provides the update_all function:

checked_out_books = User.find(100).books.checked_out
checked_out_books.update_all(status: 'returned')

Which is great! We have successfully marked the books in the system as returned with one call to the database (instead of 3)!

Some things to consider when using this method:

  • this method does not trigger model callbacks
  • this method does not update the updated_at field automatically. However you can manually pass the current DateTime to updated_at.