<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Vladislav Kopylov on Medium]]></title>
        <description><![CDATA[Stories by Vladislav Kopylov on Medium]]></description>
        <link>https://medium.com/@kopilov-vlad?source=rss-32b1b50518de------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*sjGa59Ml8vEj7-7Faf-rCw.jpeg</url>
            <title>Stories by Vladislav Kopylov on Medium</title>
            <link>https://medium.com/@kopilov-vlad?source=rss-32b1b50518de------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 11 May 2026 09:42:54 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kopilov-vlad/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Кто/Что такое DevOps?]]></title>
            <link>https://kopilov-vlad.medium.com/%D0%BA%D1%82%D0%BE-%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-devops-76d899420950?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/76d899420950</guid>
            <category><![CDATA[gitlab]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[разработка]]></category>
            <category><![CDATA[программирование]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Sat, 26 Jun 2021 09:50:34 GMT</pubDate>
            <atom:updated>2021-06-26T09:50:34.443Z</atom:updated>
            <content:encoded><![CDATA[<p>Данный вопрос однажды возник у меня в голове. Я начал разбираться в теме, смотреть доклады и у меня появилась идея оформить полученные знания в статью. Но экспертов не переплюнешь, поэтому вот ссылочки на лучшие доклады что я нашел на русском языке.</p><h3><strong>Часть 1 — Теория</strong></h3><p>Данный блок про историю, как движение появилось в индустрии и как другие люди сами себе представляют эту профессию.</p><p><strong>Барух Садогурский — DevOps для разработчиков (или против них?!)</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fz-GEbyXKetE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dz-GEbyXKetE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fz-GEbyXKetE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/75d0abb7843f36d92bf355c74bbd1424/href">https://medium.com/media/75d0abb7843f36d92bf355c74bbd1424/href</a></iframe><p>Доклад начинается с того что ведущий пытается сам для себя определить что же такое devops, враг или друг он обычному разработчику 🤔</p><p><strong>Барух Садогурский — DevOps не человек — Мы обречены #27</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FiAxUHlBtO0Q%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DiAxUHlBtO0Q&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FiAxUHlBtO0Q%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/9b895f20dedc1564af89b53639f55c57/href">https://medium.com/media/9b895f20dedc1564af89b53639f55c57/href</a></iframe><p>Данное видео — это не полноценный доклад, а интервью. Но не смотря на это, интервью является органичным продолжением предыдущего выступления (<em>в комментариях есть таймкоды</em>)</p><h3><strong>Часть 2 — Практика</strong></h3><p>Во втором блоке больше практики. Люди делятся своим опытом, советуют какие инструменты используют и на практике показывают чем занимается devops и куда копать чтобы появился опыт в данной сфере.</p><p><strong>Андрей Листочкин — DevOps for A Busy Developer</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F00bPkcqu7yA%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D00bPkcqu7yA&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F00bPkcqu7yA%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/4866ff9b4c1953c1c493500093b37710/href">https://medium.com/media/4866ff9b4c1953c1c493500093b37710/href</a></iframe><p>Докладчик с улыбкой делится своим опытом в данной сфере. Приводит практические примеры задач, инструментов и решений которые можно выбрать 🧑‍💻</p><p><strong>Илья Климов — Ламповый CI/CD. Как и с чего начать</strong></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FCwU-OiS_PEQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DCwU-OiS_PEQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FCwU-OiS_PEQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/768f774287d6fd674b60e1a220bafe68/href">https://medium.com/media/768f774287d6fd674b60e1a220bafe68/href</a></iframe><p>Практическая лекция возможностей CI/DC в GitLab</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=76d899420950" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Список докладов что я советую к просмотру (2021)]]></title>
            <link>https://kopilov-vlad.medium.com/%D1%81%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%B4%D0%BE%D0%BA%D0%BB%D0%B0%D0%B4%D0%BE%D0%B2-%D1%87%D1%82%D0%BE-%D1%8F-%D1%81%D0%BE%D0%B2%D0%B5%D1%82%D1%83%D1%8E-%D0%BA-%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D1%83-2021-ab86ca576358?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/ab86ca576358</guid>
            <category><![CDATA[разработка]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[программирование]]></category>
            <category><![CDATA[ruby]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Sat, 26 Jun 2021 07:53:23 GMT</pubDate>
            <atom:updated>2021-06-26T07:53:23.808Z</atom:updated>
            <content:encoded><![CDATA[<p>Продолжаю свою ежегодную рубрику. Надеюсь что не буду о ней забывать 😅</p><h4><strong>Почему Ruby медленный</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fm73VjmjAnuw&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dm73VjmjAnuw&amp;image=http%3A%2F%2Fi.ytimg.com%2Fvi%2Fm73VjmjAnuw%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/c772c36d41b66e14707c8564c2accc2c/href">https://medium.com/media/c772c36d41b66e14707c8564c2accc2c/href</a></iframe><p>Данный доклад не только про Ruby, он затрагивает тему работы языков программирования. Вкратце, у любого языка есть 3 скилла, как у персонажа в типичной RPG: удобство синтаксиса, скорость работы и расширяемость. Все три прокачать нельзя, поэтому приходится выбирать любые два 😅</p><h4><strong>Ruby CPU and Memory — Pareto principle</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FeYhJWoxgoKA%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeYhJWoxgoKA&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FeYhJWoxgoKA%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/960aa546ae546edf459ae0cf49d504e6/href">https://medium.com/media/960aa546ae546edf459ae0cf49d504e6/href</a></iframe><p>Хороший и вдохновляющий доклад для тех кому нравится или хочется заниматься оптимизацией производительности. Докладчик приводит в пример рабочий кейс как в Купибилет сэкономили большую сумму денег благодаря оптимизации производительности.</p><h4><strong>Небольшие видео Немчинского про книгу Чистый код (Clean Code)</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F5vsfYifNqzk%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D5vsfYifNqzk&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F5vsfYifNqzk%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6c2c96a79f5a179dcc064309c77b3dd0/href">https://medium.com/media/6c2c96a79f5a179dcc064309c77b3dd0/href</a></iframe><p>Книга о которой все слышали, но не все читали. Сергей Немчинский, очень популярный человек на YouTube, в своей ламповой манере говорит основные принципы из книги и добавляет примеры из своего опыта. Советую! На момент написания статьи уже вышло 6 видео на YouTube, все их можно найти через поиск.</p><h4><strong>Дмитрий Цепелев / Как ускорить GraphQL API</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fyz55e2zC5vk%3Flist%3DPLiWUIs1hSNePXPKk4Nj3GD1wlwlYY58n4&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dyz55e2zC5vk&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fyz55e2zC5vk%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/d6f6a539eac67960d0e99a8fffbae3c8/href">https://medium.com/media/d6f6a539eac67960d0e99a8fffbae3c8/href</a></iframe><p>Очень классный доклад в котором собраны все методы ускорения GraphQL. 🚀</p><h4><strong>Методы борьбы с legacy-кодом на примере GitLab</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F3tdfBMRq34o%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D3tdfBMRq34o&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F3tdfBMRq34o%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/7933709fe7fe534ef91fe65e8ec3c7ae/href">https://medium.com/media/7933709fe7fe534ef91fe65e8ec3c7ae/href</a></iframe><p>Доклад показывает как работают люди в больших компаниях с большими проекта. Как там у них все устроено и как они борются в legacy-кодом.</p><h4>Building a Ruby web app using the Ruby Standard Library (Maple Ong)</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FlxczDssLYKA%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DlxczDssLYKA&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FlxczDssLYKA%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/1079e595f093dec3c612f2b2c1d540a4/href">https://medium.com/media/1079e595f093dec3c612f2b2c1d540a4/href</a></iframe><p>Один из самых вдохновляющий докладов на Euruko 2021. Спикер решил написать простое веб-приложение для учета ежедневного кол-во шагов, но чтобы это было интересно, реализовать приложение на чистом Ruby без использования дополнительных библиотек. Дополнительно рассказать как работает TCP/IP протокол и на пальцах показать из каких модулей состоит любой веб-фреймворк а-ля Rails. Очень круто 😮</p><h4><strong>Барух Садогурский — Как правильно продать себя ради фана и профита</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FsEexbEv2iGc%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DsEexbEv2iGc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FsEexbEv2iGc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aa6368bc7e6af58c661bd6079d069dec/href">https://medium.com/media/aa6368bc7e6af58c661bd6079d069dec/href</a></iframe><p>Доклад не только про продвижение себя как специалиста, а также про софт скилз. Спикер быстро пробегает по разным интересным темам и слушатели смогут дальше самостоятельно углубится в то что их заинтересовало.</p><h4><strong>Самое скучное решение: как выбирать технологии, когда ты уже не стартап / Илья Климов</strong></h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FyDcwplt-vm8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DyDcwplt-vm8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FyDcwplt-vm8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ba6c2c70690c39978e48af867e87f2ec/href">https://medium.com/media/ba6c2c70690c39978e48af867e87f2ec/href</a></iframe><p>Еще одно хорошее выступление Ильи Климова о работе над большими проектами. На этот раз затрагивается темы выбора и обновления технологий.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ab86ca576358" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Какую базу данных выбрать под свой проект]]></title>
            <link>https://kopilov-vlad.medium.com/%D0%BA%D0%B0%D0%BA%D1%83%D1%8E-%D0%B1%D0%B0%D0%B7%D1%83-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D1%82%D1%8C-%D0%BF%D0%BE%D0%B4-%D1%81%D0%B2%D0%BE%D0%B9-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82-264a265db188?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/264a265db188</guid>
            <category><![CDATA[разработка]]></category>
            <category><![CDATA[nosql]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[база-знаний]]></category>
            <category><![CDATA[программирование]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Fri, 18 Jun 2021 17:37:53 GMT</pubDate>
            <atom:updated>2021-06-27T09:19:12.059Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/636/1*QHKNyNWpnuc7AgFVnRlk-w.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@tingeyinjurylawfirm?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Tingey Injury Law Firm</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>После прочтения <a href="https://kopilov-vlad.medium.com/откуда-такой-зоопарк-баз-данных-или-введение-в-разнообразие-бд-a99a0fc2371c">предыдущего поста</a> у меня спрашивали советы какую базу данных выбрать под тот или иной проект, поэтому я решил написать еще одну статью, но акцентировать внимание не на историческую часть, а на реализацию той или иной БД и дать практические советы что же них выбрать.</p><h3>TL;DR</h3><ul><li>Если ты пишешь мини приложение — выбирай key-value БД (redis)</li><li>Если нужно быстро сделать прототип — документоориентированная БД (mongoDB)</li><li>Социальная сеть — тебе подойдет графовая БД (neo4j)</li><li>Посчитать статистику — документоориентированная БД (mongoDB)</li><li>Для всего остального есть SQL</li></ul><h3>Техническая часть</h3><p>База данных — это всего лишь инструмент, для решения своей задачи: не только хранить информацию, но и давать интерфейс для манипулирования. Есть два больших семейства БД: SQL и NoSQL. Разберем их подробнее.</p><p><strong>SQL</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*iTgaqEJEy595f2y4Hf5v7A.png" /><figcaption>Microsoft Excel</figcaption></figure><p>SQL, то есть реляционные БД — это такой эксель среди баз данных. <br>Почему? — Потому что данные в этих БД хранятся в табличках как в экселе. В одной БД может быть несколько табличек, как в одном эксельном файле и данные из одной таблицы могут иметь ссылки на другие таблицы. Поэтому когда вы услышал SQL то можете смело представлять себе эксель.</p><p>Такие БД активно используются с 80-х годов. Это уже зрелая и надежная технология с огромной методологической базой.</p><p>SQL развивался в первую очередь как стандарт. Если вы раньше слышали про такие БД как MySQL, SQLite, MariaDB — то знайте что это все реализации SQL и отличия только в нюансах.</p><p><strong>NoSQL</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/1*Vu-aGs7t04XT0z_l6ROZwA.png" /><figcaption>Picture from <a href="https://neo4j.com">https://neo4j.com</a></figcaption></figure><p>NoSQL базы подходят по-другому к вопросу как хранить данные, и по названию ясно что данные хранятся не в таблице.</p><p>Есть следующие семейства которые по-разному хранят данные:</p><ul><li>Key-value хранилища (ключ-значения)</li><li>Документноориентированные БД</li><li>Графовые базы данных</li></ul><p><strong>Key-value хранилища</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/225/1*idPy9hE7fu9HbwyHVvOKTQ.png" /><figcaption>Redis logo</figcaption></figure><p>Про них можно сказать что данные хранятся в одном глобальном JSON’е в которых вы записываете данные по ключу и по этому же ключу читаете информацию.</p><p>Преимущество такой реализации — это скорость работы т.к. O-большое по поиску в хеше — это 1. Она очень быстро находит данные и записывает их. Плюс она наименее требовательная к ресурсам. Из-за этого она хорошо подходят под небольшие проекты.</p><p>Самая популярная база данных данного семейста — <a href="https://redis.io">Redis</a></p><p><strong>Документноориентированные БД</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/413/1*ckftQ5i7mMRM7Ng5AbGBvQ.png" /><figcaption>MongoDB logo</figcaption></figure><p>Если базы данных предыдущего семейства хранили данные в одном глобальном JSON’е, тот тут у нас есть массив в который мы может складывать JSON-объекты. Такие массивы тут называются коллекциями.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*EVhwTrhBH52w5kwsHlVjNg.png" /><figcaption>Picture from <a href="https://docs.mongodb.com">https://docs.mongodb.com</a></figcaption></figure><p>Вы сохраняете в коллекцию JSON’ы с произвольными наборами данных и достаете данные из этой коллекции. JSON — это очень гибкая структура данных которая может быть сколько угодно вложенная по глубине. Плюс, не проблема добавить или удалить ключик из объекта в любой момент времени</p><p>Преимущества данного подхода — гибкость. У нас нет строгой схемы данных, как например в таблице, поэтому вы можете хранить в одной коллекции объекты с разнообразными ключами.</p><p>Дополнительно на уровне БД у вас есть простой, но мощный функционал подсчета статистики по вашим данных — достаточно пройтись по массиву с помощью `map/filter/reduce`</p><p>Самая популярная база данных данного семейста — <a href="https://www.mongodb.com">MongoDB</a></p><p><strong>Графовые базы данных</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/834/1*4Ehd-BjJ57YJ2vRcks3eJg.png" /><figcaption>Neo4j logo</figcaption></figure><p>Как видно по названию, такие БД хранят графы. Но что же такое граф? — это очень математическая структура данных, и её лучше разбирать на примере.</p><p>Любая соц-сеть где куча людей подписываются друг на друга, добавляют друг друга в друзья и также могут являться друг другу родственниками — идеальный пример графа. Любая карта — это тоже граф. И задача нахождения самого короткого пути из точки A в точку B — это типичная задача из теории графов.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*2Sb9q-0apvYrilkLtY7QGA.png" /><figcaption>Picture from <a href="https://www.freecodecamp.org">https://www.freecodecamp.org</a></figcaption></figure><p>Как уже понятно, такие БД идеальны для написания социальной сети где между объектами большое кол-во связей.</p><p>Структура хранения данных — следующая. Представьте что теперь у нас есть целых два массива в который мы складываем наши JSON’ы. Но в один мы складываем только данные с информацией обо всех объектов нашей системы (так называемые ноды), а во второй информацию о связей между объектами.</p><p>Для понимания тут хорошо подойдет пример: мы пишем сервис с информацией о фильмах, как Кинописк. У нас будут данные о фильмах и о том какие люди занимались его созданием.</p><ul><li>В первый массив мы сохраняем данные обо всех объектов т.е. про фильмы и людей что принимали участие (режиссеров, актеров, операторов и прочее)</li><li>Во второй массив мы сохраняем связи — информацию кто был режиссером какого фильма, кто был актером, а кто оператором</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jzO9XEh_Y4sY5Oaz-iYDgA.png" /><figcaption>Пример хранения информации о сущностях</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6AZu0WH0rgRVdMFk-dUZBg.png" /><figcaption>Пример хранения информации о связях</figcaption></figure><p>Такая структура удобная тем что мы в одном запросе к БД достаем сразу все объекты которые нам интересны и связи: например при запросе, дай мне всех людей с кем работал этот режиссер.</p><p>Кроме соц-сетей, графовые БД хороши для реализацией систем рекомендаций т.к. нам удобно обходить графы и находить самые короткие маршруты между нодами. Самая популярная база данных данного семейства — <a href="https://neo4j.com">Neo4J</a></p><h3>Практические советы</h3><p>А теперь к практике</p><p><strong>Кейс</strong>: Мы пишем маленькое приложении чтобы выводить какую то одну информацию пользователям (курсы валют, погода в их родном городе и прочее)<br><strong>Что взять</strong>: key-value БД(redis)<br><strong>Почему</strong>: В данном кейсе достаточно использовать примитивные структуры данных. Положили строки/числа в массив и сохранил массив в БД по ключу — удобно</p><p><strong>Кейс</strong>: Маленькое приложение чтобы трекать информацию (кол-во пройденных шагов, кол-во выпитых стаканов воды или что-то другое)<br><strong>Что взять</strong>: key-value БД (redis)<br><strong>Почему</strong>: смотри выше</p><p><strong>Кейс</strong>: Наше приложение будет собирать данные из разнообразных источников, делает агрегацию по ним чтобы показать пользователям красивые дашборды, графики и прочее<br><strong>Что взять</strong>: Документноориентированные БД (mongoDB)<br><strong>Почему</strong>: Идеальна чтобы хранить в одной коллекции разнообразные данные. Так как данные хранятся не в таблице, хеши могут содержать разные ключи. Дополнительно поддержка функционала `map/filter/reduce` позволяет делать агрегации на уровне БД, а не приложения.</p><p><strong>Кейс</strong>: Мы до конца не понимаем что мы хотим реализовывать, очень смутная цель, но мы уверены что за одну неделю напишем прототип и потом скорее всего все переделаем. Нам нужна гибкость для изменений структуры данных<br><strong>Что взять</strong>: Документноориентированные БД (mongoDB)<br><strong>Почему</strong>: Так как у нас нет строгой схемы данных, мы может легко менять информацию о наших объектов (добавлять и удалять ключи из JSON’а). Благодаря этой гибкости наши мы можем свободно и быстро менять данные.</p><p><strong>Кейс</strong>: Мы пишем масштабное приложении где у каждого элемента, будет огромное кол-во связей. Функционал очень похож на типичную соц-сеть<br><strong>Что взять</strong>: графовые базы данных (neo4j)<br><strong>Почему</strong>: В графовых БД очень легко манипулировать связями между объектами в нашей БД</p><p><strong>Кейс</strong>: Мы пишем систему рекомендации. Нам нужно записывать максимальное кол-во связей между и находить связи между ними<br><strong>Что взять</strong>: графовые базы данных (neo4j)<br><strong>Почему</strong>: Идеальная БД чтобы строить графы и находить короткие маршруты между ними</p><p><strong>Кейс</strong>: Мы идеально представляем как записать наши данные в табличку в экселе. Или же мы хотите углубится в теорию и методологию реализаций баз данных<br><strong>Что взять</strong>: Любую реализацию SQL<br><strong>Почему</strong>: К вашим услугам огромное кол-во проработанной методологии, учебников и статей.</p><h3>Заключение</h3><p>Вот и все, надеюсь что этой статьей я ответил на вопрос и она оказалась полезной.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=264a265db188" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Git rebase: распространенные случаи при работе с git]]></title>
            <link>https://kopilov-vlad.medium.com/git-rebase-%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%BD%D1%8B%D0%B5-%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B8-%D0%BF%D1%80%D0%B8-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B5-%D1%81-git-f5f9d3bc8047?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/f5f9d3bc8047</guid>
            <category><![CDATA[программирование]]></category>
            <category><![CDATA[разработка]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Wed, 09 Dec 2020 12:15:20 GMT</pubDate>
            <atom:updated>2023-01-08T17:01:41.892Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_f7ZaRB2AFz7K89nZbxNFQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@rosssneddon?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ross Sneddon</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Каждый разработчик работает с git, но к сожалению не все используют rebase в своей работе. Мало кто знает в каких рабочих кейсах он может пригодится, поэтому я написал данную статью с разборами рабочих ситуаций.</p><p><strong>Предупреждение</strong>: Все примеры представленные здесь про изменение над одним файлом. Это удобно чтобы показать процесс работы, но увеличивает вероятность что при rebase возникнут конфликты. Поэтому разбор конфликтов в статье не будет.</p><p>Не удивляйтесь что после rebase придется пушить код в репозиторий через параметр “-f”. Это нужно чтобы принудительно переписать изменения в репозитории</p><pre>git push origin head -f</pre><p>Но есть более безопасный способ запушить код — использовать ключ <a href="https://stackoverflow.com/questions/8939977/git-push-rejected-after-feature-branch-rebase">force-with-lease</a></p><pre>git push origin head --force-with-lease</pre><h3>Кейсы</h3><ol><li>Поправить коммит в середине (fixup + rebase)</li><li>Удалить коммит в середине (rebase + drop)</li><li>Объединить коммиты и поменять текст итогового коммита (rebase/soft reset)</li><li>Поправить последний коммит (soft reset)</li><li>Поправить текст последнего коммита (amend)</li><li>Поменять коммиты местами (rebase)</li><li>Отребейзить ветку если родительская ветка была смерджена</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*H2qke5n2ZZ5MnNbW2CVeiA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@wonderlane?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Wonderlane</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>1) Задача: поправить коммит в середине</h3><p><strong>Решение</strong>: сделать fixup</p><p>У нас есть 4 коммита в которых мы правили один файл</p><pre>$ git log --oneline master..HEAD</pre><pre>aa871c7 (HEAD -&gt; example_1, base_branch) add third paragraph to readme<br>3774350 add second paragraph to readme<br>2143008 add first paragraph to readme<br>1da47ab add title to readme</pre><pre><br>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..315b9d6 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## Hello<br>+<br>+First paragraph<br>+<br>+Second paragraph<br>+<br>+Third paragraph</pre><p>Нам нужно поправить коммит который добавляет первый параграф (<em>2143008</em>). Открываем файл README.md и правим текст первого параграфа.</p><pre>$ git diff</pre><pre>diff — git a/README.md b/README.md<br>index 315b9d6..14dc0b7 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -1,7 +1,3 @@<br> ## Hello</pre><pre>-First paragraph<br>-<br>-Second paragraph<br>-<br>-Third paragraph<br>+First paragraph :)</pre><p>Так как мы в примере меняем один файл, то нужно сделать так каким он должен выглядеть после коммита (<em>2143008</em>) т.е там должен быть только заголовок и первый параграф.</p><p>Делаем “fixup коммит” задача которого поправить другой коммит в истории. Синтаксис операции следующий “<em>git commit — fixup &lt;commit_id&gt;</em>”</p><pre>$ git add README.md<br>$ git commit — fixup 2143008</pre><pre>[example_1 4d0edd6] fixup! add first paragraph to readme<br> 1 file changed, 1 insertion(+), 5 deletions(-)</pre><p>Готово, у нас есть новый коммит, но надо еще приложить усилия чтобы он применился к коммиту (<em>2143008</em>).</p><pre>$ git log --oneline master..HEAD</pre><pre>4d0edd6 (HEAD -&gt; example_1) fixup! add first paragraph to readme<br>aa871c7 (base_branch) add third paragraph to readme<br>3774350 add second paragraph to readme<br>2143008 add first paragraph to readme<br>1da47ab add title to readme</pre><p>Для этого нужно сделать rebase к коммиту на 1 ниже того который мы хотим поправить (<em>1da47ab</em>) (возможно здесь придется в явном виде решить конфликты, если git не понял как связать hotfix).</p><pre>$ EDITOR=vim git rebase -i --autosquash 1da47ab</pre><pre># во время выполнения вы увидите что коммит fixup встал на свое “правильное” место, а не в конце истории</pre><pre>1 pick 2143008 add first paragraph to readme<br>2 fixup 4d0edd6 fixup! add first paragraph to readme<br>3 pick 3774350 add second paragraph to readme<br>4 pick aa871c7 add third paragraph to readme</pre><pre>Successfully rebased and updated refs/heads/example_1.</pre><p>Посмотрим теперь на историю.</p><pre>$ git log --oneline master..HEAD</pre><pre>8b8e8b2 (HEAD -&gt; example_1) add third paragraph to readme<br>9dc3b2f add second paragraph to readme<br>557541f add first paragraph to readme<br>1da47ab add title to readme</pre><p>И на изменения.</p><pre>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..ff9fc5e 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## Hello<br>+<br>+First paragraph :)<br>+<br>+Second paragraph<br>+<br>+Third paragraph</pre><p>Ура, у нас получилось!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*Luex6RvtuOxYFNJF-ZlQyA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@xavi_cabrera?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Xavi Cabrera</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>2) Задача: удалить коммит в середине</h3><p><strong>Решение</strong>: сделать drop</p><p>У нас есть те же самые 4 коммита где мы правили один файл</p><pre>$ git log --oneline master..HEAD</pre><pre>aa871c7 (HEAD -&gt; example_2, base_branch) add third paragraph to readme<br>3774350 add second paragraph to readme<br>2143008 add first paragraph to readme<br>1da47ab add title to readme</pre><pre><br>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..315b9d6 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## Hello<br>+<br>+First paragraph<br>+<br>+Second paragraph<br>+<br>+Third paragraph</pre><p>Мы поняли что первый параграф нам не нужен. Удалять изменения новым коммитом не хочется т.к. мы может просто удалить старый. Для этого делаем rebase к интересующему коммиту (<em>1da47ab</em>).</p><pre>$ EDITOR=vim git rebase -i 1da47ab</pre><p>И прописываем drop к тому коммиту, который мы хотим удалить.</p><pre>1 drop 2143008 add first paragraph to readme<br>2 pick 3774350 add second paragraph to readme<br>3 pick aa871c7 add third paragraph to readme</pre><p>Посмотрим что у нас получилось.</p><pre>$ git log --oneline master..HEAD</pre><pre>2b87851 (HEAD -&gt; example_2) add third paragraph to readme<br>db792c4 add second paragraph to readme<br>1da47ab add title to readme</pre><pre><br>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..3354aa2 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,5 @@<br>+## Hello<br>+<br>+Second paragraph<br>+<br>+Third paragraph</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*9LnS3WX-wHv3zZEiloztTw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@biancablah?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Bianca Ackermann</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>3) Задача: объединить коммиты и поменять текст итогового коммита</h3><p><strong>Решение</strong>: сделать rebase</p><p>У нас есть один README.md файл и несколько «<em>wip</em>» коммитов.</p><pre>$ git log --oneline master..HEAD</pre><pre>33e58db (HEAD -&gt; example_3) wip<br>585c26b wip<br>173ab1f wip<br>c1f8895 wip<br>85855c0 wip<br></pre><pre>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..6222dc3 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## h2 header<br>+<br>+Some text. Bla-bla-bla<br>+<br>+### h3 header<br>+<br>+Some text again. LOL</pre><p>Наша задача объединить это коммиты в один с осмысленным текстом. Для этого надо сделать rebase на 5 коммитов назад.</p><pre>$ git log --oneline master..HEAD | wc -l<br>5</pre><pre>$ EDITOR=vim git rebase -i HEAD~5</pre><p>И поменять pick на squash</p><pre>1 pick 85855c0 wip<br>2 squash c1f8895 wip<br>3 squash 173ab1f wip<br>4 squash 585c26b wip<br>5 squash 33e58db wip</pre><p>После этого вручную поменять сообщение первого коммита.</p><pre>1 # This is a combination of 5 commits.<br>2 # This is the 1st commit message:<br>3<br>4 Create README.md file<br>5<br>6 # This is the commit message #2:<br>7<br>8 wip<br>9<br>10 # This is the commit message #3:<br>11<br>12 wip<br>13<br>14 # This is the commit message #4:<br>15<br>16 wip<br>17<br>18 # This is the commit message #5:<br>19<br>20 wip</pre><p>Вроде получилось</p><pre>[detached HEAD 30310eb] Create README.md file<br> Date: Sun Dec 6 22:00:41 2020 +0300<br> 1 file changed, 7 insertions(+)<br>Successfully rebased and updated refs/heads/example_3.</pre><p>Посмотрим что у нас есть в итоге.</p><pre>$ git log --oneline master..HEAD</pre><pre>30310eb (HEAD -&gt; example_3) Create README.md file<br></pre><pre>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..6222dc3 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## h2 header<br>+<br>+Some text. Bla-bla-bla<br>+<br>+### h3 header<br>+<br>+Some text again. LOL</pre><p>Ура, данные объединились в один коммит.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*ODQhXLt_nr-N_imbUQ2YwA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@fabiankuehne?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Fabian Kühne</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><strong>Решение 2</strong>: сделать soft reset</p><p>Делаем soft reset на 5 коммитов назад</p><pre>$ git log --oneline master..HEAD | wc -l<br>5</pre><pre>$ git reset --soft HEAD~5</pre><p>И сохранить изменения в один новый коммит.</p><pre>$ git ci -m “Add README.md file”</pre><pre>[example_3.2 22513de] Add README.md file<br> 1 file changed, 7 insertions(+)</pre><p>Посмотрим что получилось.</p><pre>$ git log --oneline master..HEAD</pre><pre>22513de (HEAD -&gt; example_3.2) Add README.md file</pre><pre><br>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..6222dc3 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+## h2 header<br>+<br>+Some text. Bla-bla-bla<br>+<br>+### h3 header<br>+<br>+Some text again. LOL</pre><p>Все получилось!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*1__Xrcfm2hrsp1AgfKdD8A.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@delaneyvan?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Delaney Van</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>4) Задача: поправить последний коммит</h3><p><strong>Решение</strong>: сделать soft reset</p><p>Итак, у нас есть два коммита. По каким-то причинам нам надо поправить последний коммит.</p><pre>$ git log --oneline master..HEAD</pre><pre>4efcc59 (HEAD -&gt; example_3.2) Add more text to README.md<br>22513de Add README.md file</pre><p>Можно сделать fixup, но он требует несколько действий. Гораздо быстрее сделать по-другому - убираем последний коммит, но оставляем все текущие изменения</p><pre>$ git reset --soft HEAD~1</pre><p>В итоге у нас в истории остался только предыдущий коммит.</p><pre>$ git log --oneline master..HEAD</pre><pre>22513de (HEAD -&gt; example_3.2) Add README.md file</pre><p>Но все последние изменения остались на файловой системе</p><pre>$ git st</pre><pre>On branch example_3.2<br>Changes to be committed:<br> (use “git reset HEAD &lt;file&gt;…” to unstage)</pre><pre>modified: README.md</pre><p>Теперь мы можем поменять данные в файле которые нам надо и создать новый коммит.</p><pre>$ git ci -a -m “Add more text to README.md”</pre><pre>[example_3.2 87eaff0] Add more text to README.md<br> 1 file changed, 2 insertions(+)</pre><p>Вуаля, все получилось</p><pre>$ git log --oneline master..HEAD</pre><pre>87eaff0 (HEAD -&gt; example_3.2) Add more text to README.md<br>22513de Add README.md file</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*d_sQ6KQXAxE7D-w618rkNA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@lydia_tallent21?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Lydia Tallent</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>5) Задача: поправить текст последнего коммита</h3><p><strong>Решение</strong>: сделать amend</p><p>Иногда в тексте коммита можно допустить ошибку и его надо переписать. Самый простой способ это сделать amend.</p><pre>$ git log --oneline master..HEAD</pre><pre>fb77ed2 (HEAD -&gt; example_3.2) improve documentattion<br>87eaff0 Add more text to README.md<br>22513de Add README.md file</pre><p>В последнем коммите опечатка в слове “documentation”. Поправим его</p><pre>$ git commit --amend -m “improve documentation”</pre><pre>[example_3.2 ed02c8a] improve documentation<br> Date: Sun Dec 6 22:57:22 2020 +0300<br> 1 file changed, 2 insertions(+)</pre><pre><br>git log --oneline master..HEAD</pre><pre>ed02c8a (HEAD -&gt; example_3.2) improve documentation<br>87eaff0 Add more text to README.md<br>22513de Add README.md file</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*v8LPyRsvCFv3g6OomRzpgw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@alimor?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Mor THIAM</a> on <a href="https://unsplash.com/s/photos/puzzle?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>6) Задача: поменять коммиты местами</h3><p><strong>Решение</strong>: сделать rebase</p><p>Итак, у нас опять есть три коммита</p><pre>$ git log --oneline master..HEAD</pre><pre>98bfce0 (HEAD -&gt; example_6) add footer to Readme.md<br>9fd509c add header to Readme.md<br>589ad4d add text to Readme.md</pre><p>В которых мы меняли один файл.</p><pre>$ git diff master..HEAD</pre><pre>diff --git a/README.md b/README.md<br>index e69de29..2c6d4f9 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+# Header<br>+<br>+Text. Bla-bla-bla.<br>+Some text.<br>+And text, again.<br>+<br>+# Footer</pre><p>Как поменять местами коммиты чтобы сперва в истории было добавление футера (98bfce0), а потом уже хедера (9fd509c)? Для этого делаем интерактивный rebase на 3 коммита назад</p><pre>$ EDITOR=vim git rebase -i HEAD~3</pre><pre>1 pick 589ad4d add text to Readme.md<br>2 pick 9fd509c add header to Readme.md<br>3 pick 98bfce0 add footer to Readme.md</pre><p>И меняем расположение коммитов</p><pre>1 pick 589ad4d add text to Readme.md<br>2 pick 98bfce0 add footer to Readme.md<br>3 pick 9fd509c add header to Readme.md</pre><p>Посмотрим что получилось.</p><pre>$ git diff master..HEAD</pre><pre>diff — git a/README.md b/README.md<br>index e69de29..2c6d4f9 100644<br> — — a/README.md<br>+++ b/README.md<br>@@ -0,0 +1,7 @@<br>+# Header<br>+<br>+Text. Bla-bla-bla.<br>+Some text.<br>+And text, again.<br>+<br>+# Footer</pre><pre><br>$ git log --oneline master..HEAD</pre><pre>a4e641f (HEAD -&gt; example_6) add header to Readme.md<br>cf87d0a add footer to Readme.md<br>589ad4d add text to Readme.md</pre><p>Давайте попробуем откатиться назад чтобы проверить что уберется хедер, а футер останется.</p><pre>$ git reset --hard HEAD~1</pre><pre>HEAD is now at cf87d0a add footer to Readme.md</pre><pre><br>$ cat README.md</pre><pre><br>Text. Bla-bla-bla.<br>Some text.<br>And text, again.</pre><pre># Footer</pre><p>И взглянем на историю коммитов.</p><pre>$ git log --oneline master..HEAD</pre><pre>cf87d0a (HEAD -&gt; example_6) add footer to Readme.md<br>589ad4d add text to Readme.md</pre><h3>7) Отребейзить ветку если родительская ветка была смерджена</h3><p>Бывает проблема когда делаешь ветку от ветки. Например родительская ветку уже смерджена в мастер, но коммиты были засквошены. Нужно отребейзить подветку от мастера, но не хочется решать много конфликтов.</p><p><strong>Решение</strong>: Сделать ребейз только нужных коммитов.</p><p>От мастера была создана ветка с 2-мя комитами</p><pre>O - A - B</pre><p>От этой ветки мы сделали ветку с добавили еще 3 коммита</p><pre>O - A - B - C - D - E</pre><p>Первая ветка была смерджена в мастер и вместо 2 коммитов `A — B`, в мастере появился один коммит `F`. Для того чтобы отребейзить нашу ветку от мастера надо отребейзить только уникальные коммиты этой ветки. То есть 3 коммита `C — D — E`. (<a href="https://stackoverflow.com/a/22593321">источник</a>)</p><pre>git rebase --onto master HEAD~3</pre><p>Вот и все! Надеюсь что данная статья была полезная 😁</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f5f9d3bc8047" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Откуда такой зоопарк баз данных или введение в разнообразие БД]]></title>
            <link>https://kopilov-vlad.medium.com/%D0%BE%D1%82%D0%BA%D1%83%D0%B4%D0%B0-%D1%82%D0%B0%D0%BA%D0%BE%D0%B9-%D0%B7%D0%BE%D0%BE%D0%BF%D0%B0%D1%80%D0%BA-%D0%B1%D0%B0%D0%B7-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85-%D0%B8%D0%BB%D0%B8-%D0%B2%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B2-%D1%80%D0%B0%D0%B7%D0%BD%D0%BE%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%B8%D0%B5-%D0%B1%D0%B4-a99a0fc2371c?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/a99a0fc2371c</guid>
            <category><![CDATA[программирование]]></category>
            <category><![CDATA[базы-данных]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Mon, 16 Nov 2020 10:54:14 GMT</pubDate>
            <atom:updated>2021-06-02T19:00:27.627Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*do3G_OrFnK-hb1p_gk3wWQ.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@nxn?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nikolay Tchaouchev</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><h3>Введение</h3><p>Каждый разработчик задавал себе вопрос почему существует так много языков программирования или баз данных. Ответ скрывается в том что каждый инструмент хорошо подходит только для своей задачи, а в других условиях становится не эффективным. Найти информацию о разнообразии языков не составит труда. Насчет баз данных хочется выразить свое мнение. Почему появилось разделение БД на SQL и NoSQL и было ли что-то до создания SQL.</p><h3>Темные времена</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/490/1*eaexXF6U8gwsGVRelEZwuQ.png" /><figcaption>Аспид и заклинатель</figcaption></figure><p>История любой индустрии всегда начинается с темных времен или момента рождения. Применительно к БД мне нравится выражение “<em>темные века</em>”.</p><p>Изначально никаких стандартов для БД не было. У каждого компьютера или мейнфрейма была своя имплементация БД. Чаще всего программист не делал в явном виде запрос к данным, а программировал их сам, выделяя для этого память в переменных и сам писал циклы чтобы подгрузить данные или связи.</p><p>С 1970-х начался новый тренд, БД представляли собой таблицы в которых была сложена информация. Как в привычном нам Microsoft Excel.</p><h3>Ренессанс</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zhu7QHFoU6xnZB8bBSr8PQ.png" /><figcaption>Афинская школа, Рафаэль Санти</figcaption></figure><p>Смена эпох наступила в 1974 когда IBM впервые представил свою первую имплементацию SQL. SQL менял подход в декларативную сторону и подкупил всех тем что не нужно самому программировать запросы к данных. У программистов уже появился интуитивно понятный интерфейс как это делать. Операторы <em>SELECT</em> и <em>JOIN</em> произвели революцию в своей индустрии. Вот пример запросов на языке SQL.</p><pre>SELECT first_name, last_name FROM people;</pre><pre>SELECT people.last_name, people.first_name, people.profession_id FROM people INNER JOIN profession ON people.profession_id=profession.id WHERE profession.id = 123;</pre><p>В 80-х годах SQL стал настоящим стандартном ANSI и ISO под который можно было написать свою систему управления базами данных (СУБД), что запустило эпоху ренессанса в мире БД.</p><p>SQL удовлетворял все коммерческие запросы к сохранности и надежности данных: блокировки, транзакции, внешние ключи, проверки на NULL, хранимые процедуры и прочее. Плюс была проделана огромная работа в исследовании, проектировании и работы с реляционными БД, что сделало эту систему стандартом индустрии. Казалось что в базах данных ничего никуда меняться не будет.</p><p>Дополнительно надежность SQL была гарантирована <a href="https://en.wikipedia.org/wiki/Database_schema">схемой данных</a> то есть на данные можно в любой момент посмотреть сверху как на план, как на карту города и схема гарантировала что все данных соответствуют этому плану. Пример: если в схеме написано что в таблице <em>USERS</em> поле <em>FIRST_NAME</em> является строкой и не может содержать <em>NULL</em>, то вариант что у какой-то записи там ничего нет или содержится число попросту не возможен.</p><p><strong>Плюсы SQL</strong>:</p><ul><li>Накоплен большой опыт проектирования и использования реляционных баз данных</li><li>Надежность хранения данных</li><li>Разнообразные СУБД как имплементации стандарта</li></ul><p><strong>Минусы SQL</strong>:</p><ul><li>Плохо подходят для сложных поисков по тексту (морфологический/префиксный поиск)</li><li>Плохо подходит для реализации данных которые можно представить как граф</li></ul><h3>Эпоха модерна</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/818/1*x3WtyaijC_aywjX5Lge4Ng.jpeg" /><figcaption>Пикассо авиньонские девицы</figcaption></figure><p>После долгой эпохи ренессанса наступает эпоха модернизма в мире баз данных. Программное обеспечение с каждым годом усложнялось, приложения становились более сложные, требования к ним более извращенные и в 2000-х в SQL стали находить узкие места которые не удовлетворяли по эффективности использования. Плюс не все данные удобно комплектовать в виде таблицы. Эти запросы пытаются удовлетворить новые более легкие и малые NoSQL решения.</p><p>До сих пор отношение к NoSQL решениям различные: кто-то считает это все игрушками, а кто-то узкими эффективными инструментами. Рассмотрим для примера несколько БД и поймем в чем их преимущества и минусы: Redis, MongoDB, ElasticSearch и Neo4j.</p><p>Дополнительно перед использованием каждой новой NoSQL БД надо было учиться заново т.к. у каждой из них есть свой уникальный язык запросов. Но обычно ORM/ODM имеют похожие интерфейсы.</p><h3>Redis</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/698/1*Daqq5qWRvoDZDEWRpdj_gw.png" /></figure><p>Эту БД можно представить в виде большого ассоциативного массива (ключ/значение) или одного JSON объекта. Оно представляет собой структуру данных где какая-то схема не нужна, важна только скорость записи/чтения. Ассоциативный массив для этого идеально подходит так как сложность поиска по нему <a href="https://en.wikipedia.org/wiki/Hash_table">О(1)</a>.</p><p>В Redis хранят данные к которым критически важна скорость доступа, и их не жалко потерять. Пример: данные о сессии, кэш, результаты промежуточных вычислений, очереди задач. Запускать для этих целей инстанс PSQL было бы неэффективно, а отдельная маленькая БД — самое оно.</p><p>Еще одно применение это БД — это коммуникация между процессами или доставка уведомлений. В Redis очень хорошо сделан функционал <a href="https://thoughtbot.com/blog/redis-pub-sub-how-does-it-work">подписки на каналы</a>. Можно моментально уведомить всех что какое-то событие началось, что-то случилось и запустить необходимые операции.</p><p><strong>Плюсы:</strong></p><ul><li>Скорость доступа к данным</li></ul><p><strong>Минусы:</strong></p><ul><li>Минимальные требования к надежности данным. Обычно Redis держит все данные в ОЗУ не дублируя их на диск, но эту конфигурацию можно легко включить.</li></ul><h3>MongoDB</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1001/1*C7lDQi908nxWg1mRebeV0w.png" /></figure><p>Предыдущая БД была представлена как один ассоциативный массив, MongoDB можно представить как массив <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> объектов. Эта парадигма уходит от представления что данные хранятся в таблицах как в MS Excel. С уходом от этого оказалось что схема данных не нужна. Если в SQL схема данных гарантировала целостность, но перед изменением структуры БД приходилось править схему, то тут сами данные максимально гибкие.</p><p>MongoDB идеально подходить проектам в которых есть одна (ну максимум две) сущности от которой пляшет весь функционал. Визуально ее можно представить как один массив с кучей данных прямо в нем. Другие таблицы или массивы с данными не нужны так как JSON имеет возможность вложенных данных (по ключу объекта может находится другой JSON-объект).</p><p>Эта первая NoSQL БД которая максимально эффективно манипулировала JSON’ом и искала данные в них. Плюс это был максимально простой поиск по данных. Все находится в одном массиве и не надо делать JOIN’ы чтобы собирать данные по таблицам.</p><p>Гибкость MongoDB является плюсом для кучи проектов которые только что начинаются, где требования очень туманны и меняются каждую неделя. В таких условиях максимальная гибкость БД и отсутствие схемы является плюсом и дает +10 к скорости внедрения изменений.</p><p><strong>Плюсы</strong>:</p><ul><li>Максимальная гибкость</li><li>Идеально для обхода древовидных структур данных</li><li>Хорошие возможности по агрегации данных</li></ul><p><strong>Минусы</strong>:</p><ul><li>Нет гарантий целостности данных. Из-за этого изначально не было плюшек которые давно есть в SQL (транзакции, join’ов и прочего).</li></ul><h3>ElasticSearch</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*846qvSdx5IvTlx1IaREoOA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@everhooder?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">ål nik</a> on <a href="https://unsplash.com/s/photos/book-looking?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>Эта БД создавалась с одной целью, максимально быстро и эффективно делать поисковые запросы по тексту. Со временем требования к поиску в сервисах усложнялись. Простой поиск по тексту LIKE в SQL не удовлетворял. Пользователей хотели удивить морфологическим и префиксным поиском.</p><p>Что такое морфологический поиск? Это поиск по тексту без отвлечения на род и число в языке. Например поиск в котором при введении слова “красный” также ищутся вариации “красная”, “красное”, “красные”. Префиксный поиск — это так называемый поиск с ошибками в котором пользователь может случайно перепутать буквы, но результат будет валидным.</p><p>ElasticSearch всегда используют как дополнительную БД в которую дублируются текстовые (иногда не только) данные для поиска по ним.</p><p><strong>Плюсы</strong>:</p><ul><li>Лучшее решение для реализации морфологического или префиксного поиска</li></ul><p><strong>Минусы</strong>:</p><ul><li>Лучше не хранить в этой БД данные которые не связаны с поиском.</li></ul><h3>Neo4j</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*uPqai-GAQjPnjWnsdS-LmQ.png" /></figure><p>На мой взгляд одна из самых зрелых NoSQL решений потому что очень хорошо решала задачу с которой у SQL были проблемы. Если задачу по нестандартному поиску по тексту еще можно было как то решить в SQL (добавляя плагины и небольшие хаки), то с графами проблема серьезнее.</p><p>Представьте что вам нужно проектировать социальную сеть для студентов. Из функционала:</p><ul><li>пользователи пишут посты;</li><li>к посту они пишут комментарии;</li><li>ставят лайки/дизлайки;</li><li>плюс нужно сохранять факт просмотра статьи в ленте друзей и факт полного прочтения статьи;</li><li>пользователи подписываться друг на друга;</li><li>важно запомнить кто кому друг, кто кому преподаватель, а кто кому одногруппник.</li></ul><p>По функционалу ясно что между сущностями будет куча разнообразных связей. Это связи многие ко многим, которые в SQL реализуются через ассоциативную таблицу. Представьте что вам надо вывести для пользователя друзья его друзей или друзья его однокурсников. В SQL вы запутаетесь в ассоциативных таблицах смотря на монструозную схему, а в MongoDB вы <a href="https://habr.com/ru/post/231213/">сойдете с ума от вложенных данных и их обновления</a>.</p><p>Идеальным инструментом будет использование графовых баз данных. В Neo4j также как в MongoDB нет схемы поэтому атрибуты данных можно было добавлять/удалять одним движением. Еще дополнительный плюс — то что атрибуты можно создавать/редактировать и у связей.</p><p><strong>Плюсы</strong>:</p><ul><li>Все алгоритмы линейной алгебры и теории графов работают максимально эффективно.</li><li>Поиск данных по графам работает быстрее чем в других БД.</li></ul><p><strong>Минусы</strong>:</p><ul><li>Если структура даных не предоставляет собой граф, то гораздо эффективнее использовать другую БД и не учить новый язык запросов.</li></ul><h3>Заключение</h3><p>Закончилась небольшая антология по базам данных. Естественно я не описал весь список NoSQL решений, но описал самые популярные из них. Не смотря на разнообразие NoSQL решений, чаще всего они используются дополнительно как альтернатива узким местам в SQL.</p><p>Какой новый тренд будет в будущем и когда мы вступим в эпоху метамодернизма неизвестно. Какая парадигма появится после NoSQL мы не знаем, но надеюсь что увидим.</p><h3>Дополнительно: хайп</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F7QN79mbAN6aeEglACf5nw.png" /></figure><p>Упоминая NoSQL невозможно не упомянут в каком инфопотоке они развивались. В индустрию они пришли с хайпом и юношеским максимализмом. Самый громкий из них был MongoDB. Она настолько громко заявляла о своем подходе что только ленивый не хотел ее потрогать.</p><p>В итоге <a href="https://felixit.blog/2017/08/05/ne-ispolzuite-mongodb/">полигоном испытаний для новой технологии</a> стали продакшн сервера реальных контор и это время можно описать так:</p><blockquote>Это было быстро, модно, молодежно, а с эффективностью и надежностью мы думали что как нибудь потом решиться. В общем “как нибудь” да решилось.</blockquote><p>Сейчас эта ситуация породила особое легаси на уровне БД: типо мы в этом продукте до сих пор используем MongoDB потому что так исторически сложилось и проект выстрелил. Переписывать на PSQL очень долго и дорого, а нам надо фичи катить. Поэтому пожалуйста, MongoDB Inc, добавьте нам транзакции и join’ы как в SQL 😇 Факт добавления транзакции, джойнов и схем в MongoDB, как по мне , — показатель что <a href="https://felixit.blog/2018/03/03/tri-problemy-mongodb/">ее юзают на проектах где идеально подходит SQL</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a99a0fc2371c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to preload associations for STI-model]]></title>
            <link>https://kopilov-vlad.medium.com/how-to-preload-associations-for-sti-model-3f30d36f49e8?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/3f30d36f49e8</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[ruby]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Mon, 14 Sep 2020 18:56:31 GMT</pubDate>
            <atom:updated>2020-09-14T18:56:31.748Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rfDcrwope0_ZK4Kd7HoIXQ.jpeg" /></figure><p><a href="https://dev.to/kopylov_vlad/how-to-preload-associations-for-sti-model-422a">[original post]</a></p><p>Single table inheritance (STI) is useful pattern. It helps organise codebase and split logic into different classes. Many programmers use it and like the pattern, but it has one disadvantage: you can’t preload associations by standard preloadmethod. Now, I show you the way to handle it.</p><p>Imagine, you have an Instagram style application where users are able to upload information and create posts. There are different types of post:</p><ul><li>post with one image</li><li>multi images post</li><li>and post with video</li></ul><p>You codebase is based by STI pattern</p><pre># base class<br>class Post &lt; ApplicationRecord<br>end</pre><pre># standard post with one image<br>class ImagePost &lt; Post<br>  has_one :image, dependent: :destroy, foreign_key: :post_id<br>end</pre><pre># multi images post<br>class MultiImagePost &lt; Post<br>  has_many :images, dependent: :destroy, foreign_key: :post_id<br>end</pre><pre># post with video<br>class VideoPost &lt; Post<br>  has_one :video, dependent: :destroy, foreign_key: :post_id<br>end</pre><p>Also Image class has relation to Asset</p><pre>class Image &lt; ApplicationRecord<br>  belongs_to :post, foreign_key: :post_id<br>  has_one :asset<br>end</pre><pre>class Asset &lt; ApplicationRecord<br>  belongs_to :image<br>end</pre><p>You have different feeds for each post type, and your application works perfectly.</p><pre>ImagePost.preload(image: :asset).each do |item|<br>  render &#39;image_post&#39;, item: item<br>end</pre><pre># database queries:<br># ImagePost Load (0.8ms)  SELECT &quot;posts&quot;.* FROM &quot;posts&quot; WHERE &quot;posts&quot;.&quot;type&quot; = ?  [[&quot;type&quot;, &quot;ImagePost&quot;]]<br>#  Image Load (1.4ms)  SELECT &quot;images&quot;.* FROM &quot;images&quot; WHERE &quot;images&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 21], [&quot;post_id&quot;, 22]]<br>#  Asset Load (0.9ms)  SELECT &quot;assets&quot;.* FROM &quot;assets&quot; WHERE &quot;assets&quot;.&quot;image_id&quot; IN (?, ?)  [[&quot;image_id&quot;, 5], [&quot;image_id&quot;, 6]]</pre><pre>MultiImagePost.preload(images: :asset).each do |item|<br>  render &#39;multi_image_post&#39;, item: item<br>end</pre><pre># database queries:<br># MultiImagePost Load (0.7ms)  SELECT &quot;posts&quot;.* FROM &quot;posts&quot; WHERE &quot;posts&quot;.&quot;type&quot; = ?  [[&quot;type&quot;, &quot;MultiImagePost&quot;]]<br># Image Load (1.1ms)  SELECT &quot;images&quot;.* FROM &quot;images&quot; WHERE &quot;images&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 20], [&quot;post_id&quot;, 25]]<br># Asset Load (1.0ms)  SELECT &quot;assets&quot;.* FROM &quot;assets&quot; WHERE &quot;assets&quot;.&quot;image_id&quot; IN (?, ?, ?, ?)  [[&quot;image_id&quot;, 3], [&quot;image_id&quot;, 4], [&quot;image_id&quot;, 7], [&quot;image_id&quot;, 8]]</pre><pre>VideoPost.preload(:video).each do |item|<br>  render &#39;video_post&#39;, item: item<br>end</pre><pre># database queries:<br># VideoPost Load (0.9ms)  SELECT &quot;posts&quot;.* FROM &quot;posts&quot; WHERE &quot;posts&quot;.&quot;type&quot; = ?  [[&quot;type&quot;, &quot;VideoPost&quot;]]<br># Video Load (0.9ms)  SELECT &quot;videos&quot;.* FROM &quot;videos&quot; WHERE &quot;videos&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 23], [&quot;post_id&quot;, 24]]</pre><p>The other day, a customer asked you to render all types of post in one feed. But there is one problem: you can’t use standard preload</p><pre>ActiveRecord::AssociationNotFoundError (Association named &#39;image&#39; was not found on MultiImagePost; perhaps you misspelled it?)</pre><p>What should you do? You can write your custom preload logic for new feed using ActiveRecord::Associations::Preloader You should create new instance of the class and then use preloadmethod. It takes two parameters: <br> * collection of AR-items<br> * hash with relations that you want to preload.<br>The code doesn’t look like rails-magic and you have to describe all relations explicitly, but it works perfectly.</p><pre>posts = Post.all<br>preloader = ActiveRecord::Associations::Preloader.new<br>    preloader.preload(posts.select{ |i| i.type == &#39;ImagePost&#39; }, image: :asset)<br>preloader.preload(posts.select{ |i| i.type == &#39;MultiImagePost&#39; }, images: :asset)<br>preloader.preload(posts.select{ |i| i.type == &#39;VideoPost&#39; }, :video)</pre><pre>posts.each |item|<br>  render &#39;post&#39;, item: item<br>end</pre><p>Look into logs, Preloader sends one query for each association, and you there aren’t N+1 queries</p><pre># 1) take posts from DB<br>Post Load (0.4ms)  SELECT &quot;posts&quot;.* FROM &quot;posts&quot;<br># 2) load images for all ImagePosts<br>Image Load (1.5ms)  SELECT &quot;images&quot;.* FROM &quot;images&quot; WHERE &quot;images&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 21], [&quot;post_id&quot;, 22]]<br># 3) load assets for them<br>Asset Load (1.0ms)  SELECT &quot;assets&quot;.* FROM &quot;assets&quot; WHERE &quot;assets&quot;.&quot;image_id&quot; IN (?, ?)  [[&quot;image_id&quot;, 5], [&quot;image_id&quot;, 6]]<br># 4) load images for all MultiImagePost<br>Image Load (0.4ms)  SELECT &quot;images&quot;.* FROM &quot;images&quot; WHERE &quot;images&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 20], [&quot;post_id&quot;, 25]]<br># 4) load assets for them<br>Asset Load (0.2ms)  SELECT &quot;assets&quot;.* FROM &quot;assets&quot; WHERE &quot;assets&quot;.&quot;image_id&quot; IN (?, ?, ?, ?)  [[&quot;image_id&quot;, 3], [&quot;image_id&quot;, 4], [&quot;image_id&quot;, 7], [&quot;image_id&quot;, 8]]<br># 5) load videos for all VideoPosts<br>Video Load (0.4ms)  SELECT &quot;videos&quot;.* FROM &quot;videos&quot; WHERE &quot;videos&quot;.&quot;post_id&quot; IN (?, ?)  [[&quot;post_id&quot;, 23], [&quot;post_id&quot;, 24]]</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3f30d36f49e8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Почему jQuery сдал позиции в эпоху SPA?]]></title>
            <link>https://kopilov-vlad.medium.com/%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-jquery-%D1%81%D0%B4%D0%B0%D0%BB-%D0%BF%D0%BE%D0%B7%D0%B8%D1%86%D0%B8%D0%B8-%D0%B2-%D1%8D%D0%BF%D0%BE%D1%85%D1%83-spa-97fc7fb30c15?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/97fc7fb30c15</guid>
            <category><![CDATA[разработка]]></category>
            <category><![CDATA[программирование]]></category>
            <category><![CDATA[jquery]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Tue, 21 Apr 2020 10:03:47 GMT</pubDate>
            <atom:updated>2020-04-24T16:20:04.016Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/773/1*TTgAS2LA5vYz-5twJ5Uhew.png" /></figure><p><a href="https://medium.com/@kopilov.vlad/почему-jquery-это-легендарный-инструмент-231dbf9ebe0f">В моем предыдущем посте</a> я так нахваливал jQuery что у читателя мог возникнуть вопрос “Почему тогда большие приложения пишутся на react, vuejs и других инструментов?”</p><p>Да, jQuery сдал позиции другим библиотекам и на это есть две причины:</p><ul><li>Пришла эпоха SPA (single page application)</li><li>Победа декларативной парадигмы программирования</li></ul><h3>Почему пришла эпоха SPA ?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/550/1*3bomdP0U7rUEAw0d9yloNQ.png" /><figcaption>Типичное веб-приложение в 2020 году</figcaption></figure><p>Типичное веб-приложение, будь то CRM или очередная CMS — это сложная штука с огромным количеством кнопочек и UX элементов.<br>А если этим сервисом пользуется большое кол-во человек то продакшн сервера пыхтят и тратят много сил на отрисовку html.</p><p>И однажды появилась идея 💡:</p><ul><li>Почему бы не прекратить рендерить страницу каждый раз заново, а пусть лучше веб-клиент отправляет post-запрос на сервер, получает результат и меняет данные там где нужно 🤔</li><li>Пусть на сайте новостей при клике на новость не перерисовывается вся страница, а отправляется GET-запрос на сервер. Клиент получает заголовок, текст и заменяет данные 🤔</li><li>Пусть клиент всего один раз загружает весь html, css и js а дальше обменивается с сервером только необходимыми данными. 🤔</li></ul><p>Это же удобно! 😃</p><p>Были небольшие эксперименты но, они были не настолько удачными чтобы стать массовыми. Backbonejs показал что классический ООП-подход плохо ложиться на функционал в браузере клиента.</p><p>Работа браузера полностью асинхронная, данные должны летать туда-сюда, кнопочки нажимаются в разные моменты времени, каждую минуту тригерятся разнообразные события. Как не странно, но на это очень хорошо лег функциональный подход.</p><p>Первая хорошая реализация стала Angular/Ember.js 🤓. Но это был полноценный фреймворк. На нем с нуля надо было писать приложения и процесс обучения занимал много времени.</p><p>После этого стартовал react. 😎 Его киллер фича была в том что react — это библиотека и он продвигал функциональный подход. Его можно было просто встроить в проект в виде небольшого функционала (чатик, калькулятор или прочее).</p><p>SPA сперва был прекрасен только для приложений и админок. Но потихоньку пришел server site rendering (SSR) и при помощи SPA можно было спокойно пилить любой медиа-ресурс.</p><p>Позже маркетологи все это увидели и сказали: “<em>Да с помощью технологии SPA мы можем бесконечный скролл реализовать!!! И вставить кучу рекламы между статьями!</em>” 💵💵💵💵💵</p><h3>Победа декларативной парадигмы программирования</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/701/1*KIoNyRO6s_52W68Y-0usJw.png" /><figcaption>Именно так теперь работает веб на клиенте</figcaption></figure><p>Чем конкретно хороши эти инструменты для разработчика? Тем что не надо в явном виде ковыряться в DOM! Это реально очень удобный подход, объясню на примере vuejs:</p><ul><li>Сверстал компонент</li><li>Разметил куда должны попадать данные из store</li><li>Навесил события на кнопочки и переключатели (остальное за тебя сделал two-way data binding)</li><li>Описал сериализацию данных перед отправкой на бэк и описал как данные с бека попадают в store</li><li>Все! После этого все работает!</li></ul><p>Ты описываешь data-flow (и иногда немного допиливаешь его напильником). А то как в явном виде передаются данные за тебя делает библиотека. Это была победа декларативного подхода в программировании! 👏</p><p>Vuejs — показал каким может быть реально удобный cli, как просто поднять проект и что для SPA нужно всего три либы: vue, vuex, vue-router (ну и Axios иногда 😅 ).</p><p>Работая с vuejs невозможно подумать что работа с формами может быть сложной (привет, react). Все это облегчило написание больших приложений, но и снизило входной порог в профессию.</p><h3>Мир дальше углубился в разделение труда</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/326/1*LwGg_oac0T4nou8IbuDPdw.png" /></figure><p>Я, как backend разработчик, счастлив таким положением дел. Моя работа:</p><ul><li>Получил от клиента http-запрос</li><li>Взял данные из БД</li><li>Положил их в json и отправил назад</li></ul><p>Каждый в команде занимается своим делом. Фронты верстают, пишут js-код, вставляют данные в красивую верстку. Сейчас осталось мало мест где для правок дизайна проекта, фронту надо поднимать монолит искать где тут вьюхи чтобы их править. Backend программистам не надо ковырять html. Все разработчики занимаются своим любимым делом ❤️</p><h3>React плох, но он набрал критическую массу</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/590/1*5oTkxOQg-iicSlYNSoFTLQ.png" /><figcaption><a href="https://twitter.com/acdlite/status/1022306639498506240">Даже создатель react хочет уничтожить эти либы 👿</a></figcaption></figure><p>Когда один инструмент набирает критическую массу пользователей это может быть опасно. Потому что людям сложно слезть с того что привычно.</p><p>Это тоже самое как во время всеобщей пандемии и самоизоляции люди продолжают использовать zoom, в котором большие проблемы с безопасностью. Просто все к нему привыкли и проще написать коллеге “давай созвонимся в zoom?” и получить положительный ответ чем “давай созвонимся в skype”.</p><p>Так чем плох реакт? 🤔 А тем что эта библиотека до сих пор заставляет разработчиков плакать если на нем писать большие приложения 😭</p><ul><li>Плохая реализация tree-shaking. Хочется как можно быстрее отдать клиенту его бандл чтобы он был как можно быстрее счастлив, но нет (вы проверяли сколько весит ваш hello world на react?)</li><li>Работа с формами — это боль 🤦‍♀️</li><li>Сложность экосистемы и ее многословность. Берем стандартный react стек: react, redux, redux form, redux-saga и прочее. И я вспоминаю, как раньше шутили о джаве: “<em>Взял одно, другое, склеил первое, второе, третье, написал конфиг. В итоге ты поднял простенький hello world, но выглядит это как enterprise решение для малого бизнеса.</em>”</li><li>Один паттер проектирования — компоненты высшего порядка, который очень плохо заходит новичкам. Плюс при разработке оказывается что в погоне за этой архитектурой начинается куча проблем. Мы обнаруживаем что одни обертки высших порядков зависят от других; что их надо не забыть перечислять в правильном порядке; что писать типы для компонентов высшего порядка либо боль, либо сложно, либо неэффективно.</li><li>Нет одной каноничной жесткой архитектуры с необходимыми абстракциями из коробки. В компонентах очень легко смешать логику и представление в беспорядочную мешанину. Из-за этого большие приложения легко и непреднамеренно превращаются в месиво кода.</li><li>Где конфигурация для create-react-app? И почему это не может быть в react-cli из коробки? После vuejs это все выглядит очень дико.</li></ul><p>Хоть мне и очень нравиться подход в vuejs, но никто в здравом уме не будет переписывать работающий большой проект с react на vuejs или ember. Это неадекватно с точки зрения затраты сил и ресурсов.</p><h3>А что с jQuery?</h3><p>Он просто работал и не пытался играть в гонку с другими js-библиотеками. jQuery идеальная для того что бы найти нужные элементы в DOM. Да, это просто либа, и она не дает какой либо каркас приложения но в то время это было не нужно.</p><p>И тут эпоха SPA заявила: «В DOM мы руками больше не лезем! Это сложно, медленно и от этого на проекте куча багов!»</p><p>Поэтому jQuery так и остался либой для работы с DOM, так как никому не пришла в голову идея доработать его для SPA:</p><ul><li>Взять уже готовый handlebars.js для html-шаблонов</li><li>Написать с нуля store</li><li>Функционал для http-запросов уже есть из коробки (<a href="https://reactjs.org/docs/faq-ajax.html">даже в документации react написано что для http-запросов хорошо подходит jQuery</a>)</li><li>Написать роутер</li><li>Реализовать необходимый функционал для two-way data binding</li></ul><p>То есть инструмент похожий на vuejs мог появится раньше, но с нативной поддержкой http-запросов из коробки. А еще бы добавить к этому create_app как во vue cli и поддержку coffeescript из коробки 😍 Ваще красота) 🔥</p><p>Вот так этот старичок оказался преданным своему делу, но потерял позиции перед другими инструментами. Но не все так плохо, он все еще остался хорош для парсинга сайтов: удобный api для http-запросов и самый простой интерфейс для ковырянии в DOM’е 👨‍💻</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=97fc7fb30c15" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Почему jQuery — это легендарный инструмент?]]></title>
            <link>https://kopilov-vlad.medium.com/%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-jquery-%D1%8D%D1%82%D0%BE-%D0%BB%D0%B5%D0%B3%D0%B5%D0%BD%D0%B4%D0%B0%D1%80%D0%BD%D1%8B%D0%B9-%D0%B8%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82-231dbf9ebe0f?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/231dbf9ebe0f</guid>
            <category><![CDATA[jquery]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[разработка-сайтов]]></category>
            <category><![CDATA[программирование]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Sat, 18 Apr 2020 12:30:04 GMT</pubDate>
            <atom:updated>2021-01-04T07:49:35.646Z</atom:updated>
            <content:encoded><![CDATA[<h3>Почему jQuery — это легендарный инструмент</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Cjo0-QICm-NDVn_l-mFUWA.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@artnok?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Nicolas Picard</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p><em>(The Write Less, Do More)</em></p><p>Первый релиз jQuery был 26 августа 2006 (13 лет назад). Но почему мы все еще в 2020 обсуждаем эту библиотеку?</p><p>jQuery — это живая легенда веба и на это есть три причины:</p><ul><li>Удобство</li><li>Стабильность</li><li>Эпоха</li></ul><h4>У — удобство</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/770/1*xbdP1YDtUrZiaeMDFjM_TA.gif" /><figcaption>Data science на js зарождался именно с jQuery)</figcaption></figure><p>Библиотека подключалась одной строчкой с любого CDN</p><pre>&lt;script src=&quot;<a href="https://code.jquery.com/jquery-3.5.0.min.js">https://code.jquery.com/jquery-3.5.0.min.js</a>&quot;&gt;&lt;/script&gt;</pre><p>Для разработки достаточно было всего одной либы. В ней есть все необходимое для работы с DOM, анимацей и ajax-запросами. Плюс у нее всегда была очень подробная документация. Эта библиотека показала насколько удобной может быть работа с ajax-запросами и что работать с ними может каждый. (<em>для молодых: fetch появился в js только с </em><a href="https://developers.google.com/web/updates/2015/03/introduction-to-fetch"><em>Chrome 42</em></a>)</p><p>Она показала как крут <em>chaining</em> еще до изобретения промисов 😅. Вот такую красоту мог использовать любой и спокойно работать с элементами как с объектами.</p><pre>$(&quot;#p1&quot;)<br>  .css(&quot;color&quot;, &quot;red&quot;)<br>  .slideUp(2000)<br>  .slideDown(2000);</pre><pre>$( &quot;ul.first&quot; )<br>  .find( &quot;.foo&quot; )<br>    .css( &quot;background-color&quot;, &quot;red&quot; )<br>  .end()<br>  .find( &quot;.bar&quot; )<br>    .css( &quot;background-color&quot;, &quot;green&quot; );</pre><p>jQuery была настолько удобной что разработчики забывали ванильный js. Многим людям для того что бы переквалифицироваться из верстальщика в разработчика было достаточно за пару выходных изучить api jQuery. По этой причине в 2014 году появился сайт <a href="http://youmightnotneedjquery.com/">youmightnotneedjquery.com</a></p><p>Счастье разработчика не ограничивалось одним core-функционалом. Было и есть огромное количество плагинов для разнообразных операций (вплоть до математических 🤪).</p><h4>С — стабильность</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/475/1*TAUgAn5YdjPoxvvRbWIDIQ.png" /><figcaption>Все вопросы которые могли возникнуть уже давно решены 😎</figcaption></figure><p>Было время когда еще не было никаких менеджеров пакетов типо npm или yarn, но и не было проблем с установкой и управлением зависимостями. В гугле без труда можно было найти плагины на любую задачу. Каждый плагин был написан энтузиастом всего один раз и просто работал!</p><p>Люди находили плагины в гугле (привет, <a href="https://ruseller.com/">ruseller.com</a>) или на страницах stackoverflow и просто подключали его к себе на сайт. Крафтовость разработки — 80-й уровень 🧔😎<br>Не важно когда плагин был написан, он работал стабильно.<br><a href="https://github.com/petk/awesome-jquery">Все аккордеоны, тоглы, табы, простенькие модальные окна</a> работали без постоянных патчей и багфиксов.</p><p>Но даже если версия jQuery на сайте отличалась от версии которая нужна была для правильной работы плагина, то внутри некоторых плагинов был уже встроенный “no conflict mode”. Изнутри плагина запускалась нужная версия jQuery, а на сайте, в глобальном пространстве имен, разработчик спокойно использовал нужную ему версию jQuery.<br>Еще был надежный функционал <a href="https://api.jquery.com/jquery.noconflict/"><em>jQuery.noConflict()</em></a> который освобождал переменную <em>$</em> для других библиотек 😻.</p><p>Бывало я и сам для себя писал плагинчики для jQuery 😀</p><p>Либа до сих пор поддерживается на github! <a href="https://github.com/jquery/jquery/commits/master">https://github.com/jquery/jquery/commits/master</a> А сколько вы знаете фронтовых либ которые поддерживаются 13 лет к ряду?!</p><h4>Э — эпоха</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/394/1*xUD9d2GUOL-HJII8HxD5vw.png" /></figure><p>jQuery — это эпоха которая еще не прошла. Разработчики до сих пор любят и используют jQuery ❤️.</p><p>Bootstrap только в феврале 2019-го смог избавиться от jQuery в своем коде, но каких усилий и временных затрат им это стоило. <a href="https://github.com/twbs/bootstrap/pull/23586">https://github.com/twbs/bootstrap/pull/23586</a></p><p>В статистике npm по jQuery вы можете увидеть 3,504,030 weekly downloads, и это в 2К20! <a href="https://www.npmjs.com/package/jquery">https://www.npmjs.com/package/jquery</a></p><p>jQuery до сих пор часть таких известных библиотек как:<br><a href="https://www.npmjs.com/package/bootstrap-datepicker">https://www.npmjs.com/package/bootstrap-datepicker</a><br><a href="https://www.npmjs.com/package/owl.carousel">https://www.npmjs.com/package/owl.carousel</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jNFcFZzG6pAqJ2h-V4A0lA.png" /><figcaption>И на hh.ru всегда есть работа на jquery, даже в 2к20!</figcaption></figure><p>Даже используя jQuery сейчас не приходиться думать про поддержку старых браузеров. Подключаешь jQuery 1.12 и твой ламповый сайтик работает на всех старых браузеров.</p><p><strong>Резюмируя.</strong></p><p>Для многих олдов jQuery — это как первая машина! 🚙<br>Спустя десять лет человек может купить себе две BMW, но в душе он всегда помнит свою первую четырку которая просто работала и ни разу его не подводила 😊</p><p>До сих пор в 2020 году, если тебе нужно написать небольшое приложение, то бывает проще заюзать jQuery чем поднимать create-react-app</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=231dbf9ebe0f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Metaprogramming Ruby by Paolo Perrotta]]></title>
            <link>https://kopilov-vlad.medium.com/metaprogramming-ruby-by-paolo-perrotta-4d22d60bf78b?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/4d22d60bf78b</guid>
            <category><![CDATA[metaprogramming]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[ruby]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Sun, 22 Sep 2019 10:44:59 GMT</pubDate>
            <atom:updated>2019-09-22T13:19:56.379Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/417/1*o9PU-iQpg0-0-zAc9EBrkg.jpeg" /><figcaption>The image from amazon.com</figcaption></figure><p>Metaprogramming is writing code that manipulates language constructs at runtime. It is an essential component of Ruby, and you can use it to remove duplication in your code and write elegant, beautiful programs.</p><p>Metaprogramming is always interesting to me. I have had experience with it, but I still had questions about it. One of my colleagues recommended me to read the book. After that, I have found answers to all my questions. Therefore I highly recommend it everyone who wants to learn more about metaprogramming.</p><p>By reading the book, you will be able to learn new by one week. You will be able to understand new constructions, and you will see a lot of code examples (in plain Ruby and code in popular gems):</p><ul><li>how to create new methods in runtime with <em>method_missing</em> and <em>respond_to_missing</em></li><li>defining new methods in runtime with <em>define_method</em> construction</li><li>how to pass constant by <em>const_missing</em></li><li>new way to create classes dynamically</li><li>learn more about metaprogramming in ActiveRecords</li><li>monkey patching and how to add a method to a class dynamically</li><li>and you will reach the whole power of <em>DSL</em> (domain-specific language)</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d22d60bf78b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Speeding up xml view for RSS feed in Rails]]></title>
            <link>https://kopilov-vlad.medium.com/speeding-up-xml-view-for-rss-feed-in-rails-f70f65024626?source=rss-32b1b50518de------2</link>
            <guid isPermaLink="false">https://medium.com/p/f70f65024626</guid>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[xml]]></category>
            <category><![CDATA[rss]]></category>
            <dc:creator><![CDATA[Vladislav Kopylov]]></dc:creator>
            <pubDate>Sun, 04 Aug 2019 08:40:37 GMT</pubDate>
            <atom:updated>2019-08-04T10:18:52.019Z</atom:updated>
            <content:encoded><![CDATA[<p>Recently, I tried to make a RSS feed faster in my Rails application. I had a Rails application with standard xml.builder view wrote with <a href="https://github.com/jimweirich/builder">builder gem</a>.</p><p>Example:</p><pre>xml<strong>.</strong>instruct! :xml, :version =&gt; &quot;1.0&quot;<br>xml<strong>.</strong>rss :version =&gt; &quot;2.0&quot; do<br>  xml<strong>.</strong>channel do<br>    xml<strong>.</strong>title &quot;My Company Blog1&quot;<br>    xml<strong>.</strong>description &quot;This is a blog by My Company&quot;<br>    xml<strong>.</strong>link &#39;/&#39;<br>    @topics<strong>.</strong>each do |i|<br>      xml<strong>.</strong>item do<br>        xml<strong>.</strong>title i<strong>.</strong>title<br>        xml<strong>.</strong>subtitle i<strong>.</strong>subtitle<br>        xml<strong>.</strong>description i<strong>.</strong>description<br>        xml<strong>.</strong>big_text i<strong>.</strong>big_text<br>        xml<strong>.</strong>rubric_id i<strong>.</strong>rubric_id<br>        xml<strong>.</strong>tag_id i<strong>.</strong>tag_id<br>        xml<strong>.</strong>publication_at i<strong>.</strong>publication_at<br>        xml<strong>.</strong>one_more_time i<strong>.</strong>one_more_time<br>      end<br>    end<br>  end<br>end</pre><p>It is absolutely standard xml view for all RSS feeds in Rails. I began an experiment to rewrite it from xml.bulder to xml.erb and it made render faster. For my app, it made it twice as fast as before.</p><p>Example:</p><pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<br>&lt;rss version=&quot;2.0&quot;&gt;<br>  &lt;channel&gt;<br>  &lt;title&gt;&lt;%= &#39;My Company Blog1&#39; %&gt;&lt;/title&gt;<br>  &lt;description&gt;&lt;%= &#39;This is a blog by My Company&#39; %&gt;&lt;/description&gt;<br>  &lt;link&gt;&lt;%= &#39;/&#39; %&gt;&lt;/link&gt;<br>  &lt;% @topics<strong>.</strong>each do |i| %&gt;<br>    &lt;item&gt;<br>      &lt;title&gt;&lt;%= i<strong>.</strong>title %&gt;&lt;/title&gt;<br>      &lt;subtitle&gt;&lt;%= i<strong>.</strong>subtitle %&gt;&lt;/subtitle&gt;<br>      &lt;description&gt;&lt;%= i<strong>.</strong>description %&gt;&lt;/description&gt;<br>      &lt;big_text&gt;&lt;%= i<strong>.</strong>big_text %&gt;&lt;/big_text&gt;<br>      &lt;rubric_id&gt;&lt;%= i<strong>.</strong>rubric_id %&gt;&lt;/rubric_id&gt;<br>      &lt;tag_id&gt;&lt;%= i<strong>.</strong>tag_id %&gt;&lt;/tag_id&gt;<br>      &lt;publication_at&gt;&lt;%= i<strong>.</strong>publication_at %&gt;&lt;/publication_at&gt;<br>      &lt;one_more_time&gt;&lt;%= i<strong>.</strong>one_more_time %&gt;&lt;/one_more_time&gt;<br>    &lt;/item&gt;<br>  &lt;% end %&gt;<br>&lt;/channel&gt;<br>&lt;/rss&gt;</pre><p>Almost the same result we can reach to replace gem builder by <a href="https://github.com/ohler55/ox">ox</a> (the fastest optimized XML parser and generator). But, unfortunately, it has quirky syntax and we don’t have action_view’s template out the box.</p><p>In conclusion, there is an easy way to decrease rss response time. I prepared a test application in order to check it out and uploaded it to Github. There is the link to test application with the result — <a href="https://github.com/kopylovvlad/rails_rss_app">github</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f70f65024626" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>