classtag

Visit the ClassTag Wiki for more information about the site and how it works.

DOCKER

Install Docker Compose

Install guide

Run container

docker-compose up

If use docker, chapters: PostrgreSQL (12), Redis, Memcached should be skipped!

Migrate DB data from the oldest PG version

after PG version update you will see an error: The data directory was initialised by not compatible version to resolve this and save your data follow these steps: 1. open docker-compose.yml and switch PG version to previous one 2. docker-compose down 3. docker-compose up 4. docker exec classtag_web_postgres_1 pg_dumpall -U postgres > dump.sql 5. docker-compose down -v 6. docker volume rm classtag_web_pg_data 7. switch to the newest version in docker-compose.yml 8. docker-compose up --force-recreate 9. docker exec classtag_web_postgres_1 createuser -s -r postgres 10. Mac: brew upgrade postgresql, Ubuntu: https://newbedev.com/postgresql-9-2-pg-dump-version-mismatch # this step is to support pg_dump for structure.sql 11. rake db:create 12. docker exec -i classtag_web_postgres_1 psql -U postgres -v -d classtag_development < dump.sql 13. rake db:migrate

Application

Hosts

Add to /etc/hosts lines:

127.0.0.1 classtag.int 127.0.0.1 home.classtag.int 127.0.0.1 social.classtag.int

RVM - Ruby enVironment (Version) Manager + Ruby (3.1.2)

If you do not have gpg already installed:

brew install gpg

Go to rvm.io/rvm/install, follow the instructions on the page. (Explicitly below.)

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

If you get this error: “gpg: keyserver receive failed: No route to host”, run the command below & retry

gpg-connect-agent --dirmngr 'keyserver --hosttable”

Then

curl -sSL https://get.rvm.io | bash -s stable --ruby

This should install ruby-3.1.2 (at the time the docs is written, and we use this version)

PostrgreSQL (12)

Go to postgresapp.com > Download button on top will get you the latest (Postgres 12 for now)

Follow the instructions on the page:

  • Download

  • Move to Applications folder

  • Open Postgres

  • Click “Initialize” to create a new server

Make sure it is running!

Redis

brew install redis@3.2
brew link redis@3.2 --force

update your PATH like, this is just an example (using zsh):

echo 'export PATH="/usr/local/opt/redis@3.2/bin:$PATH"' >> ~/.zshrc

Make sure redis is running!

Memcached

brew install memcached

Make sure memcached is running!

Imagemagick 7.0.X (eg. 7.0.8)

brew install imagemagick

Clone Repo

git clone git@github.com:ClassTagInc/classtag_web.git

Adding a new SSH key to your GitHub account

Follow the instruction

Install Gems

In root folder run:

echo "classtag, .ruby-version - 3.1.2" > .ruby-gemset

Reenter the folder!

gem install bundle

Configure Sidekiq-Pro

To make sure nokogiri gem will install properly:

brew install libxml2
bundle config build.nokogiri --use-system-libraries --with-xml2-include=$(brew --prefix libxml2)/include/libxml2

To make sure ffi gem will install properly:

brew install libffi && brew link libffi --force

bundle install

This might throw you warning for bundler patch version mismatch, but it should be ok. Sudo needed for http_parser gem —— Gems should be installed!

Sidekiq Pro

bundle config gems.contribsys.com f6af4a84:d5f166c9

  Alternately you can set an environment variable or use local mode:

    BUNDLE_GEMS__CONTRIBSYS__COM=f6af4a84:d5f166c9
    bundle config --local gems.contribsys.com f6af4a84:d5f166c9

Environments

Copy .env.template to .env, leave REQUIRED block and DOCKER if use docker containter. Remove all OPTIONAL block.

Copy .env.js.template to .env.js.dev, leave REQUIRED block and uncomment DEVELOPMENT REQUIRED.

Copy .env.js.template to .env.js.test, leave REQUIRED block and uncomment TEST REQUIRED.

Google API Key

You will need a Google API Key. Go to console.developers.google.com/project/_/apiui/credential to create a project (you can call it whatever you like) and create a key. You will need to enable the Time Zone api on the key.

We use .env for environment variables through the dotenv gem. You can create your own .env file, but please don’t commit it to the repo. Everyone should have their own .env file. You can create yours from .env.template.

In .env

GOOGLE_GEOCODER_API_KEY: <Your key here>

ClassTag Private NPM package

To use @classtag/ui library which is a private package, you should add auth token to your machine.

In OSX or Linux, add this line to your ~/.profile:

export NPM_TOKEN="021053af-91c3-4013-9df9-9b9096db3a4e"

and then refresh your environment variables:

source ~/.profile

Initialize Database

rake db:setup

To seed the database of schools, run:

rake schools:google_seed

Mailers preview (development only!)

To make an email template preview you have to describe it into spec/mailers/previews folder. First of all have to add a file

script
touch spec/mailers/previews/<mailer_name>_preview.rb

and define a class inherited ActionMailer::Preview class where you have to invoke a mailer action

class FooMailerPreview < ActionMailer::Preview
  def foo
    FooMailer.foo
  end
end

The mailer action preview will be available by the following url

http://classtag.int:3000/rails/mailers/foo_mailer/foo

Backdoor

To change server address for the ClassTag application please follow this link

https://classtag.com/appconfig

Run Dev Server As Public accessible APP

This is useful when you want to test locally Mobile App or Google, Facebook oauth
  • open 3000 port on your router

  • install Ngrok

  • run it for port 3000 with command ./ngrok http 3000

  • comment CLASSTAG_DEV_PORT=3000 in .env file

  • update all .env Variables with value classtag.int to your.ngrok.host where your.ngrok.host is a host provided by Ngrok

  • restart server

and now you can use your.ngrok.host to access mobile app from the Backdoor or for other purposes where you need your dev app to be shared public

do not forget to rollback those changes to use DEV env as before :)

Webpacker

NVM

Recommend to install NVM.

To install our packages, make sure to run yarn.

yarn

Services

Use puma-dev for classtag.int

Webpack

For faster webpacker compiles when you are updating javascript, instead of relying on the Rails webpacker, in a separate console run the dev server binstub (see the webpacker gem for installing the binstubs)

bin/webpack-dev-server

Run with SSL

Generate self-signed cert and key
$ mkdir .certs
$ openssl req -new -newkey rsa:2048 -sha1 -days 365 -nodes -x509 -keyout .certs/classtag.int.key -out .certs/classtag.int.crt

You can leave all the address and organization info blank.

For the Common Name use classtag.int if you want to access subdomains.

Trust the cert in keychain

  1. Open the certificate in Keychain Access.

bash $ open /System/Applications/Utilities/Keychain\ Access.app .certs/classtag.int.crt

  1. Click Don't Trust.

  2. Select the newly imported certificate, which should appear at the bottom of the certificate list, and click the [i] button.

  3. In the popup window, click the ▶ button to the left of Trust, and select Always Trust for When using this certificate:.

  4. Close the popup window.

  5. When prompted, enter your password again and click Update Settings.

  6. Close Keychain Access.

Start rails using with ssl options
$ rails s -b 'ssl://classtag.int:3443?key=.certs/classtag.int.key&cert=.certs/classtag.int.crt&verify_mode=peer&ca=.certs/classtag.int.crt'

Before start, please check: - .env: - DOMAIN_SCHEME=https - CLASSTAG_DEV_SCHEME=https - CLASSTAG_DEV_PORT=3443 - config/webpacker.yml: - dev_server -> https sets to true

Run Rails server

rails s

Now you can hit the page at http(s)://classtag.int:3000/! :)

Notes: * the local server always returns errors with actioncable, so you can ignore that. * assets (css, js) may be missing because of http/https mismatch: * either visit at https and have https as your CLASSTAG_DEV_SCHEME in .env * or visit http and have http as your dev scheme.

Rails Routes

After config/routes.rb updates, to make it available in JS application.

rake js:routes

GraphQL and Relay

After GraphQL updates, update the GraphQL schema for Relay.

rake graphql:dump

After any changes in Relay part of components and queries:

yarn run relay

Note: you have explicitly rerun yarn run relay after rake graphql:dump:json, even if you run it in --watch mode as yarn run relay --watch

Generated files

There are files like structure.sql and schema.json (generated with rake graphql:dump:json) which might be updated quite often.

The policy: you should not commit structure.sql (if you don’t add new migration), but if you do it is not a problem. You should commit schema.json. (This might be later automated with a git pre-commit hook)

Code Quality

Please use a linter for each language.

Confirm that all tests pass on circleci as well (excluding flaky tests - you’ll see which those are :<) before requesting review.

Install/Update Chromedriver (Mac)

Needed to run the tests.

Homebrew

brew tap caskroom/cask
    brew cask install chromedriver

Manually

  1. You need to go the below address and download chrome driver for Mac operating system.

Link: sites.google.com/chromium.org/driver/downloads

<img src=“” width=“400” >

  1. Move the driver to the /usr/local/bin folder

Now, we can move the driver a path which is defined as a path in your system. You can check them with below command and you will see that /usr/local/bin folder is defined as a global path on your system.

less /etc/paths

If you want you can add a specific path here and you can move the chromedriver to this folder but as you see, /usr/local/bin folder is defined as a path by default.

Now, go to your downloads folder, find the chromedriver_mac64.zip file and unpack it. You will see the chromedriver executable file.

Now, we can run below command and move the chromedriver file to the /usr/local/bin folder.

```
mv chromedriver /usr/local/bin
```
  1. MacOS Catalina security

    cd /usr/local/bin
    	xattr -d com.apple.quarantine chromedriver
    
  2. Check version of chromedriver

    chromedriver -v
    

Run tests

To run ruby tests locally use one of these:

rspec
rspec file_path
rspec file_path:line
````

### How to became admin user?
Locally:

rails c

User.lookup_by_credential(‘<your credential>’).super_admin!

“‘

On staging: Tell Jason the credentials and he will update it.

You may find the link to admin section on the bottom of the left sidebar.

Access your local server through mobile

In you .env (which is not commited to the repository):

  • set CLASSTAG_DEV_HOST=<your_local_ip> like CLASSTAG_DEV_HOST=192.168.0.177

  • comment out DOMAIN=classtag.int, make sure there is no DOMAIN in .env

Now you should be able to access from your local network.

Policy

Delete old branches

Please make sure to delete any old branches that we aren’t using.

Naming/numbering similar branches

The numbering at the end can make things risky. When numbering branches put the code a, b, etc., immediately after the branch number and before the name.

This makes it harder to accidentally auto-complete and go into the wrong branch.

Frontend

Prefer Underscore.js

Use Underscore instead Lodash. They might conflict. If they do there are some “.noConflict” examples in repo.

Delete after Refactor

When refacoring from flux + .coffee + rest to redux + .js(x) + graphql (+ rest), delete the old .coffee files if you are done.

Gotchas

Almost blank page appers with content “Confirmation, Cancel button, Confirm”

Change your env to not be https. You aren’t getting the assets because the client is not secure but the assets are.

Don’t forget to restart rails

Sometimes you have to restart rails. Examples: * editing .sass

CircleCi & local test run might cheat on you

If you see a test failing oddly try to rerun (rebuild) at leaste once but better a couple of times locally. Same in case of CircleCi. There might be a wierd bug / dirty commit on master as well, you might ask for help.

Syntax error in classtag.int:3000/graphiql

Might not be Syntax error in the graphql code, rather an unhandled exception on the backedend in dev mode. Eg.: it happened a non existing ID was selected in a valid query but the response was turned into a syntax error.

Eg. SyntaxError: Unexpected token A in JSON at position 0 in graphiQL

react-rails Cannot find component

Error:
Browser Console
[react-rails] Cannot find component: ‘<Path/To/Component>’ for element

Possible real causes & tips:

  1. given Component or its SubComponent can not render (eg. Syntax error) - check webpack’s / relay-compiler’s output.

  2. iTerm/terminal goes mad after changing branches - restart the whole app and start new sessions from scratch.

Graphql: dbId vs id & snake_case vs camelCase

You can always go to staging.classtag.com and see what your Component used to receive (camelCase or snake_case)

  • dbId in GraphQL: “real” id, like “38” on User node

  • id in GraphQL: UUID

  • You might use our custom ObjectHelper.toSnakeCase and ObjectHelper.toCamelCase to convert objects got from GraphQl to the “old” objects the original .coffee implementations do need.

    • Sometimes dbId is enough like <OldCoffeeComponent old_id_prop=new_gq_objnew_gq_obj.<code>dbId</code>>

Google::Cloud::InvalidArgumentError

Google::Cloud::InvalidArgumentError - Google::Cloud::InvalidArgumentError: lib/translator.rb:14:in ‘detect’

Solution: delete/comment line TRANSLATE_KEY=XXXXXX in .env

Useful

Capybara

  • Basics: gist.github.com/tomas-stefano/6652111

  • save_and_open_page to save the screen and have a look on it

  • We have a new approach: stop using wait_for_ajax, since it doesn’t work with axios and it probably won’t work for relay, since it is jQuery-specific.

    • If we want any waiting, use an expect(page).to have_content/have_css as appropriate to capture the result on the page.

  • Don’t forget you might use visible:false if you use find or similar functions

  • You might use page.execute_script to interact with the page with a higher degree of freedom

  • you might want to add , js: true do at the top of a failing block

  • Also, locally, add use_chrome outside the ’it should…‘ section and it will give you chrome step by step

  • You might use sleep(<seconds>) to wait

  • Window size might be important (resize it)

  • Scrolling on page might be important

    • page.execute_script ‘window.scrollBy(0,10000)’

    • scroll_to(“<selector>”)

Access old code

Any old commit is going to have a different expectation about databases. We update the database frequently. Migrating the database is a tricky thing. You can access the old code, but if you want the database to work, you’ll have to re-run the db setup Which blows out any existing data.

stackoverflow.com/questions/10301794/difference-between-rake-dbmigrate-dbreset-and-dbschemaload

reset might be what you need.

Github

NFM tag stands for not for merge. We use it as WIP (Work In Progress).

Deploy to production

git checkout master
git pull
heroku git:remote -a classtag
heroku features:enable -a classtag preboot
git push heroku master:master
heroku ps:restart -a classtag
heroku features:disable -a classtag preboot

Updating SIS cassettes

To update Clever specs, use real token in sis_connector.access_key or Sis::ApiClients::Clever to update cassettes; Consider clearing old cassettes so they don’t pile up to help reading and maintaining them.

Yardoc

Run Server locally

yard server

Rebuild Yardoc files

You should run this command whenever you want to update doc files

yardoc

Yardoc repository

We use it as a submodule for classtag_web. This means that you can work with it within classtag_web/docs folder as well as with classtag_docs repository itself.

https://github.com/ClassTagInc/classtag_docs

Yardoc docs

https://yardoc.org/

Yardoc github pages host

https://docs.classtag.com/

Work with classtag_docs submodule

To pull latest submodules data use: git pull --recurse-submodules or git submodule update --recursive

otherwise you should work with submodule absolutely the same way as with any regular repository.

for example to commit changes/deploy submodule you should follow these steps: 1. yardoc 2. cd docs 3. git commit ... 4. git push ...

Each merge to master or push to master will update code on GithubPages

docs and classtag_web changes are tracked separately. To commit changes for one or another project you should be in it.

Deploy of docs submodule

You can simply run: 1. rails docs:generate or rails docs:generate[branch_name] which will generate docs && push them to the master by default or to the specific branch 2. commit changes in the main repository classtag_web.