- Initial Configuration
- Generate a New Rails API
- Gem Additions
- First Migration
- New Graphql Generator
- Schema, Types
In this blog, I'll be covering how to create an initial Rails backend API utilizing Graphql. If you don't know Graphql, if you're familiar with it or just need a refresher, this blog is for you.
Let's generate a new API-only application. I won't be using most of the gems that come with a new rails generation, so the command I will use with numerous options is:
rails new vacationme_backend --api --database=postgresql --skip-action-mailer --skip-action-mailbox --skip-action-cable
- Uncomment the
graphiql-rails hasn't been updated since January of 2019. There are many pull requests and issues stated, and quite a few direct you to how the application can begin working again. I will show you how you can do so further down.
config/initializers/cors.rb, uncomment the following code:
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post, :patch, :put] end end
For Rails, you'll need to add this middleware on application startup. A practical way to do this is with an initializer file. For example, the following will allow GET, POST, PATCH, or PUT requests from any origin on any resource:
insert_beforeto make sure
Rack::Corsruns at the beginning of the stack to make sure it isn't interfered with by other middleware (see
Rack::Cachenote in Common Gotchas section). Basic setup examples for Rails 5 & Rails 6 can be found in the examples/ directory.
config.hosts << "localhost"
Rails 6 has support for blocking requests from unknown hosts, so origin domains will need to be added there as well.
A more detailed reason for this addition can be found here in the Ruby on Rails Guide.
Graphql will be interacting with ActiveRecord. We will have to create our migrations and models as we normally would. I am using the
bcrypt gem, so instead of a
password field, it will be a
rails g model user name:string username:string password_digest:string
Remember to include
app/models/user.rb. Now let's write two seeds in
User.create( name: "John Doe", username: "JohnDoe", password: "123" ) User.create( name: "Ethan Gustafson", username: "GoodGuyGuf", password: "123" )
graphiql-rails gem enables one route in your application where you can open a browser and develop using an IDE for graphql.
After navigating through the issues, I stumbled onto the best solution I could use without changing much of the code I currently have. It can be found here in this issue.
graphiql-rails guide normally.
# config/routes.rb post "/graphql", to: "graphql#execute" if Rails.env.development? mount GraphiQL::Rails::Engine, at: "/graphiql", graphql_path: "graphql#execute" end
You would navigate to "/graphiql" in your browser, and the path would still use the
Sprockets is a Ruby library for compiling and serving web assets.
To create the last fix, run
touch app/assets/config/manifest.js to create a manifest.js file. Put this inside of it:
//= link graphiql/rails/application.css //= link graphiql/rails/application.js
That's all. This is so the gem can link to the CSS and js it defined in its own files. Now we can begin building the types.
Now that we have a user and a record, we can generate the
graphql install. Run:
rails generate graphql:install
This will create:
graphqldirectory containing two subdirectories and one file:
mutations, which contains 1 file
types, which contains 10 files
To keep it simple I won't go into detail about the mutations directory.
GraphQL cannot execute a query without a type system.
There are object, mutation, query, scalar, enumeration, interfaces, union, and input types.
Every GraphQL service defines a set of types which completely describe the set of possible data you can query on that service. Then, when queries come in, they are validated and executed against that schema.
Before building a schema, you have to define an entry point to your system, which is called the “query root”. The query root will be the
# app/graphql/types/query_type.rb module Types class QueryType < Types::BaseObject # Add root-level fields here. # They will be entry points for queries on your schema. # First describe the field signature: field :user, UserType, null: true do description "Find a User by ID" argument :id, ID, required: true end def user(id:) User.find(id) end end end
module Types class UserType < Types::BaseObject field :id, ID, null: false field :name, String, null: false field :username, String, null: false field :password, String, null: false end end
Including the root query in the schema ensures that the application is now functional. Run
rails s. Your application should be working normally, and you can run queries on the types above without a problem.
# app/graphql/vacationme_backend_schema.rb class VacationmeBackendSchema < GraphQL::Schema mutation(Types::MutationType) query(Types::QueryType) # Opt in to the new runtime (default in future graphql-ruby versions) use GraphQL::Execution::Interpreter use GraphQL::Analysis::AST # Add built-in connections for pagination use GraphQL::Pagination::Connections end