A guide to maintain a consistent standard of how we set up and maintain rails projects - aim to keep up with best practises and project familiarity between team members.
Before setting up - always check we are using the latest version of ruby and rails. (rvm list known
)
-
create project with postgresql (
rails new myapp --database=postgresql
) - unless a project demands something specifically for speed/handling huge amount of records like mongodb (if app is api-only, runrails new my_api --api
) -
Before any models/relationships are created and coded in - db structure and diagram has to be created, agreed and approved. Great tool for this can be found here
Standard gems to use throughout project:
- HAML - No ERB here folks - HAML is better.
- pry-rails - Best debugging/breakpoint tool.
- faker - great tool for generating fake data
- simple_form - simple rails forms (willing to discuss the best option - but good to stick to one)
- Rspec - best tool for backend testing
- friendly_id - no id's in URL's on a show page
- figaro - best practise for keeping secret keys safe and sound
- letter_opener emails on dev
- rubocop analyse each ruby file and it will tell you where your code can be better
- devise If it needs users and authentication - there is no other.
- Any rails dev should be able to run the seeds file and have the app running straight away. So first thing there needs to be a script in the seeds file to generate data. Should all be ludicrously easy.
- Use sass to extend the possibilites of the css. (things such as variables, nested style formatting)
- scss files kept as separate as possible. Where possible - separate for each page/partial. Trawling though giant css fies should be a nono.
- use partials wherever appropriate and possible. If you have to scroll past the bottom of your haml file - you probably need to separate it out into partials. Keep everything as small as possible
- wherever possible - keep these to CRUD /routes and not a great deal more. Skinny Controllers and all that. Logic don't need to be there.
- Always a good idea for future proofing and maintaining if we split out Rails API routes into namespaced versions. Means we can easily separate out versions without breaking shit in the future. Better article describing the benefits here. Example of how that works with routes here and how that is reflected in the controllers here . Each controller inherits from the 'v1' module. We can easily then create a 'v2' module for which we can put in new features.
- when writing methods - keep separated into sections to easily keep track (e.g - after_create methods section/calculations section)
- When creating methods - think whether it needs to be in the model or not. If it's logic for the view - it should be a helper method or a Decorater object.
- If there is a large chunk of the model which is dedicated to one particular feature/page - perhaps you can create a service for it? This will help restrict the how bloated the model file gets. Couple of examples:
-
when time allows - always try and write unit tests using rspec for more complex features. I don't think it's necessary for every single button click and every bog standard method under the sun - but any chunks of functionality that have an element of complexity and potential to break shoudl have a test written for it.
-
write out testing sheets so other users can go through and test. Record the results and make notes of failures and points you;ve noticed. Example can be found here
- if we need to run a large / memory-intensive section of code, or just write something that sites outside the thread of the main code execution - we should use ApplicationJobs.
- example here - where we tried to improve the memory intensiveness of a giant reporting job by putting into a background job
- here for JAQ where we wanted to send a push notification out when an order changed it status to ready - without disturbing the main thread of events.
More commenting the better. Code needs to be understandable. If it's not blindingly obvious - write out what's happening. So much easier for the team to understand what's going on - and can also help you with the process of writing code if you map out what you need to achieve.