Skip to content

Repository for 2024_fall Hackathon, HeatSyncers Team, Nature's Edge Wildlife and Reptile Rescue Digital Transformation Problem Statement

License

Notifications You must be signed in to change notification settings

2024-Arizona-Opportunity-Hack/HeatSyncers-Nature-sEdgeWildlife-Nature-sEdgeWildlifeandReptileRescueDigitalTransformation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HeatSyncers' 2024 Opportunity Hack Project

Nonprofit: Nature's Edge Wildlife and Reptile Rescue

Quick Links

Team "HeatSyncers"

Project Overview

Brief description of your project and its goals.

Product management

Follow along with our Trello board: 2024 HeatSyncers Trello

Tech Stack

  • Frontend: HTML/CSS/JS
  • Backend: Ruby on Rails
  • Database: Postgres
  • APIs (planned): payment processor, email service, etc.

Environment Setup

Important

Make sure to install these pre-requisites first:

  • Ruby 3.3.5 (chruby is recommended for managing Ruby versions)
  • Rails 7.2.1 (follow this guide to install)
  • Postgres (either via brew or Postgres.app)

Once you're ready to go, you'll need to make sure to install via both Bundler and NPM:

bundle install
npm install

Local development uses Foreman to run two parallel processes: one for the Rails server (rails s) and one for compiling Tailwind (npm build:css --watch). To start these, simply run:

bin/dev

Tip

It's also recommended that you pull the latest changes from the main branch and rebase them into your working branch every day to avoid merge conflicts.

git checkout main
git pull
git checkout your-branch
git rebase main

This repo makes use of the pry-byebug and pry-rails gems for debugging. You can insert a binding.pry statement in your code to pause execution and open a REPL in the terminal (similar to debugger in JavaScript). You can do this anywhere Ruby is parsed in the codebase, including in tests. For testing email, letter_opener catches emails in the development environment and opens them in a browser window.

If you need to run bundle install or rails db:migrate, Rails will tell you in the command line if you need to do so.

First time setup

  1. Run bundle install to install Ruby dependencies

  2. Make a copy of .env from .env.example, and update these values:

    • BASEAPP_DATABASE_USER (your local Postgres username)
    • BASEAPP_DATABASE_PASSWORD (your local Postgres password)
  3. Create, init, and seed your local database:

    rails db:create && rails db:migrate && rails db:seed

Optional local environment setup

  • You may want to integrate Rubocop into your editor of choice. This project has a .rubocop.yml file that Rubocop will use to enforce code style. You can install the Rubocop extension for your editor to see these style violations inline. Some will even automatically re-format for you.

Making a pull request

When you make a pull request (PR), you'll want to be sure that the following things are true:

  • Your code is up-to-date with the main branch
  • Your code passes all tests
  • Your code is styled according to Rubocop

To check these things, run the following commands:

# update with latest from main:
git checkout main
git pull
git checkout your-branch
git rebase main

# run tests
bundle exec rspec

# check style
bundle exec rubocop

Code base quirks

Constants

This project uses constants to store values that are used in multiple places. These are defined using YAML files in config/constants/. You can access these constants in your code by using the Constants module. For example:

# get a single value
Constants.example.value

# get all values
Constants.example.values

Important

This means that values is a special keyword and should not be used in the constants file.

Helper files

We use helper files for shared functionality that doesn't belong in a model or controller. These are stored in app/helpers/. Display logic for data typically would rest with the model, but if you need repeated configration that doesn't make sense to be in a model, you can put it in a helper file.

Common examples of things that might go in a helper file are:

  • navigation config
  • mapping data to display values
  • configuration for a third-party service

# frozen_string_literal: true

This project uses # frozen_string_literal: true at the top of each Ruby file. This is a magic comment that tells Ruby to freeze all string literals in the file. This means that you cannot modify the string in place. This is a good practice because it helps prevent bugs where you accidentally modify a string that you didn't mean to.

Note

Rubocop will enforce this rule, so you don't need to worry about adding it yourself. If you have installed Rubocop in your editor, it will even automatically add this comment to new files.

Working with the front end

We don't use React or any other frontend framework, but we do make use of Rails' partials to create reusable components. These are stored either in app/views/components/ or in a controller-specific directory (such as app/views/home/components) if it's scoped to a base controller, such as when there's a marketing-side vs logged in portal side.

Tailwind best practices

@apply

In this repo, we rely heavily on Tailwind's @apply directive to keep display logic in CSS files and out of the HTML. This can make our Tailwind file pretty long, so there is a custom compile step that looks for specific CSS files to compile into the public/ directory. In general, we'll want to create a new *.tailwind.css file for each controller but may also make separate files for larger components/partials.

These new files should be imported to the base application.tailwind.css file or the matching domain-specific example.tailwind.css file (such as marketing.tailwind.css) above the Tailwind imports.

Extending Tailwind classes

Tailwind only includes classes that are used so that the CSS file is as small as possible for the client, but it's a little dumb/simplistic about it. What this means is that if we're using Ruby to programmatically set a class Tailwind won't know and it won't be included in the generated/built CSS. To get around this, we use a set of regexes configured in the safelist object in the module.exports of tailwind.config.js.

Colors

Colors are defined as CSS variables in app/assets/stylesheets/colors.tailwind.css in the @layer base { :root {}} block. We intentionally pass in only the channels so that way Tailwind's alpha functions will work with them. (See Tailwind - Customizing Colors - Using CSS Variables for more on that.)

Colors are then referenced by CSS variable name (var(--color-name)) in tailwind.config.js, which defines the reference names that are used in Tailwind's CSS class building (ie: text-brand-orange-500 or bg-brand-orange-700, etc...).

We define the brand colors and several shade values for them, with the 500 shade and the DEFAULT value being the same.

If you need to add a new set of colors with shades, Noel Delgado's Shadowlord tool is a great resource for generating shades of a color. You kind of need to eyeball it to get the right shade, but it's a good autogenerator of values to select from.

Adding a new Tailwind file

To add a new file that needs to be compiled for Tailwind (ie, it's not being @included'd in a file that is already being compiled), you'll need to update the package.json file. We rely on an NPM package called npm-run-all to look for build scripts, so so long as you follow naming conventions it's pretty straightforward.

  1. Follow convention and name the file your-file-name.tailwind.css
  2. Add a new build:css:your-file-name and a watch:css:your-file-name script to the package.json scripts object (in alphabetical order):
    "scripts": {
      "build:css:your-file-name": "tailwindcss -i ./app/assets/stylesheets/your-file-name.tailwind.css -o ./app/assets/builds/your-file-name.css --minify",
    
      "watch:css:your-file-name": "tailwindcss -i ./app/assets/stylesheets/your-file-name.tailwind.css -o ./app/assets/builds/your-file-name.css --minify --watch"
    }
  3. Restart bin/dev

Your new file will be automatically watched and rebuilt during development now. :)

A quick note on SASS

This project intentionally does not use SASS, as the benefits that we used to get from SASS are now in common CSS. Additionally, the SASS processor kept breaking the deploy randomly so it was removed. The Rails admin panel techincally does use SASS, so if it is added you'll need to grab a compiled version of its CSS and manually include it in the build.

Working with specs

This project uses RSpec for testing, in combinatin with FactoryBot to create test fixtures and Faker to generate random data as needed.

It's also supported by a few other gems to help with testing:

Running the test suite

You can run the entire test suite with:

bundle exec rspec

You can also run a single test file by specifying the path to the file:

bundle exec rspec spec/models/user_spec.rb

If you want to focus a single test or set of tests, you can use the focus tag or the f prefix:

# using the focus tag
RSpec.describe User do
  it 'does something', focus: true do
    # ...
  end
end

# using the f prefix for a single test
RSpec.describe User do
  fit 'does something' do
    # ...
  end
end

# using the f prefix for a block of tests
RSpec.describe User do
  fcontext 'when something' do # this would also work with `fdescribe`
    it "flimflams" do
      # ...
    end

    it "jimmity jams" do
      # ...
    end
  end
end

and only those focused tests will run when you run bundle exec rspec.

Writing tests

When writing tests, you'll want to follow the Arrange-Act-Assert pattern. This means you'll set up the test environment, perform the action you're testing, and then assert that the result is what you expect.

If you are creating a new model, you will want to create a new factory for it in spec/factories. You can then use this factory in your tests to create instances of the model that you then act upon. Be sure to use Faker to generate random data for your factories. This will help ensure that your tests are robust and that they don't rely on specific data.

Here's an example of a test for a User model:

RSpec.describe User do
  describe "validations" do
    # note: `bulid` comes from FactoryBot, and relies on `spec/factories/user.rb`
    it "is valid with valid attributes" do
      user = build(:user)
      expect(user).to be_valid
    end

    it "is not valid without an email" do
      user = build(:user, email: nil)
      expect(user).to_not be_valid
    end
  end
end

Working with the database

This project uses Postgres as the database. You can interact with the database using the Rails console. To open the console, run:

rails c

From here, you can interact with the database using ActiveRecord. For example, to find all users, you could run:

# list all users
User.all

# find a user by email
User.find_by(email: "foo@example.com")

# find users where name is "Cerberus"
User.where(name: "Cerberus")

Creating seed data

If you need to create seed data for the database, you can do so by creating a new seed file in db/seeds/. Make sure to include and run it in db/seeds.rb. You can then run the seed file with:

rails db:seed

We want to be careful to not overuse Faker in our seeds, as our seeds should be highly repeatable and easily identifiable. It's okay to use it for filler data (such as paragraphs of text), but we should avoid using it for things like names, titles, or emails.

Troubleshooting

[TODO: Add common issues here]

About

Repository for 2024_fall Hackathon, HeatSyncers Team, Nature's Edge Wildlife and Reptile Rescue Digital Transformation Problem Statement

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published