39 | Services
40 |
41 |
42 |
43 | app/services
44 | ├── add_points_to_user.rb
45 | ├── aes_crypt.rb
46 | ├── assign_geo_keywords.rb
47 | ├── assign_location_attributes.rb
48 | ├── braintree
49 | │ ├── customer_and_token_creator.rb
50 | │ └── webhook_handler.rb
51 | ├── calculate_bearing.rb
52 | ├── developers
53 | │ └── api
54 | │ └── v1
55 | │ └── process_occupancy_params.rb
56 | ├── devise
57 | │ └── strategies
58 | │ └── jwt.rb
59 | ├── export_service
60 | │ ├── config.rb
61 | │ ├── generator.rb
62 | │ ├── model.rb
63 | │ └── options_formatter.rb
64 | ├── exporter
65 | │ ├── creator.rb
66 | │ └── generator.rb
67 | ├── exporters
68 | │ └── csv
69 | │ ├── base.rb
70 | │ └── generator.rb
71 | ├── feature.rb
72 | ├── filters
73 | │ ├── creator.rb
74 | │ └── updater.rb
75 | ├── generate_friends_report.rb
76 | ├── indigo
77 | │ ├── cancel_reservation.rb
78 | │ └── create_reservation.rb
79 | ├── jwt_serializer.rb
80 | ├── locations
81 | │ └── actions.rb
82 | ├── loyalty_points_awarder.rb
83 | ├── mailgun_notify_email_forwarder.rb
84 | ├── merge_parking_places.rb
85 | ├── migrations
86 | │ └── file_mover.rb
87 | ├── notifications
88 | │ ├── amazon_notifications.rb
89 | │ ├── firebase_notifications.rb
90 | │ ├── sender.rb
91 | │ └── shared_actions.rb
92 | ├── parking_place_awarder.rb
93 | ├── parking_place_exporter.rb
94 | ├── parking_places
95 | │ ├── category_updater.rb
96 | │ ├── country_code_mapper.rb
97 | │ ├── creator.rb
98 | │ ├── exporter.rb
99 | │ ├── generators
100 | │ │ ├── icons
101 | │ │ │ ├── combiner.rb
102 | │ │ │ └── type.rb
103 | │ │ └── icons.rb
104 | │ ├── icon_types.rb
105 | │ ├── icons
106 | │ │ └── updater.rb
107 | │ ├── icons.rb
108 | │ ├── occupancies
109 | │ │ └── setter.rb
110 | │ ├── security_rating.rb
111 | │ └── updater.rb
112 | ├── payment_exporter.rb
113 | ├── payments
114 | │ └── exporter.rb
115 | ├── promiles
116 | │ ├── add_driving_distance.rb
117 | │ ├── build_polyline.rb
118 | │ ├── corridor_search.rb
119 | │ ├── create_or_update_parking_places.rb
120 | │ ├── create_or_update_promiles_locations.rb
121 | │ └── get_route.rb
122 | ├── provider_occupancies_service.rb
123 | ├── providers
124 | │ ├── client
125 | │ │ └── mdm.rb
126 | │ └── parser
127 | │ ├── a63_france.rb
128 | │ └── mdm.rb
129 | ├── request_logs
130 | │ ├── archive_partition.rb
131 | │ ├── create_archive.rb
132 | │ └── create_partition.rb
133 | ├── reservations
134 | │ ├── booking_id_generator.rb
135 | │ ├── charger.rb
136 | │ ├── creator.rb
137 | │ ├── emails.rb
138 | │ ├── integrations_caller.rb
139 | │ ├── mails_sender.rb
140 | │ ├── notifications_sender.rb
141 | │ ├── settler.rb
142 | │ ├── status_setter.rb
143 | │ ├── updater.rb
144 | │ ├── users_setter.rb
145 | │ └── voider.rb
146 | ├── shared
147 | │ └── filter_suggested.rb
148 | ├── stats_maker.rb
149 | ├── subscriptions
150 | │ └── actions.rb
151 | ├── tln
152 | │ └── number_checker.rb
153 | ├── translators
154 | │ └── google.rb
155 | ├── units.rb
156 | ├── update_user_to_developer.rb
157 | ├── user_loyalty_points.rb
158 | ├── users
159 | │ ├── actions.rb
160 | │ ├── creator.rb
161 | │ ├── destroyer.rb
162 | │ ├── exporter.rb
163 | │ ├── o_auth_creator.rb
164 | │ ├── retrieve_all_data
165 | │ │ ├── base.rb
166 | │ │ ├── favorites.rb
167 | │ │ ├── friends_list.rb
168 | │ │ ├── notifications.rb
169 | │ │ ├── personal_information.rb
170 | │ │ └── reviews.rb
171 | │ ├── retrieve_all_data.rb
172 | │ └── settings.rb
173 | ├── vat_checker.rb
174 | ├── version_converter.rb
175 | └── x_server
176 | ├── add_detour_distance.rb
177 | ├── add_driving_distance.rb
178 | ├── base.rb
179 | ├── build_polyline.rb
180 | ├── corridor_search.rb
181 | ├── get_detour_distance.rb
182 | ├── get_driving_distance.rb
183 | ├── get_geo_keywords.rb
184 | ├── get_location_attributes.rb
185 | ├── get_route.rb
186 | └── leave_reachable.rb
187 |
188 |
189 |
190 |
191 | At some point this folder became a dumpall folder without rhyme or reason.
192 | There is also an issue of boundaries: there are none. Each class is used from anywhere in the application and that can
193 | cause headaches.
194 |
195 | # Desired structure
196 |
197 | Here is a folder structure we should strive for
198 |
199 | ```
200 | app
201 | ├── controllers # Rails
202 | ├── frontend # webpacker
203 | ├── domains # custom
204 | ├── models # Rails
205 | ├── views # Rails
206 | └── web # custom
207 | ```
208 |
209 | Let's first talk about Rails-specific folders (`controllers`, `views` and `models`).
210 |
211 | The `views` folder needs to exist because it is hardcoded in the Rails itself (https://github.com/rails/rails/blob/main/railties/lib/rails/engine.rb#L610)
212 |
213 | The `controllers` folder is there because of the way Rails finds controller names (it appends `"Controller"` to the resource name) (https://github.com/rails/rails/blob/main/actionpack/lib/action_dispatch/http/request.rb#L88)
214 |
215 | `models` is a folder where we put all our ActiveRecord models. It is technically not necessary but we will talk about it in the [Further Improvements](#further-improvements) chapter.
216 |
217 |
218 | # `domains` vs `web` folder
219 | `web` is for classes used in controller actions: forms, policies, serializers, queries and similar.
220 | `domains` is for business logic.
221 |
222 | ## `web` folder
223 | The `web` folder structure should follow your routes. Having these routes:
224 |
225 | ```ruby
226 | namespace: :dasboard do
227 | resources :projects
228 | end
229 | namespace :api do
230 | namespace :v1 do
231 | resources :projects
232 | end
233 | end
234 | ```
235 |
236 | it would have this folder structure:
237 |
238 | ```
239 | web
240 | ├── dashboard
241 | │ ├── projects
242 | │ │ ├── presenter.rb
243 | │ │ ├── decorator.rb
244 | │ │ ├── form.rb
245 | │ │ └── policy.rb
246 | ├── api
247 | │ ├── v1
248 | │ │ ├── v1
249 | │ │ │ ├── projects
250 | │ │ │ │ ├── policy.rb
251 | │ │ │ │ ├── query.rb
252 | │ │ │ │ └── serializer.rb
253 | ├── mailers
254 | │ ├── projects
255 | │ │ ├── mailer.rb
256 | │ │ └── decorator.rb
257 | ```
258 |
259 | ## `domains` folder
260 | The `domains` folder should be organized into domains.
261 |
262 | The main idea is to create cohesive groups of domain objects that are involved in the same business use case(s). The same way we try to build classes that are loosely coupled but highly cohesive we should build our domains as well.
263 | Here is an example of domains folder:
264 |
265 | ```
266 | domains
267 | ├── base
268 | │ ├── decorator.rb
269 | │ ├── mailer.rb
270 | │ ├── policy.rb
271 | │ ├── presenter.rb
272 | │ ├── query.rb
273 | │ └── serializer.rb
274 | ├── exports
275 | │ ├── formatters
276 | │ ├── csvs
277 | │ └── spreadsheets
278 | ├── external
279 | │ └── zapier.rb
280 | ├── projects
281 | │ ├── counter.rb
282 | │ └── presister.rb
283 | └── utils
284 | ├── cache.rb
285 | └── slug.rb
286 | ```
287 |
288 | ## Further improvements
289 | * Move mailers into domains folder, where they are actually used. There might be an issue of template files discovery.
290 | * Move controllers to web folder as well
291 | * Move models to domains and web folders (build DTOs)
292 | * Move views to web folder
293 | * Move frontend to web folder
294 |
--------------------------------------------------------------------------------
/Development practices/__Other important guidelines.md:
--------------------------------------------------------------------------------
1 | ## Do!
2 | * [Check the return value of **#save**, otherwise use **#save!**](http://rails-bestpractices.com/posts/2012/11/02/check-the-return-value-of-save-otherwise-use-save) The same goes for #create, #update and #destroy.
3 | * Mirror model validations to database constraints and defaults as much as possible.
4 | * Validate the associated `belongs_to` object (`user`), not the database column (`user_id`).
5 | * All non-actions controller methods should be **private**.
6 | * Use the user's name in the `From` header and email in the `Reply-To` when [**delivering an email on behalf of the app's users**]( http://robots.thoughtbot.com/post/3215611590/recipe-delivering-email-on-behalf-of-users)
7 |
8 |
9 | ## Don't!
10 | * Never use `has_and_belongs_to_many`—use `has_many :through` instead. The first one has unexpected hidden behaviors and, if you find out that you need an extra column in the intermediate table, converting it to the second macro requires a fair amount of work.
11 | * [**Never rescue the Exception class**](http://rails-bestpractices.com/posts/2012/11/01/don-t-rescue-exception-rescue-standarderror/)
12 | * Don't change a migration after it's been merged into master if the desired change can be solved with another migration.
13 | * Don't reference a model class directly from a view.
14 | * Don't use instance variables in partials. Pass local variables to partials from view templates.
15 | * Don't use before_actions for setting instance variables. Use them only for changing the application flow, such as redirecting if a user is not authenticated.
16 | * Avoid the `:except` option in routes. Use the `:only` option to explicitly state exposed routes.
17 |
18 |
19 | ## Naming
20 | * Name date columns with `_on` suffixes.
21 | * Name datetime columns with `_at` suffixes.
22 | * Name time columns (referring to a time of day with no date) with `_time` suffixes.
23 | * Name initializers for their gem name.
24 |
25 |
26 | ## Organization
27 | * Order ActiveRecord associations above ActiveRecord validations.
28 | * Order i18n translations alphabetically by key name.
29 |
--------------------------------------------------------------------------------
/Fiscalizer.md:
--------------------------------------------------------------------------------
1 | ## Fiscalizer
2 |
3 | We use the [fiscalizer gem](https://github.com/infinum/fiscalizer) to transfer various document types from a business entity to the tax authorities.
4 |
5 | ### Setup & Usage
6 |
7 | Everything about setup and usage of this gem is explained at [fiscalizer gem](https://github.com/infinum/fiscalizer).
8 |
9 | ### Certificates
10 |
11 | #### Environments:
12 |
13 | + ##### Production environment
14 |
15 | Requires only one certificate - application certificate. It is most often called `FISCAL_1.p12`. It contains the public and private key, and the CA (`Certificate authority`) certificate.
16 |
17 | Secrets file example:
18 |
19 | ```Ruby
20 | fiscalization_app_cert_path: 'cert/production/FISKAL_1.p12'
21 | fiscalization_ca_cert_path: ''
22 | ```
23 |
24 |
25 | + ##### Development & staging environment
26 |
27 | Requires 2 certificates - both application and server certificate. The application certificate (`FISCAL_1.p12`) contains the public and private key. The server certificate (most often `fina_ca.pem`) contains the required CA certificates.
28 |
29 | Secrets file example:
30 |
31 | ```Ruby
32 | fiscalization_app_cert_path: 'cert/development/FISKAL_1.p12'
33 | fiscalization_ca_cert_path: 'cert/development/fina_ca.pem'
34 | ```
35 |
36 | #### Application certificate unpacking
37 |
38 | To view the content of the application certificate locally, you need to unpack it with this command:
39 |
40 | ```
41 | openssl pkcs12 -in FISKAL_1.p12 -out FISKAL_1.pem -nodes
42 | ```
43 |
44 | After running this command, you are prompted to input the `fiscalization password`.
45 |
46 | #### Create your own certificate
47 |
48 | If you need to test some features that require certificates but you don't have them and your request cannot be sent, you can create a certificate following this [tutorial](https://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/).
49 | Once done, create a `.p12` file following these two steps:
50 |
51 | 1. Copy the private key and SSL certificate to a plain text file. The private key should be at the top with the SSL certificate below. In the example, we use "filename.txt" as the name of the file containing the private key and SSL certificate.
52 |
53 | 2. `openssl pkcs12 -export -in filename.txt -out filename.p12`
54 |
--------------------------------------------------------------------------------
/Hosting API Documentation.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | This is the flow we use to generate and host our documentation:
4 |
5 | - Write tests using rspec and annotate them using [dox](https://github.com/infinum/dox)
6 | - Once tests on [semaphore](https://semaphoreci.com) pass we move to deploy
7 | - In the deploy phase we do the following:
8 | * deploy the application using [mina](https://github.com/mina-deploy/mina)
9 | * run only dox tagged specs (request specs) to generate the documentation
10 | * copy the generated documentation to the application server inside `public` folder
11 |
12 | # Why
13 |
14 | Hosting the API documentation directly from the application server is convenient and does not cost extra.
15 | Solutions like apiary.io require having one project for each environment, can't easily set
16 | a desired domain and can't easily hide behind some kind of authentication (like Basic Authentication).
17 |
18 | To ensure that the documentation is always up to date it is copied only after a successful deploy
19 |
20 | By using the `public` folder nginx takes care of serving the static file and the requests don't go through the whole Rails stack.
21 |
22 | # How
23 |
24 | ## Dox generating task
25 |
26 | Here is an advanced example of a rake task that generates the documentation:
27 | It has the feature to write ERB code inside your accompanying .md files.
28 |
29 | ```ruby
30 | namespace :dox do
31 | task :md, [:version, :docs_path, :host] do |_, args|
32 | require 'rspec/core/rake_task'
33 |
34 | version = args[:version] || :v1
35 | docs_path = args[:docs_path] || "api/#{version}/docs"
36 |
37 | RSpec::Core::RakeTask.new(:api_spec) do |t|
38 | t.pattern = "spec/requests/#{version}/"
39 | t.rspec_opts =
40 | "-f Dox::Formatter --order defined -t dox -o public/#{docs_path}/apispec.md.erb"
41 | end
42 |
43 | Rake::Task['api_spec'].invoke
44 | end
45 |
46 | task :html, [:version, :docs_path, :host] => :erb do |_, args|
47 | version = args[:version] || :v1
48 | docs_path = args[:docs_path] || "api/#{version}/docs"
49 | `node_modules/.bin/aglio -i public/#{docs_path}/apispec.md -o public/#{docs_path}/index.html --theme-full-width --theme-variables flatly`
50 | end
51 |
52 | task :open, [:version, :docs_path, :host] => :html do |_, args|
53 | version = args[:version] || :v1
54 | docs_path = args[:docs_path] || "api/#{version}/docs"
55 |
56 | `open public/#{docs_path}/index.html`
57 | end
58 |
59 | task :erb, [:version, :docs_path, :host] => [:environment, :md] do |_, args|
60 | require 'erb'
61 |
62 | host = args[:host] || 'http://localhost:3000'
63 | version = args[:version] || :v1
64 | docs_path = args[:docs_path] || "api/#{version}/docs"
65 |
66 | File.open("public/#{docs_path}/apispec.md", 'w') do |f|
67 | f.write(ERB.new(File.read("public/#{docs_path}/apispec.md.erb")).result(binding))
68 | end
69 | end
70 | end
71 | ```
72 |
73 | ```markdown
74 | FORMAT: 1A
75 | HOST: <%= host %>
76 |
77 |
78 | # My app API
79 | An API documentation for my app
80 | ```
81 |
82 | ```sh
83 | rake 'api:doc:html[v1, api/v1/docs, https://example.com]'
84 | ```
85 |
86 | The above example can be simplified if some of the features are not needed.
87 |
88 | ## Deploy script
89 |
90 | The mina-dox plugin includes the `dox:publish` task, which runs `rake dox:html` and copies the generated documentation to the server.
91 |
92 | ```sh
93 | echo "=========== bundle install ==========="
94 | bundle install --deployment --path vendor/bundle
95 | echo "=========== deploy ==========="
96 | bundle exec mina production ssh_keyscan_domain deploy
97 |
98 | echo "=========== setup for tests ==========="
99 | bundle exec secrets pull -e development -y
100 | bundle exec rake db:setup
101 | bundle exec rake db:test:prepare
102 |
103 | echo "=========== install aglio and themes ==========="
104 | yarn install
105 |
106 | echo "=========== publish api doc ==========="
107 | bundle exec mina production dox:publish
108 | ```
109 |
--------------------------------------------------------------------------------
/Misc/Fiscalization.md:
--------------------------------------------------------------------------------
1 | ## Fiscalizer
2 |
3 | We use the [fiscalizer gem](https://github.com/infinum/fiscalizer) to transfer various document types from a business entity to the tax authorities.
4 |
5 | ### Setup & Usage
6 |
7 | Everything about setup and usage of this gem is explained at [fiscalizer gem](https://github.com/infinum/fiscalizer).
8 |
9 | ### Certificates
10 |
11 | #### Environments:
12 |
13 | + ##### Production environment
14 |
15 | Requires only one certificate - application certificate. It is most often called `FISCAL_1.p12`. It contains the public and private key, and the CA (`Certificate authority`) certificate.
16 |
17 | Secrets file example:
18 |
19 | ```Ruby
20 | fiscalization_app_cert_path: 'cert/production/FISKAL_1.p12'
21 | fiscalization_ca_cert_path: ''
22 | ```
23 |
24 |
25 | + ##### Development & staging environment
26 |
27 | Requires 2 certificates - both application and server certificate. The application certificate (`FISCAL_1.p12`) contains the public and private key. The server certificate (most often `fina_ca.pem`) contains the required CA certificates.
28 |
29 | Secrets file example:
30 |
31 | ```Ruby
32 | fiscalization_app_cert_path: 'cert/development/FISKAL_1.p12'
33 | fiscalization_ca_cert_path: 'cert/development/fina_ca.pem'
34 | ```
35 |
36 | #### Application certificate unpacking
37 |
38 | To view the content of the application certificate locally, you need to unpack it with this command:
39 |
40 | ```
41 | openssl pkcs12 -in FISKAL_1.p12 -out FISKAL_1.pem -nodes
42 | ```
43 |
44 | After running this command, you are prompted to input the `fiscalization password`.
45 |
46 | #### Create your own certificate
47 |
48 | If you need to test some features that require certificates but you don't have them and your request cannot be sent, you can create a certificate following this [tutorial](https://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/).
49 | Once done, create a `.p12` file following these two steps:
50 |
51 | 1. Copy the private key and SSL certificate to a plain text file. The private key should be at the top with the SSL certificate below. In the example, we use "filename.txt" as the name of the file containing the private key and SSL certificate.
52 |
53 | 2. `openssl pkcs12 -export -in filename.txt -out filename.p12`
54 |
--------------------------------------------------------------------------------
/Starting a new project.md:
--------------------------------------------------------------------------------
1 | ## Starting a new project
2 |
3 | When you're starting a new project, there are a few things you need to do:
4 |
5 | #### 1. Open a repository
6 |
7 | Ask your team lead or DevOps to open a repository.
8 |
9 | #### 2. Fill out the project setup sheet
10 |
11 | We've come up with a project setup template in cooperation with the DevOps team. Its purpose is to provide the DevOps with all the details needed for deploying your application to staging and production servers.
12 |
13 | It contains general info about your project that your project manager can fill out, as well as more technical information like frameworks and technologies used, the build and deploy setup, third party services that need to be set up, etc.
14 |
15 | Ask your PM for a link to the sheet template.
16 |
17 | **Fill in the blanks on backend-related stuff.**
18 |
19 | If you need any other services that aren't mentioned, **provide as much information as possible**
20 |
21 | **The project setup sheet needs to be up to date** with new changes to the project setup and services used. If you're adding some new dependency or service or changing something, please update it in the project setup sheet and notify DevOps to make these changes.
22 |
23 |
24 | #### 3. Generate a new application
25 |
26 | Use the [**default rails template**](https://github.com/infinum/default_rails_template/) to start your new application.
27 |
28 | Most of our work is based on the Rails framework. We have some standard configurations and gems that are basically in every Rails application. To make our lives easier, we've made a default template to generate new Rails applications that meet those standards.
29 |
30 | Please always update the default rails template if something gets broken or out of date when you're starting a new project.
31 |
32 |
33 | #### 4. Check for new/better gems
34 |
35 | We usually use specific gems for some purposes, e.g. Devise for authentication, Pundit for authorization, etc. That doesn't mean we need to use those gems necessarily.
36 |
37 | When adding a gem to your application, check if there's some new and better gem for that purpose.
38 |
39 | When checking out a gem, always look for these things:
40 |
41 | * is the gem maintained? when was the last commit?
42 | * how many stars does it have?
43 | * what is the ratio between open and closed issues?
44 |
45 |
46 | #### 5. Fill out the readme file
47 |
48 | After setting up a project, fill out the readme file with all the necessary details about the application:
49 |
50 | * dependencies & prerequisites
51 | * setup instructions
52 | * development instructions
53 | * deployment instructions
54 | * test instructions
55 | * any other project specific information that someone who takes over a project needs to know
56 |
57 |
58 | #### 6. Create an ER diagram
59 |
60 | Before you start coding, you always need to create an ER diagram for your database. Go through the project specification and list all the entities and their attributes and construct relationships between listed entities.
61 |
62 | For creating an ER diagram use:
63 |
64 | * [DB diagram](https://dbdiagram.io/)
65 | * [MySQL Workbench](https://dev.mysql.com/downloads/workbench/)
66 |
67 | After creating an ER diagram, you need to go through an architecture review. You can read more about it in the [Architecture review chapter](Architecture review)
68 |
69 | If you need to create an application or a server architecture diagram use:
70 |
71 | * [Gliffy](https://www.gliffy.com/)
72 |
73 | If you need to create a sequence diagram use:
74 |
75 | * [Web Sequence Diagram](https://www.websequencediagrams.com/)
76 |
--------------------------------------------------------------------------------
/Workflows/Architecture review.md:
--------------------------------------------------------------------------------
1 | ## The reason behind it
2 |
3 | Before you start programming, your application should go through an architecture review.
4 | When we say architecture review, we mostly have the database design and API in mind.
5 |
6 | We do architecture planning and review in order to:
7 |
8 | * have a clear overview of the project before we start coding
9 | * have a clear way of communicating the project architecture to the client
10 | * prevent scope creep
11 | * have better architecture
12 |
13 | **Database design is by far the most important part of a web application.**
14 |
15 | ## Architecture review timeline
16 |
17 | Please follow this timeline:
18 |
19 | 1. A project manager asks you to go into an initial project meeting.
20 | 2. You should never go alone as the only Rails developer in the meeting—always take another team member with you.
21 | 3. There are no stupid questions in these meetings. It's better to understand everything at this point, than make assumptions two weeks later.
22 | 4. Ask the project manager to give you the project specification.
23 | 5. Once you're done with the initial project meeting and have the specification, sit down with the member of your team that was at the meeting with you and design the database. You can do this on a whiteboard or a piece of paper, or use a tool, such as [Gliffy](https://www.gliffy.com/) or [MySQL Workbench](https://dev.mysql.com/downloads/workbench/). If you need to draw a sequence diagram, use [Web Sequence Diagram](https://www.websequencediagrams.com/).
24 | 6. Consult the project manager at will and add new discoveries to the specification if you find that something's missing.
25 | 7. Don't hesitate to involve other team members since this is the most important part of the app.
26 | 8. Once you've finished the database design, it has to be approved by someone from the management.
27 | 9. Once your architecture has been approved, you can generate a new Rails project. Read more about that on the next page.
28 |
29 | In order to start coding, the whole project must go through an architecture review.
30 | If this is not possible for any reason, the project should be split into phases. In that case, each phase needs to go through an architecture review before coding can begin.
31 |
32 | Sometimes, you will notice some obvious mistakes you couldn't have seen when you started the project. If these make a large architecture overturn, go back to step 8.
33 |
34 | **Think of this as a never bending rule.**
35 |
--------------------------------------------------------------------------------
/Workflows/Dependencies.md:
--------------------------------------------------------------------------------
1 | > Every dependency in your application has the potential to bloat your app, to destabilize your app, to inject odd behaviour via monkeypatching or buggy native code.
2 | >
3 | > When you are considering adding a dependency to your Rails app, it’s a good idea to do a quick sanity check, in order of preference:
4 | >
5 | > Do I really need this at all? Kill it.
6 | >
7 | > Can I implement the required minimal functionality myself? Own it.
8 | >
9 | > If you need a gem:
10 | >
11 | > Does the gem have a native extension? Look for pure ruby alternatives.
12 | >
13 | > Does the gem transitively pull in a lot of other gems? Look for simpler alternatives.
14 | >
15 | > Gems with native extensions can destabilize your system; they can be the source of mysterious bugs and crashes. Avoid gems which pull in more dependencies than their value warrants.
16 | >
17 | > --