An API-only Rails app acting as a server backing groceries: a real time, offline-capable grocery list.
- Grocery list items are persisted in an
itemstable inside a Postgres database. - Rails Action Cable is used to broadcast
itemsCRUD operations with a WebSocket. - Action Cable is configured with Redis in production.
To make sure everything runs smoothly, install the following on your machine first:
- Node.js 14.x
- Ruby 2.7.6
- Yarn 1.22.19
- Postgres 14
Now, clone the repo, cd into your repo’s directory, and run the following commands:
# Install Ruby gems specified in /Gemfile
bundle install
# Install Node packages specified in /package.json
yarn install
# Set up a local Postgres database
bin/rails db:setupIf everything went right, you should now be able to start a local dev server with rails:
bin/rails serverPlease note that Heroku no longer offers free plans. But you should be able to deploy this app with some cheap plan prorated to the second. It shouldn’t cost more than a couple of bucks.
Click the Deploy to Heroku button below to deploy without having to do any manual configuration:
Deploying manually will take more work. Here are some pointers:
- Download the Heroku CLI, and log in.
- Provision the Heroku Postgres add-on; this will set a DATABASE_URL config variable in Heroku, and the Rails app will use it to connect to the database.
- Provision the Heroku Data for Redis add-on; this will set a REDIS_URL config variable in Heroku used by the Rails app.
- Add a
liststable so that many separate lists can be used instead of everyone using the same grocery list.
Note: enabling HTTPS requires changes to both groceries and groceries_api. For simplicity, I kept the instructions in this section the same in each repo.
Both this Groceries client and the groceries_api use HTTPS when deployed to production. You might want to enable HTTPS in development to get as close as possible to simulating a production environment.
When you’re done with this setup, you’ll be able to connect to your local server from any device in your local network using a custom made-up domain. This domain will only work in your local network.
We’ll be using https://groceries.andy for this client and https://api.groceries.andy for the API server.
This is a pretty involved process, and the individual steps may vary depending on your system. I’ll paint a broad picture and provide guidelines using macOS and iOS devices as examples here.
Follow the steps in this article to set it up: Create Your Own SSL Certificate Authority for Local HTTPS Development
Follow the article mentioned in the previous step.
Once you’ve generated the certificates, copy them into your repo:
- For the client, place the certificates in
/ssl - For the API server, place the certificates in
/config/ssl
The client and the API server are already configured to work with groceries.andy as the client URL and api.groceries.andy as the API server URL. If you want to use another custom domain, you’ll have to edit both projects:
Client
- The
HOSTenv var in thestart-httpsscript in `package.json. - The
REACT_APP_API_HOST_DEVELOPMENT_HTTPSenv var in.env.development
API server
- Edit the
config.hosts << "api.groceries.andy"line in/config/environments/development.rb.
A made-up domain like groceries.andy doesn’t exist. We don’t want to go out into the open internet and ask any DNS servers where to find the computer behind groceries.andy. Instead, we’ll make our own machine the DNS server for this domain only.
To do that, we need to create a resolver that will point from a domain name to a nameserver. Run the following command:
cd /etc
mkdir resolver
cd resolver
echo "nameserver 127.0.0.1" | sudo tee groceries.andyYou might not have write permissions to /etc. Cautiously run with sudo in that case.
Confirm that our resolver was created:
scutil --dnsWe’ll use dnsmasq as our DNS forwarder. Whenever someone asks for groceries.andy, we’ll forward them to localhost.
Install dnsmasq with Homebrew:
brew install dnsmasqFind the configuration file for dnsmasq. On Apple silicon Macs it’s in /opt/homebrew/etc/dnsmasq.conf. Open the file and add the following line to it:
address=/groceries.andy/127.0.0.1dnsmasq runs continously as a service on your machine. Restart it so that your changes take effect:
brew services restart dnsmasqYou might need to run the above command with sudo.
Run any of the following to test that the forwarding works:
ping -c 1 happy.tree
dscacheutil -q host -a name happy.tree
dig happy.tree @localhostOn your iPhone, go to the settings of your local Wi-Fi. Change the DNS setup from Automatic to Manual. Enter your dev machine’s local network IP address as the address of the DNS server.
Phew, this was a lot! You should now be able to run the client and the API server with HTTPS in development.
Run your API server:
zsh -c "GROCERIES_API_HTTPS=true && rails s -b 'ssl://api.groceries.andy:9000?key=config/ssl/api.groceries.andy.key&cert=config/ssl/api.groceries.andy.crt'"Run your client server:
yarn start-https