Ruby on Rails - Найпоширеніші помилки новачка
Перед початком. хотів би ще згадати у тому, що одні й самі завдання потрібно вирішувати однаково. У Вас особисто, або в команді, має бути style guide, який охоплює всі ключові моменти оформлення та організації коду. Одинаковий код дозволить легше взаємодіяти команді та допускати менше помилок.
Перша частина присвячена моделям. Цей шар містить у собі всю бізнес логіку, одразу і найбільшу кількість помилок у її реалізації.
Отже, новачки:
Не використовують методи, що автоматично генеруються.
Зазвичай Rails і багато геми додають багато корисних допоміжних методів в об'єкти, з якими працюють. Потрібно знати ці особливості та використати. Наприклад, для boolean полів rails автоматично додає предикати. Це методи, назва яких закінчується знаком питання. Використовувати їх вважається правилом гарного тону.
Не розуміють, звідки береться N+1 зарість
Розуміння того, як ORM працює з базою, дуже важливо, але не завжди є хоча б навіть на базовому рівні. Тому майже не використовуються методи includes, preload, eager_load. Не використовується гем bullet. У першому випадку виконається N+1 запит до бази даних, де N - кількість зданих домашніх завдань. Це може бути і 10, і 20, і навіть 100 запитів. У другому коді будевсього 2 запити!
Не використовують скоупи
Скоупи дозволяють приховати імплементацію бази даних та уникалізувати код. Крім того, їх використання роблять код набагато читанішим. Тому що вони показують наміри розробника, а чи не структуру бази.
Не знають різницю між size та count у ActiveRecord::Relation
Різниця в тому, що count – завжди зробить запит, size – перевірить, ачи не пораховано потрібне значення у якомусь полі. Докладніше - дивитися screencast про CounterCache
Мюслі звичайного новачка
Я завжди пишу count просто тому, що мені зазвичай це слово з інших мов і воно мені більше подобається.
І мюслі того, хто читав rails guide
Я завжди пишу size тому що знаю, що в разі потреби додавання кешу, мені потрібно буде просто оновити пару рядків, не шукаючи count по всьому проекту
Не знають різницю між after_create та after_commit
Дані моделі, у тому числі її новий ID всередині after_create доступний, а ззовні ще немає. Тому що транзакцію ще не завершено. Якщо після створення запису в базі даних, я хочу покласти його ID в redis або будь-яке інше сховище. то:
У випадкуafter_create це може призвести до невалідних даних, якщо ID буде використано до того, як транзакція дійшла до кінця. У разі використання Sidekiq або будь-який інший BackgroundJob я завжди використовуватимуafter_commit, що гарантує цілісність моїх даних.
Завжди використовують ORM
Хоча робота з об'єктами і є найзручнішою, вона досить повільна та вимоглива по пам'яті. Не завжди є розуміння, який код як працює, і як його краще оптимізувати
Не знають різницю між dependent destroy vs delete_all
dependent destroy перед видаленням вибере всі пов'язані записи, побудує їх об'єкти і кожному так само викличе метод destroy. Такий підхід видалить усі пов'язані дані. Перестає працювати на великих обсягах даних
dependent delete_all виконає видалення через SQL запит, це швидко, але доведеться самому дбати про цілісність бази
Не використовують методи з бенгом
Згідно з угодами, в ім'я методу додається bang(!)у 2х випадках: якщо метод змінює об'єкт, у якому він викликається чи якщо метод викидає виняток, у разі невдалого виконання. Про другу особливість часто забувають. Якщо в коді щось не так, про це потрібно дізнатися якомога раніше. Тобто, якщо ви ніяк не обробляєте результат збереження запису в базу даних, то краще викинути виняток, щоб дізнатися про те, що в конкретній ділянці коду можуть оброблятися невалідні дані.
У міграціях не ставлять дефолтні поля
Якщо у моделі поле має значення за промовчанням, його потрібно встановити через базу даних.
У міграціях не ставлять constraints
Чим більше обмежень ми накладемо на базу, тим надійнішим буде наш додаток. Не забуваймо про null: false. Профіль, за жодних умов, не може існувати без користувача.
У міграціях не пишуть зворотну міграцію
Міграція повинна дозволяти себе відкотити, інакше, який у ній сенс.
Продовження слідує!
Англійську версію цієї статті можна почитати у нашому корпоративному блозі тут