|
1 |
| -# Coding standard |
| 1 | +# Coding Convention |
2 | 2 |
|
3 |
| -## Programming |
4 |
| - |
5 |
| -* Write DRY code during development any project. |
6 |
| - |
7 |
| -* Use spaces around operators, after commas, colons and semicolons, around `{` and before `}`. |
8 |
| - |
9 |
| -* No spaces after `(`, `[` No spaces before `]`, `)` |
10 |
| - |
11 |
| -* Order variables and methods alphabetically when possible. |
12 |
| - |
13 |
| -* Use 2 space indentation. |
14 |
| - |
15 |
| -* Do not make any spalling mistakes or grammar mistakes. Use proper english words. |
16 |
| - |
17 |
| -* put space if needs. like- `<% if current_user %>`(correct) `<%if current_user%>`(wrong). |
18 |
| - Another example: `"hello"` (correct) `" hello "` (wrong) |
19 |
| - |
20 |
| -* Use valid syntax. If you are using rails 5 version, then follow rails 5 syntax. |
21 |
| - Example: don't use `=>` like- `(:presence => true)`, use `(presence: true)` |
22 |
| - |
23 |
| -* Don't use an empty line at the beginning or end of methods, blocks or conditionals. |
24 |
| - Use an empty line between methods, blocks and conditionals. |
25 |
| - |
26 |
| - ```ruby |
27 |
| - # bad |
28 |
| - def hello |
29 |
| - |
30 |
| - puts "Hello world" |
31 |
| - end |
32 |
| - |
33 |
| - # good |
34 |
| - def hello |
35 |
| - puts "Hello world" |
36 |
| - end |
37 |
| - |
38 |
| - # bad |
39 |
| - [2, 3, 4].map{ |x| x + 2 } |
40 |
| - if array.empty? |
41 |
| - # do some thing |
42 |
| - end |
43 |
| - |
44 |
| - # good |
45 |
| - [2, 3, 4].map{ |x| x + 2 } |
46 |
| - |
47 |
| - if array.empty? |
48 |
| - # do some thing |
49 |
| - end |
50 |
| - ``` |
51 |
| -* Do not repeat same code, write it inside helper. Example: suppose you are styling a button |
52 |
| - with some front-awesome style and this same button needs in more than one places, then write |
53 |
| - it inside a helper method and then call it from view and pass link path. |
54 |
| - |
55 |
| - ```erb |
56 |
| - # bad |
57 |
| - # index.html.erb |
58 |
| - <%= link_to ('<i class="fa fa-trash" title="Delete Details"></i> Delete').html_safe, |
59 |
| - employee_path(employee), |
60 |
| - method: :delete, |
61 |
| - data: { confirm: "Are you sure?" }, |
62 |
| - class: 'btn btn-danger btn-sm' %> |
63 |
| -
|
64 |
| - # show.html.erb |
65 |
| - <%= link_to ('<i class="fa fa-trash" title="Delete Details"></i> Delete').html_safe, |
66 |
| - employee_path(@employee), |
67 |
| - method: :delete, |
68 |
| - data: { confirm: "Are you sure?" }, |
69 |
| - class: 'btn btn-danger btn-sm' %> |
70 |
| -
|
71 |
| - # good |
72 |
| - # helper.rb |
73 |
| - def delete_link(path) |
74 |
| - link_to ('<i class="fa fa-trash" title="Delete Details"></i> Delete').html_safe, |
75 |
| - path, |
76 |
| - method: :delete, |
77 |
| - data: { confirm: "Are you sure?" }, |
78 |
| - class: 'btn btn-danger btn-sm' |
79 |
| - end |
80 |
| -
|
81 |
| - # index.html.erb |
82 |
| - <%= delete_link(employee_path(employee)) %> |
83 |
| -
|
84 |
| - # show.html.erb |
85 |
| - <%= delete_link(employee_path(@employee)) %> |
86 |
| - ``` |
87 |
| -* Name of the helper(or variable/funcation/scope) should reflect its purpose. |
88 |
| - |
89 |
| -* Try to avoid comment messages unless the code is too complicated. |
90 |
| - |
91 |
| -## git |
92 |
| - |
93 |
| -* Write a good commit message with story number(if present). |
94 |
| - |
95 |
| - ``` |
96 |
| - [#102] Update scope for unattach items |
97 |
| - ``` |
98 |
| - |
99 |
| -* Remove buffer file during commit your changes. |
100 |
| - |
101 |
| -* Create different branch for different story and Each branch should contain maximum 2 commit messages. |
102 |
| - |
103 |
| -* Create Pull Request only after finish the task competely of a particular story. |
104 |
| - |
105 |
| -* Do not change anything in master branch, always create seperate branch. |
106 |
| - |
107 |
| -* Rebase frequently to incorporate upstream changes. |
108 |
| - |
109 |
| -* If any branch merge with master branch, then delete that branch from local as well as master. |
110 |
| - |
111 |
| -* Before creating Pull Request review code yourself once. |
112 |
| - |
113 |
| -* Use `gitk` to see the changes from local machine |
114 |
| - |
115 |
| -* Do not upload credentials files or any secret file in git, add them in `.gitignore` |
116 |
| - |
117 |
| -* Always create new branch from master. |
118 |
| - |
119 |
| -## Bundler |
120 |
| - |
121 |
| -* Put gems in alphabetical order in the Gemfile. |
122 |
| - |
123 |
| -* Do not use any unnecessary gems in your project. |
124 |
| - |
125 |
| -* Use only established gems in your projects. If you're contemplating on |
126 |
| - including some little-known gem you should do a careful review of its source |
127 |
| - code first. |
128 |
| - |
129 |
| -* If your project needs different gems for different environments, then group it for that specific environment. |
130 |
| - ```ruby |
131 |
| - group :development, :test do |
132 |
| - gem 'mysql2' #mysql for development |
133 |
| - gem 'pry-rails', "~> 0.3.4" |
134 |
| - end |
135 |
| - |
136 |
| - group :production do |
137 |
| - gem 'pg' #postgresql for production |
138 |
| - end |
139 |
| - ``` |
140 |
| - |
141 |
| -* Do not remove the `Gemfile.lock` from version control. This is not some |
142 |
| - randomly generated file - it makes sure that all of your team members get the |
143 |
| - same gem versions when they do a `bundle install`. |
144 |
| - |
145 |
| -## Migrations |
146 |
| - |
147 |
| -* Keep the `schema.rb` under version control and arrange it well, so that it clearly understandable. |
148 |
| - |
149 |
| -* Add database level validation as well model level validation |
150 |
| - |
151 |
| -* Enforce foreign-key constraints. |
152 |
| - |
153 |
| -* When writing constructive migrations (adding tables or columns), |
154 |
| - use the `change` method instead of `up` and `down` methods. |
155 |
| - ```Ruby |
156 |
| - # the old way |
157 |
| - class AddNameToPeople < ActiveRecord::Migration |
158 |
| - def up |
159 |
| - add_column :people, :name, :string |
160 |
| - end |
161 |
| - |
162 |
| - def down |
163 |
| - remove_column :people, :name |
164 |
| - end |
165 |
| - end |
166 |
| - |
167 |
| - # the new preferred way |
168 |
| - class AddNameToPeople < ActiveRecord::Migration |
169 |
| - def change |
170 |
| - add_column :people, :name, :string |
171 |
| - end |
172 |
| - end |
173 |
| - ``` |
174 |
| - |
175 |
| -* If you are writing something within `up` migration, write it in the reverse order within |
176 |
| - `down` migration if needed. |
177 |
| - |
178 |
| -* After migrating a migration use `rollback` command to check whether the database can |
179 |
| - return to its previous state or not. |
180 |
| - |
181 |
| -## Routing |
182 |
| - |
183 |
| -* When you need to add more actions use `member` and `collection` routes. |
184 |
| - |
185 |
| - ```Ruby |
186 |
| - # bad |
187 |
| - get 'subscriptions/:id/unsubscribe' |
188 |
| - resources :subscriptions |
189 |
| - |
190 |
| - # good |
191 |
| - resources :subscriptions do |
192 |
| - get 'unsubscribe', on: :member |
193 |
| - end |
194 |
| - |
195 |
| - # bad |
196 |
| - get 'photos/search' |
197 |
| - resources :photos |
198 |
| - |
199 |
| - # good |
200 |
| - resources :photos do |
201 |
| - get 'search', on: :collection |
202 |
| - end |
203 |
| - ``` |
204 |
| - |
205 |
| -* If you need to define multiple `member/collection` routes use the |
206 |
| - alternative block syntax. |
207 |
| - |
208 |
| - ```Ruby |
209 |
| - resources :items do |
210 |
| - member do |
211 |
| - get 'allocate' |
212 |
| - put 'reallocate' |
213 |
| - # more routes |
214 |
| - end |
215 |
| - end |
216 |
| - |
217 |
| - resources :photos do |
218 |
| - collection do |
219 |
| - get 'search' |
220 |
| - # more routes |
221 |
| - end |
222 |
| - end |
223 |
| - ``` |
224 |
| - |
225 |
| -* Use nested routes to express better the relationship between ActiveRecord |
226 |
| - models. |
227 |
| - |
228 |
| - ```Ruby |
229 |
| - class Post < ActiveRecord::Base |
230 |
| - has_many :comments |
231 |
| - end |
232 |
| - |
233 |
| - class Comments < ActiveRecord::Base |
234 |
| - belongs_to :post |
235 |
| - end |
236 |
| - |
237 |
| - # routes.rb |
238 |
| - resources :posts do |
239 |
| - resources :comments |
240 |
| - end |
241 |
| - ``` |
242 |
| -* Left unnecessary routes if those routes are not used. Use `except/only` for the purpose. |
243 |
| - |
244 |
| - ```ruby |
245 |
| - resources :users, except: [:show] |
246 |
| - resources :employee, except: [:show, :edit, :update] |
247 |
| - ``` |
248 |
| - |
249 |
| -## Controllers |
250 |
| - |
251 |
| -* Keep the controllers skinny - they should only retrieve data for the view |
252 |
| - layer and shouldn't contain any business logic (all the business logic |
253 |
| - should naturally reside in the model). |
254 |
| - |
255 |
| -* If more than one action in a controller contains same lines of code, then write |
256 |
| - it into seperate a method and use callback funcation to invoke it on those action. |
257 |
| - |
258 |
| - ```ruby |
259 |
| - # bad |
260 |
| - # controller.rb |
261 |
| - def edit |
262 |
| - @category = Category.find(params[:id]) |
263 |
| - end |
264 |
| - |
265 |
| - def show |
266 |
| - @category = Category.find(params[:id]) |
267 |
| - @category_items = @category.items.paginate(page: params[:page], per_page: 5) |
268 |
| - end |
269 |
| - |
270 |
| - #good |
271 |
| - # controller.rb |
272 |
| - before_action :get_category, only: [:edit, :show] |
273 |
| - def show |
274 |
| - @category_items = @category.items.paginate(page: params[:page], per_page: 5) |
275 |
| - end |
276 |
| - |
277 |
| - def get_category |
278 |
| - @category = Category.find(params[:id]) |
279 |
| - end |
280 |
| - ``` |
281 |
| - |
282 |
| -* If `current_user` exists in browser, then don't need to hit database every time you need |
283 |
| - `curent_user`. |
284 |
| - ```ruby |
285 |
| - #bad |
286 |
| - def current_user |
287 |
| - @current_user = User.find(session[:user_id]) if session[:user_id] |
288 |
| - end |
289 |
| - |
290 |
| - #good |
291 |
| - def current_user |
292 |
| - @current_user ||= User.find(session[:user_id]) if session[:user_id] |
293 |
| - end |
294 |
| - ``` |
295 |
| -* Remove n + 1 query problem from all places in your project. |
296 |
| - |
297 |
| -## Model |
298 |
| - |
299 |
| -* Write your model simple and well formated. |
300 |
| - Group same type of method. Follow this coding pattern for model. |
301 |
| - ```ruby |
302 |
| - class Issue < ActiveRecord::Base |
303 |
| - enum priority: [:high, :medium, :low, :as_soon_as_possible] |
304 |
| - |
305 |
| - belongs_to :item, optional: true |
306 |
| - belongs_to :system, optional: true |
307 |
| - |
308 |
| - has_many :resolution, optional: true |
309 |
| - |
310 |
| - validates :title, presence: true |
311 |
| - validate :item_or_system_presence |
312 |
| - validate :item_closed_at_limitation |
313 |
| - validate :system_closed_at_limitation |
314 |
| - |
315 |
| - scope :order_desending, -> { order('created_at DESC') } |
316 |
| - scope :unclosed, -> { where(closed_at: nil) } |
317 |
| - |
318 |
| - def item_or_system_presence |
319 |
| - unless [item, system].any? |
320 |
| - errors.add :base, 'Item / System must be present!' |
321 |
| - end |
322 |
| - end |
323 |
| - end |
324 |
| - ``` |
325 |
| - |
326 |
| -* Generate model from terminal. Do not create `model.rb` and migration your own, let |
327 |
| - rails to do it for you. |
328 |
| - |
329 |
| - ``` |
330 |
| - rails generate model Item name:string description:text |
331 |
| - ``` |
332 |
| - |
333 |
| -* Choose a proper name for methods, scopes etc. |
| 3 | +1. <a href="/git.md">Git</a> |
| 4 | +2. <a href="/ruby.md">Ruby</a> |
| 5 | +3. <a href="/rails.md">Rails</a> |
0 commit comments