model = MyModel.find_by(criteria).includes(:associations) MyLogic.do_logic(model) model.save! redirect_to :show end end module MyLogic extend self def do_logic(model) # тут никакого доступа к базе - чисто бизнес логика end end
проверка бизнес-логики" if "вторая проверка" "поставить флаг 1" else "поставить флаг 2" end else "поставить флаг 3" end end end → чтоб протестировать, приходится настроить много сложных контекстов и выполнить много сложных проверок результатов
end module MyLogic extend self def update_related_models if complex_check_1 if complex_check_2 update_flag(1) else update_flag(2) end else update_flag(3) end end end
строк кода → (N+1)1000 запросов к базе откуда попало → только самое базовое покрытие тестами Задача - сделать так, чтобы это работало быстрее. (Переписывать не получится)
посредством includes() и preload() → остается все равно куча N+1 запросов, например, что тут предзагружать? Author's top published post: <%= @author.posts.published.order(:rating).first %>
объектов 4000 → периодов, на данный момент, 2 → показателей 1000 → перемножаем, получаем 8 000 000 строк в таблице нужно показать для выбранного объекта все доступные периоды (периоды у всех разные) (переписывать не получится)
name VARCHAR NOT NULL, position INT NOT NULL) CREATE UNIQUE INDEX items_position ON items (position) ну и как теперь поменять строки местами, не теряя целостности? item1 = Item.create!(name: 'Foo', position: 1) item2 = Item.create!(name: 'Bar', position: 2) # упс... item1.update!(position: 2)
IS NOT NULL правда, придется отступить целостность на проверке NOT NULL: # упс... item2.update!(position: nil) item1.update!(position: 2) item2.update!(position: 1)
NOT NULL, name VARCHAR NOT NULL, position INT) CONSTRAINT position_is_not_null CHECK (position IS NOT NULL); теперь... Item.transaction do Item.defer_constraints item1.update!(position: 2) item2.update!(position: 1) # ! end
do |street_json| street = city.streets. find_by(street_json["name"]) street.update!(length: street_json["length"]) end end хотелось бы @cities = City.preload(:streets) ...ну и что потом с ними делать?
end cities = City.preload(:streets) json["cities"].each do |city_json| city = cities.detect_by(name: city_json["name"]) city_json["streets"].each do |street_json| street = city.streets. detect_or_initialize_by(street_json["name"]) street.update!(length: street_json["length"]) end end