Ruby on Rails application implementing an API using GraphQL. The API listens on path /graphql
and responds to POST
requests. The /graphiql
endpoint is available to explore the API using graphical tool called GraphiQL.
PostgreSQL is used as database for ActiveRecord
The application consists of 2 models User and Transaction. The User model is used for authentication using devise. It holds information about registered users and referrals. The Transaction model holds information about the account transactions of the user. The type of transaction is determined by code
column. Appication implements 2 types of transactions (REFERRER_BONUS
and REFERRALS_BONUS
). New transaction types should be added by implementing new codes.
The application implements 2 types of rewards that can be achieved upon registration ReferredBonus and ReferralsBonus. Each reward business logic is implemented in a service object in services/user_services/
.
ReferredBonus adds fixed amount to user's account if the registered user used a valid referral token.
ReferralsBonus adds fixed amount to user's account if 5 new users registered using user's referral token
Ruby on Rails, PostgreSQL, RSpec and Graphql was used because of my personal preference. The devise
and devise-jwt
gems were used for authentication instead of implementing custom authentication method because it is battle tested by the community.
Two different rewards were identified and implemented as separate service objects. Unit and integration tests are used to maintain working functionality of these objects.
The account balance was implemented using Transaction model to support extensibility.
The application implements following GraphQL Schema:
"""
Autogenerated return type of Login
"""
type LoginPayload {
error: String
jwt: String
success: Boolean!
}
type Mutation {
login(email: String!, password: String!): LoginPayload
register(email: String!, password: String!, passwordConfirmation: String!, referralToken: String): RegisterPayload
}
type Query {
currentUser: User
}
"""
Autogenerated return type of Register
"""
type RegisterPayload {
errors: [String!]
"""
Result of the registration process
"""
success: Boolean!
user: User
}
type User {
balance: Float!
email: String!
id: ID!
referralToken: String
}
It is expected for the front-end developer to understand how GraphQL API works and how to use the schema types.
Application uses JWT based authentication implemented using battle tested gems devise and devise-jwt.
The client logs in using register
mutation and receives JWT token. This token is valid ofr 12 hours and identifies authenticated request when included in the HTTP headers of the API request:
Header Name: Authorization
Header Value: Bearer <token>
Clone the repository and install gems using Bundler
$ git clone https://github.com/tulak/referrals.git referrals
$ cd referrals
$ bundle
Create database and migrate the schema
$ rails db:create
$ rails db:migrate
Run tests
$ rspec spec/