Exchange aspires to be responsible for the various types of e-commerce interactions available on the Artsy platform. It's currently a prototype, with legacy e-commerce still handled by Gravity. It uses Ruby, Rails, Postgresql, and exposes a GraphQL API.
- State: production
- Production: https://exchange.artsy.net, Admin Dashboard | Sidekiq Dashboard
- Staging: https://exchange-staging.artsy.net, Admin Dashboard | Sidekiq Dashboard
- GitHub: https://github.com/artsy/exchange/
- Point People: @ashkan18, @williardx
PRs merged to
master are automatically deployed to staging by CI.
Mention in #dev slack channel that you are going to deploy and then run:
hokusai pipeline promote --git-remote upstream
upstream points to Artsy's repository.
Fork the project to your GitHub account
Clone your fork:
$ git clone firstname.lastname@example.org:your-github-username/exchange.git
$ bundle install
Once setup, you can run the tests like this:
$ bundle exec rspec
If this is your first time starting the app, make sure your database is setup first by running:
rails db:create rails db:setup
Then run Procfile.dev via foreman to start the web (rails) and worker (sidekiq) services:
foreman start -f Procfile.dev
Did You Change Models?
Papertrail Audit Logging
As Exchange persists important financial information, we use the PaperTrail gem to maintain a log of data changes to important models within the main relational database.
Exchange implements a slightly-customized, but supported, installation of PaperTrail. By default, PaperTrail writes audit log records to a single
versions table. In Exchange, we write audit logs into model-namespaced tables. For example, the audit log for
Order records are in the
order_versions table and the audit log for
Offer records are in the
Why do we do this? It'll allow PostgreSQL to query across smaller sets of data when operating against the audit log for a particular model.
How to implement this pattern for future models:
- Include the versioned model shared example in the spec for your model:
# spec/models/foo_spec.rb describe Foo, type: :model do ... it_behaves_like 'a papertrail versioned model', :foo ... end
- Ensure that a Fabricator factory exists for your model:
# spec/fabricators/foo_fabricator.rb Fabricator(:foo) do # define enough attributes to have a `valid?` instance of `Foo` end
- Include the customized PaperTrail DSL in your model (provides #versions):
# app/models/foo.rb class Foo < ApplicationRecord has_paper_trail class_name: 'PaperTrail::FooVersion' ... end
- Define the model-specific version class:
# app/models/paper_trail/foo_version.rb module PaperTrail class FooVersion < PaperTrail::Version self.table_name = :foo_versions end end
- Create the model-specific versions table:
bundle exec rails generate migration add_foo_versions
# db/migrate/timestamp_add_foo_versions.rb class AddFooVersions < ActiveRecord::Migration[5.2] def change create_table :foo_versions do |t| t.string :item_type, null: false t.uuid :item_id, null: false t.string :event, null: false t.string :whodunnit t.jsonb :object t.jsonb :object_changes t.datetime :created_at end add_index :foo_versions, %i[item_type item_id] end end
N.B: If the model being versioned uses a different type of primary key (i.e. integer instead of UUID), feel free to change the
- Exchange PR with initial implementation: https://github.com/artsy/exchange/pull/314
- PaperTrail docs on Custom Version Classes: https://github.com/paper-trail-gem/paper_trail/tree/091612fb565c5fa71aee828fa575cc4e4c180f28#6a-custom-version-classes
If you changed something in the
/models make sure to inform #data (analytics) team about it in case it impacts their reports.
Did You Change GraphQL Schema?
Metaphysics is the current consumer of Exchange GraphQL schema and keeps a copy of latest schema in https://github.com/artsy/metaphysics/tree/master/src/data, if you have changed Exchange GraphQL schema, make sure you also update the copy of this schema in Metaphysics. In order to do so follow these steps:
- In exchange run
schema.graphqlfile generated ☝🏼 to
mv schema.graphql exchange.graphql
- copy file above to your local update Metaphysics under
src/dataand make a PR to Metaphysics with this change.
There is a guide on how to add exchange operations to Metaphysics here
Talking to Exchange
In order to talk to Exchange GraphQL endpoint:
- Update the
REPLACE_MEvalues in the
.envfile. You can reference the values used on staging with
hokusai staging env get.
gem install dotenv
- Start local server
dotenv rails s
- If you work at Artsy, get proper Gravity User Token following these instructions (the client application name is "Exchange Staging").
- Install and run GraphiQL app
brew cask install graphiql
- In GraphiQL app, go to http://localhost:3000/api/graphql, you should ge unauthorized error
- Edit HTTP Headers and add
Authorizationheader and set it to
<token>is your Gravity token generated few steps above.
Working at Artsy?
Get Access To Exchange
Access to Exchange Admin is limited to users with the role "Sales Admin". Ask someone with Role Manager permissions to grant your user "Sales Admin" permissions.
Something went wrong? Ideally in the JSON response returned from Exchange there will be enough info to describe what went wrong. In case that was not useful, you can:
- Check Sentry (password in 1Pass) and look for Exchange (staging or production) and see the error.
- Follow exchange logs by doing
hokusai staging logs -f
If you think there is something we could improve in this error case, feel free to open an issue with details about what you did and what went wrong.