Pull to refresh

Comments 23

t.integer "user_id", :null => false
А как насчёт более православного
t.belongs_to :user
Плюс с limit спорный момент — не все базы принимают оные во внимание и очень часто делают лишь внешнее ограничение, выделяя памяти с излишком.
Вы имеете в виду…

t.references :user, :null => false


Не знаю почему автор это не использовал, но согласен, что так будет правильно.
Да, именно (и необязательно references, belongs_to вполне работает аналогичным образом :)).
Плюс использование NOT NULL в определении это скорее оптимизация баз данных и этот момент непосредственно к rails отношения не имеет — разрывы связей должна пресекать валидация, а если вы хотите отслеживать связи со стороны базы данных, то для этого есть другие более подходящие методы.
И очень интересен момент с тем, что автор сначала говорит «даже если в нашем коде валидации будут баги», а потом наставляет «не принимайте пул-реквесты без тестов, которые проходят успешно».

В общем со всех сторон спорные замечания, хотя совсем уж новичкам может чем и помогут.
Ну например, можно просто забыть или не подумать о каком-то типе валидации — это как бы и не баг и на тесты не повляет.

А так-то да, статья для начинающих в основном.
что-то тут c математикой 1'000'000/100 = 1000
Спасибо, исправил. Хотя в оригинале именно так, а у меня глаз замылился :)
А почему именно Rails? Незнание фреймворка, непонимание ООП прочее — по-моему вполне общие проблемы. Мне даже кажется, что изложенные здесь ошибки чаще в пхп проектах встречаются, всетаки рельсы пока не настолько популярны
Хочу добавить, что работа с таблицами, где в столбцах null недопустим выполняется несколько быстрее. null: false также имеет смысл для такой микро-оптимизации работы приложения. А еще ошибка — это не использование ключей или создание лишних ключей, которые не используются — все это сказывается на производительности.
Я считаю, что некорректно использовать схему БД для «микро-оптимизации». Наличие констрейнтов должно целиком и полностью определяться бизнес-логикой. Констрейнты нужны для исключения невозможных данных, когда в алгоритмах возможны ошибки. Также они несут смысловую нагрузку, отражая часть архитектуры приложения.
Мой опыт показывает, что от SQL еще никто не умер. Неплохо, конечно, поручать работу Arel и руби вообще, но иногда массовые операции проще проводить через SQL. В первую очередь это касается DDL, потому что с выборками как правило можно извернуться достаточно элегантно.
никто еще не умер и от SQL кода во вьюшках, но мировой опыт показывает, что это вызывает воспаление геморроидальных вен
да и поручать работу руби тоже не стоит
Мёртвому припарки.
Возьмём DataMapper на
User.all(:purchased => true).each do |customer|
customer.grant_role(:customer)
end


И получим:
UPDATE users
SET role=customer
WHERE COUNT(purchases) > 0

И не нужно вытягивать записи. И даже пакетами по 1000 штук. И изучать SQL не обязательно.
Зависит от ситуации. Когда вы пишете сложную выборку или пакетное обновление по сложным критериям, вы ведь всё равно пишете это на SQL и от переписывания её на ARel никому лучше не станет, а читабельность упадёт до уровня «без бутылки не разберёшься». Как ни крути, для сложных запросов ничего элегантнее raw SQL пока не придумали.
Мне как раз таки сложную выборку проще понять в AREL, это раз
во вторых обычно приходится статические запросы с 3мя и больше join на больших таблицах разбивать на отдельные запросы для производительности

третье — (основная моя мысль) составлять на лету сложный запрос ( в котором WHERE условия и JOIN таблички подключаются в зависимости от других бизнес-условий) гораздо проще и понятней через AREL, чем пытаться работать со строкой

четвертое — портабельность, я легко переключаюсь между mysql, postgresql и sqlite

все это мое имхо, я вижу явные преимущества в использовании AREL, кто считает что SQL строка удобней — дело его.
> Мне как раз таки сложную выборку проще понять в AREL, это раз

Это очень странно, возможно Вы начали работу с СУБД сразу с ORM. Не вижу другого объяснения почему SQL-запрос может казаться сложнее, чем конкатенация кучи методов. Особенно с учётом того, что сложная выборка на ARel занимает обычно в 2-3 раза больше строк, чем на SQL.

> я легко переключаюсь между mysql, postgresql и sqlite

Зачастую это не более, чем самообман.
Сложные запросы, как правило, используют возможности конкретной СУБД. А если не использует, то запрос скорее просто длинный, а не сложный.
Хотя в целом соглашусь, что надо умело сочетать ORM c raw-SQL и не злоупотреблять ни тем, ни другим. Надо использовать то, что проще в конкретной ситуации. Я ни в коем случае не призываю везде использовать raw-SQL, т.к. это не менее глупо, чем везде использовать ARel.
> Это очень странно, возможно Вы начали работу с СУБД сразу с ORM.
:) познакомился я с SQL в 2000г на СУБД Informix, в то время очень крутой, в то время никто и не слышал об ORM

кол-во строк не показатель, обычно сложный SQL в ruby (в принципе не важно в каком языке) длинная строка в которой сходу ничего не поймешь, AREL вносит ясность
если хотите — в личку могу скинуть примеры кода и некоторые кейсы, когда использование SQL было бы гораздо сложней

я не агитирую полностью отказаться от SQL, возможно использование каких-то простых команд типа TRUNCATE. Но по возможности следует пользоваться AREL (имхо).

1 совет — непонятно зачем так делать, ну допустим, мы уверены, что валидацию напишем с багами, что дальше? — перекладывать часть валидации на уровень бд? Ок, валидация прошла, а в бд запись не сохранили, что будет с приложением? Надо дополнительно отлавливать исключения. ИМХО, проще написать нормальную валидацию и протестить это.

2 совет — имеется в виду, что можно не следовать конвенциям, а писать что угодно как угодно и прикручивать это к фреймворку? Конечно, можно, только «назачем»

3 совет — да это ж вёрстка, это должно быть в шаблоне, а не хелпере

Последняя рекомендация вообще относится к workflow — итого, топик бы я охарактеризовал как «вредные советы». Хотя автор оригинальной статьи честно написал в предисловии, что он
а также немало прочитал и написал плохого кода на Ruby
так что всё соответствует :)
1) Очень вредный совет — нужно делать с точностью, да наоборот. Валидацию и проверку целостности данных лучше поручить уровню кода приложения, а не размывать её между кодом и БД. Тем более что, при валидации на уровне БД будет необходимо учесть возможные исключения, и обработать их. И это усложнит код и поддержку помимо всего прочего.
2) Смысл не очень понятен, надеюсь автор не призывает нарушать соглашения без серьёзных на то причин
3) Раньше так тоже думал, пока не пришёл к выводу, что лучше использовать темплейты, поскольку они более наглядные и читаемые.
html = <<-CODE
<li class="vehicle_list">
 %link 
</li>
CODE
html % { link: link_to("#{vehicle.title.upcase} Sale", show_all_styles_path(vehicle.id, vehicle.url_title) }
Дрянь. Выброс очередного рубистар-ванаби. И, да, если нужно идти поперек фрейворка, берем в руки Руби или Синатру. Фреймворк (любой), только тем и хорош, что если следовать его гайдам, то все идет гладко.
Что, не уменьшает заслуг переводчика, который дал пищу для размышлений. :)
Sign up to leave a comment.

Articles