DEV Community

Cover image for Rails Meets GraphQL: How to Master context and find_by with Examples
Takehiro_Yamazaki
Takehiro_Yamazaki

Posted on

1 1 1 1 1

Rails Meets GraphQL: How to Master context and find_by with Examples

Introduce

Ever wondered how to fetch data in Rails with GraphQL without overcomplicating things? You’ve got two trusty tools: context and find_by. Choosing the right one can make your code cleaner, your queries faster, and your app easier to maintain.

In this guide, I’ll break down their differences, walk you through real examples, and share some lessons learned from working with both in production.

⚠️ Note: This guide is based on my own experience. Depending on your project’s architecture, there might be some nuances or edge cases not covered here.


🔍 What’s the Deal with context and find_by?

Let’s start with the basics—what each one actually does.

🕵️‍♂️ find_by: The Database Detective

  • Searches the database based on given conditions.
  • Executes a fresh query every time—no caching.
  • Returns nil if no match (use find_by! to raise an error instead).
  • Doesn’t rely on model relationships—works anywhere.

🤝 context: The Request Sidekick

  • Stores temporary data shared across a GraphQL request.
  • Holds things like context[:current_user] for quick access.
  • Helps avoid redundant database calls by reusing already-fetched data.
  • Especially useful for accessing data tied to the logged-in user.

✅ When context Saves the Day

If you're fetching data tied directly to the authenticated user, context is your best friend.

Example: Fetching a User Profile

# File: app/graphql/types/auth_query_type.rb
module Auth
  module Types
    class AuthQueryType < Base::Types::BaseObject
      field :user_profile, Auth::Types::ProfileType, null: false,
            description: "Gets the current user's profile."

      def user_profile
        # Grabs the profile via the user’s relationship—no extra query needed
        context[:current_user].profile
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Why it works:

Since context[:current_user] is already loaded, calling .profile just uses the ActiveRecord association—no additional database hit. This is perfect for performance-sensitive routes.


🔎 When find_by Takes the Lead

Sometimes you need more control—specific filters, IDs, or permissions. That’s where find_by comes in.

Example: Finding a Post by ID

# File: app/graphql/types/auth_query_type.rb
module Auth
  module Types
    class AuthQueryType < Base::Types::BaseObject
      field :post, Auth::Types::PostType, null: false do
        argument :id, ID, required: true
      end

      def post(id:)
        # Finds a post matching the ID and user, throws an error if not found
        Post.find_by!(id: id, user_id: context[:current_user].id)
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Why use find_by!?

You're filtering not just by ID, but also by user_id—something relationships alone can't express. And with find_by!, you make sure an error is raised if the post doesn’t exist. (Use find_by if you’re okay with getting nil.)


🧠 Your Cheat Sheet for Choosing

Scenario context find_by
Fetching logged-in user data
Searching by a specific ID
Accessing data via relationships
Adding custom filters
Handling records that might be nil

Rule of thumb:

Use context for relationship-driven access. Use find_by when you need fine-grained filters or extra logic.


💭 My Two Cents from the Trenches

After using both in real-world Rails + GraphQL apps, here’s how I approach the decision:

🔄 Why I Reach for context

def profile
  context[:current_user].profile # Clean, quick, done
end
Enter fullscreen mode Exit fullscreen mode

If the data is tied to a user and you already have the user loaded, context gives you a fast, elegant solution. I’ve seen it reduce database queries significantly.

🔍 Why find_by Still Has Its Place

def published_post(post_id:)
  Post.find_by(id: post_id, status: 'published') # Filters like a champ
end
Enter fullscreen mode Exit fullscreen mode

Need filters? Want to find data that may or may not exist? Dealing with permissions? That’s find_by territory.


🚀 Wrapping Up: Your Action Plan

Here’s how to apply what you’ve learned:

  • Use context[:current_user] when working with logged-in user relationships.
  • Use find_by when:
    • You need to filter with custom conditions.
    • You're fetching another user’s data (with proper permission checks).
    • A record might not exist and you need graceful handling.

Mastering this distinction keeps your codebase clean, performant, and maintainable.


📚 Further Reading


Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay