<?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"><channel><title><![CDATA[Viacheslav Kharchenko]]></title><description><![CDATA[Ukrainian Tech Lead &amp; Rails dev.

Solving software engineering bottlenecks and daily routine friction — from smart homes to life-ops. Streamlining code and ]]></description><link>https://vchkhr.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 11:17:00 GMT</lastBuildDate><atom:link href="https://vchkhr.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Невидимий дизайн: Чому «хмара часток» в Apple Watch — це геніальний інженерний хід]]></title><description><![CDATA[Кожен розробник, який хоч раз налаштовував Apple Watch, відчував цей «wow-ефект». Замість стандартного QR-коду — таємнича анімація, яку iPhone зчитує за частку секунди. Як інженер, я не міг пройти повз і не розібратися: як це працює насправді?
Довгий...]]></description><link>https://vchkhr.com/nevidimij-dizajn-chomu-hmara-chastok-v-apple-watch-ce-genialnij-inzhenernij-hid</link><guid isPermaLink="true">https://vchkhr.com/nevidimij-dizajn-chomu-hmara-chastok-v-apple-watch-ce-genialnij-inzhenernij-hid</guid><category><![CDATA[ukrainian]]></category><category><![CDATA[engineering]]></category><category><![CDATA[UX]]></category><category><![CDATA[Apple]]></category><category><![CDATA[software development]]></category><category><![CDATA[Product Design]]></category><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Tue, 27 Jan 2026 14:23:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769524189844/05d0222a-4f8e-424f-bfad-db65a085bcce.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Кожен розробник, який хоч раз налаштовував Apple Watch, відчував цей «wow-ефект». Замість стандартного QR-коду — таємнича анімація, яку iPhone зчитує за частку секунди. Як інженер, я не міг пройти повз і не розібратися: як це працює насправді?</p>
<p>Довгий час вважалося, що вся ця «хмара» — це динамічно згенерований код. Але реальність куди цікавіша і, чесно кажучи, геніальніша у своїй простоті.</p>
<p><img src="https://cdsassets.apple.com/live/7WUAS350/images/apple-watch/watchos-11-series-9-iphone-15-pro-setup-managed-animation.png" alt="Smartphone screen displaying Apple Watch pairing instructions with &quot;Hold Apple Watch up to the Camera&quot; text, showing an Apple Watch centered in a viewfinder." class="image--center mx-auto" /></p>
<h3 id="heading-sekret-u-fajli-proximitypairingloopmov">Секрет у файлі <code>ProximityPairingLoop.mov</code></h3>
<p>Якщо «залізти під капот» iOS, а саме в директорію <code>/Applications/Setup.app/</code>, можна знайти файл під назвою <code>ProximityPairingLoop.mov</code>.</p>
<p>Виявляється, та сама заворожуюча «хмара часток» — це просто <strong>статичний відео-ассет</strong>. Сама по собі вона не несе ніякої технічної інформації для пейрингу. Справжній код — це шар «статичного шуму», який накладається поверх цього відео.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=Oc1qJW_p6jQ">https://www.youtube.com/watch?v=Oc1qJW_p6jQ</a></div>
<p> </p>
<p>Це класичний приклад того, як Apple розділяє естетику та функціональність:</p>
<ul>
<li><p><strong>Відео-петля</strong> створює візуальний контекст і емоцію «магії».</p>
</li>
<li><p><strong>Оверлей із шумом</strong> містить у собі дані, зашифровані за принципами, які Apple описувала у своїх патентах про невидимі оптичні мітки.</p>
</li>
</ul>
<h3 id="heading-yak-pracyuye-cej-nevidimij-kod">Як працює цей «невидимий» код?</h3>
<p>Навіть якщо хмара — це лише відео, сам шум зверху працює за дуже хитрими алгоритмами психовізуального сприйняття:</p>
<ol>
<li><p><strong>Тимчасове усереднення:</strong> Код мерехтить на частоті 60–120 Гц. Для нашого ока це виглядає як легкий шум або частина анімації, бо мозок «усереднює» картинку. Але камера iPhone бачить кожен кадр окремо і легко дешифрує матрицю даних.</p>
</li>
<li><p><strong>Хроматичні маніпуляції:</strong> Дані зашиті в коливаннях кольору (хроматичності), до яких людське око менш чутливе, ніж до яскравості. Це дозволяє приховати код навіть на рухомому фоні.</p>
</li>
</ol>
<h3 id="heading-chomu-cej-pidhid-urok-dlya-kozhnogo-inzhenera">Чому цей підхід — урок для кожного інженера?</h3>
<p>Працюючи з Ruby on Rails чи архітектурою складних систем, ми часто намагаємося зробити все «чесно» — щоб кожна піксельна зміна була результатом складних обчислень. Apple пішла іншим шляхом:</p>
<ul>
<li><p><strong>Економія ресурсів:</strong> Навіщо рендерити складну математичну модель часток у реальному часі на слабкому процесорі годинника, якщо можна програти легке відео і накласти на нього тонкий шар даних?</p>
</li>
<li><p><strong>Invisible Design:</strong> Це ідеальний баланс між «красивим» та «корисним». Користувач не бачить технічного «сміття», а система отримує всі необхідні дані для з’єднання.</p>
</li>
</ul>
<h3 id="heading-mij-visnovok">Мій висновок</h3>
<p>Цей кейс навчив мене, що найкраще інженерне рішення — це не обов'язково найскладніше. Це те, яке вирішує проблему користувача найелегантнішим способом. Іноді для «магії» достатньо простої відео-петлі та правильно накладеного шуму.</p>
<p>В моїй практиці, будь то розробка високонавантажених сервісів чи налаштування Home Assistant, я все частіше намагаюся знайти такі «точки спрощення». Бо кінцевому користувачу байдуже на складність вашого алгоритму — йому важливо відчути магію, яка просто працює.</p>
]]></content:encoded></item><item><title><![CDATA[Завантаження власних шрифтів на електронну книгу PocketBook з Mac]]></title><description><![CDATA[Photo by Ruta Gudeliene on Unsplash
Щоб завантажити власні шрифти на електронну книгу PocketBook з компʼютера Apple Mac чи ноутбука Apple MacBook, виконайте наступні дії:

Підʼєднайте книгу до компʼютера. Для сучасних моделей вам знадобиться кабель U...]]></description><link>https://vchkhr.com/pocketbook-fonts-instruction-uk</link><guid isPermaLink="true">https://vchkhr.com/pocketbook-fonts-instruction-uk</guid><category><![CDATA[ukrainian]]></category><category><![CDATA[guide]]></category><category><![CDATA[PocketBook]]></category><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Wed, 29 Jan 2025 18:57:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077386097/a7750df5-18c6-4774-a906-6802c75eae16.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@rutaurban?utm_source=medium&amp;utm_medium=referral">Ruta Gudeliene</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>Щоб завантажити власні шрифти на електронну книгу PocketBook з компʼютера Apple Mac чи ноутбука Apple MacBook, виконайте наступні дії:</p>
<ol>
<li><p>Підʼєднайте книгу до компʼютера.<br /> Для сучасних моделей вам знадобиться кабель USB Type-C — USB Type-C. Упевніться, що кабель підтримує передачу даних.<br /> Якщо при підключенні електронної книги нічого не відбувається і вона не заряджається, спробуйте підключити кабель іншою стороною або в інший порт на MacBook. Якщо ви спробували всі варіанти, змініть кабель.</p>
</li>
<li><p>На PocketBook зʼявиться повідомлення: “Оберіть режим USB” та дві кнопки: “Звʼязок з ПК” та “Зарядка”. Натисніть на “Звʼязок з ПК”.<br /> Якщо при підключенні відбувається лише зарядка та вікно на PocketBook не зʼявляється, відкрийте “Параметри”, “Обслуговування”, у “Режим USB” оберіть “Запитати при підключенні”.</p>
</li>
<li><p>На Mac зʼявиться таке вікно:</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077376958/a49725df-508f-493a-9a3c-84a2ff5f3dff.png" alt /></p>
<p>Натисніть кнопку “Дозволити”.</p>
<p>3. На Mac відкрийте програму “Finder” та відкрийте новий зʼємний пристрій в меню зліва:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077378769/37a9bc99-f0c0-428d-bd0a-ad8f59de4733.png" alt /></p>
<p>4. Увімкніть перегляд прихованих папок. Для цього натисніть комбінацію “Command + Shift + .” (крапка). Ви маєте побачити приховану папку “System”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077380108/742d664d-4d1e-4b2a-901c-64874da956fc.png" alt /></p>
<p>5. У папці “System” відкрийте папку “fonts”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077381823/a77f9e25-0c1d-43e7-b300-ac373ae76e46.png" alt /></p>
<p>6. Перенесіть свої шрифти з розширенням “.ttf” у цю папку.<br />Краще не створювати підпапок та не видаляти стандартні шрифти, аби не зашкодити роботі системи:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077383220/7b331a28-acc0-46e2-8aeb-e3c3d683faa4.png" alt /></p>
<p>7. Після перенесення всіх файлів зі шрифтами, натисніть кнопку безпечного відʼєднання пристрою:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077384503/188a2ffe-94a3-43aa-af41-bafd156d73b2.png" alt /></p>
<p>8. Трохи зачекайте, на PocketBook зʼявться іконка завантаження.</p>
<p>9. Після завершення завантаження, відкрийте будь-яку електронну книгу на PocketBook.</p>
<p>10. Знову зачекайте закінчення завантаження. Натисніть “Параметри”, “Шрифт” та оберіть новий шрифт.</p>
<p>Чим більше шрифтів ви завантажите на PocketBook, тим довше буде завантажуватись їх список.</p>
]]></content:encoded></item><item><title><![CDATA[Як додати графік відключення світла у Календар?]]></title><description><![CDATA[Оновлення
Ця стаття втратила актуальність після закінчення відключення світла. Останнє відключення світла у Львові було 30 грудня 2024 р.
Ви можете легко додати графіки погодинних відключень світла у місті Львові в Google Календар на Android чи Apple...]]></description><link>https://vchkhr.com/d18fd0ba-d0b4d0bed0b4d0b0d182d0b8-d0b3d180d0b0d184d196d0ba-d0b2d196d0b4d0bad0bbd18ed187d0b5d0bdd0bdd18f-d181d0b2d196d182d0bbd0b0-d183-d0bad0b0d0bbd0b5d0bdd0b4d0b0d180-714e7cdcd22c</link><guid isPermaLink="true">https://vchkhr.com/d18fd0ba-d0b4d0bed0b4d0b0d182d0b8-d0b3d180d0b0d184d196d0ba-d0b2d196d0b4d0bad0bbd18ed187d0b5d0bdd0bdd18f-d181d0b2d196d182d0bbd0b0-d183-d0bad0b0d0bbd0b5d0bdd0b4d0b0d180-714e7cdcd22c</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Sat, 22 Jun 2024 12:55:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077372908/bb3aa1af-11ce-442e-bd17-e4f0c631a6bb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-onovlennya">Оновлення</h3>
<p>Ця стаття втратила актуальність після закінчення відключення світла. Останнє відключення світла у Львові було 30 грудня 2024 р.</p>
<p>Ви можете легко додати графіки погодинних відключень світла у місті Львові в Google Календар на Android чи Apple Календар на iPhone.</p>
<p>Графіки в календарях оновлено <strong>10 липня 2024 року</strong>.</p>
<p>Дізнайтесь групу відключень на сайті <a target="_blank" href="https://poweron.loe.lviv.ua/">Львівобленерго</a>.</p>
<p>Для того, аби додати графік відключень у календар на смартфоні чи компʼютері, натисніть на посилання необхідної групи, а потім підтвердьте додавання календаря:</p>
<ul>
<li>Група 1.1: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=MzFiYTI0ZjQwNDRhMzI0YzdhMDZlM2RjMDVmZmQyOWQ5YjhmZTA4YWFiYjM3NDNlMWY0MTIwMTBhYzQ4OTJkZEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
<li>Група 1.2: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=MTI5NzgwOWE2ZDIwZDFmODYzZmRmNTcwZjkzMTY5ZGNmMzEyZmVmOTk1Yzk5MjY2MTI2MzIzN2ZkMmZkYjNjYkBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
<li>Група 2.1: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=OWJiYzg5MWJkOTNmOTRmNjk4ZGNkM2I5ZjU3YWNiN2VmMThlNGJhY2Q4YTg4ZWEyMjQwOGFkMjhjMzEwMDgxNEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
<li>Група 2.2: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=ZjU0Yzk2MGE0OWYwNzcwMWNhYWE0ZTZlOTJhMDI3Y2NjMjZlZmViZDU0ODA4OTIyY2E0MGY3NjA4YWFkYTc3ZEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
<li>Група 3.1: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=M2YzZDFlODE1NjMxZjBkMWZlZTkwMWM4YzM3MmYzZmJmNmJlZWZkYjg3MWFhNzIwZGI4YzllMWVlMWQ5MDI2NkBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
<li>Група 3.2: <a target="_blank" href="https://calendar.google.com/calendar/u/0?cid=MTFlNGMxOTYxMmNlZTdjNzUwODhiYjA5MDYxZWU2YWJiZGRjYzg0MzMwODdkY2E0NTczNGMzNDg3NzdlZjQ5NUBncm91cC5jYWxlbmRhci5nb29nbGUuY29t">Google Календар</a></li>
</ul>
<h3 id="heading-yak-dodati-grafik-vidklyuchennya-svitla-na-pochatkovij-ekran">Як додати графік відключення світла на початковий екран?</h3>
<p>На iPhone помістіть віджет Календаря на початковий екран, потім затисніть його, оберіть “Редагувати віджет”, в полі “Календарі” оберіть календар із вашою групою.</p>
<p>Інструкція “<a target="_blank" href="https://support.apple.com/uk-ua/guide/iphone/iphd2fc8ce30/ios">Переміщення програм і віджетів на початковий екран на iPhone</a>” від Apple.</p>
<p>Віджет із графіком відключення світла на початковому екрані iPhone</p>
]]></content:encoded></item><item><title><![CDATA[Solution: .webp images are not loaded in Google Chrome from a CDN subdomain]]></title><description><![CDATA[Context
You have a web site with the domain example.org. Images are loaded through Cloudflare CDN with the subdomain cdn.example.org.
Broken image icons
Problem
.webp images not loaded in Google Chrome, Microsoft Edge, Arc, and other Chromium-based b...]]></description><link>https://vchkhr.com/solution-webp-images-are-not-loaded-in-google-chrome-from-a-cdn-subdomain-81378aa7eb69</link><guid isPermaLink="true">https://vchkhr.com/solution-webp-images-are-not-loaded-in-google-chrome-from-a-cdn-subdomain-81378aa7eb69</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Tue, 23 Jan 2024 10:39:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077391523/4b5c5551-3ff1-4169-8fdd-987955c2895b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-context">Context</h3>
<p>You have a web site with the domain <em>example.org</em>. Images are loaded through Cloudflare CDN with the subdomain <em>cdn.example.org</em>.</p>
<p>Broken image icons</p>
<h3 id="heading-problem">Problem</h3>
<p>.webp images not loaded in Google Chrome, Microsoft Edge, Arc, and other Chromium-based browsers.</p>
<h3 id="heading-solution">Solution</h3>
<ol>
<li>Go to Cloudflare Dashboard.</li>
<li>Select the “<em>Rules</em>” tab on the sidebar, “<em>Transform Rules</em>”.</li>
<li>Open the “<em>Modify Response Header</em>” tab and press “<em>+ Create rule</em>”.</li>
<li>Fill in the form:</li>
</ol>
<p>Rule name: <em>Content-Type: image/webp</em></p>
<p>If: <em>Custom filter expression  
</em>Field: <em>URI Path  
</em>Operator: <em>contains  
</em>Value: <em>.webp</em></p>
<p>Then: <em>Set static  
</em>Header name: <em>Content-Type  
</em>Value: <em>image/webp</em></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077390380/5ad854da-c7ba-4894-af28-9099145a1d79.jpeg" alt="Transfrom Rules" /></p>
<p>Transform Rules</p>
<p>5. Press the “<em>Deploy</em>” button.</p>
<h3 id="heading-result">Result</h3>
<p>Go to your website and .webp images should be displayed in Google Chrome.</p>
]]></content:encoded></item><item><title><![CDATA[Resolve “Could not dump table because of following FrozenError can’t modify frozen String: “false”]]></title><description><![CDATA[Photo by Markus Spiske on Unsplash
If you encountered this problem in your schema.rb file:
# Could not dump table "users" because of following FrozenError#   can't modify frozen String: "false"
Then, do the following:

Create file config/initializers...]]></description><link>https://vchkhr.com/resolve-could-not-dump-table-because-of-following-frozenerror-cant-modify-frozen-string-false-bb64d0701b52</link><guid isPermaLink="true">https://vchkhr.com/resolve-could-not-dump-table-because-of-following-frozenerror-cant-modify-frozen-string-false-bb64d0701b52</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Mon, 30 Oct 2023 13:29:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077395705/b333dd0e-6f9b-4b9c-980f-5d9460763396.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@markusspiske?utm_source=medium&amp;utm_medium=referral">Markus Spiske</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>If you encountered this problem in your <code>schema.rb</code> file:</p>
<p># Could not dump table "users" because of following FrozenError<br />#   can't modify frozen String: "false"</p>
<p>Then, do the following:</p>
<ol>
<li>Create file <code>config/initializers/prepare_column_options.rb</code> with the following content:</li>
</ol>
<p>module ActiveRecord<br />  module ConnectionAdapters<br />    module ColumnDumper<br />      def prepare_column_options(column, types)<br />        spec = {}<br />        spec[:name]      = column.name.inspect<br />        spec[:type]      = column.type.to_s<br />        spec[:null]      = 'false' unless column.null  </p>
<p>        limit = column.limit || types[column.type][:limit]<br />        spec[:limit]     = limit.inspect if limit<br />        spec[:precision] = column.precision.inspect if column.precision<br />        spec[:scale]     = column.scale.inspect if column.scale  </p>
<p>        default = schema_default(column).dup if column.has_default?<br />        spec[:default]   = default unless default.nil?  </p>
<p>        spec<br />      end<br />    end<br />  end<br />end</p>
<p>2. Run <code>bundle exec rake db:schema:dump</code> to recreate the <code>schema.rb</code> file.</p>
<p>And you will not see the following error in your <code>schema.rb</code> file anymore when you run <code>rails db:migrate</code>.</p>
<p>Source: <a target="_blank" href="https://stackoverflow.com/a/68708411">Abdul Rehman at Stack Overflow</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Інформація про відключення світла у Львові в Google Календарі]]></title><description><![CDATA[Львівобленерго може надсилати інформацію про відключення світла вам на пошту, яку потім можна автоматично надсилати до Google Календаря. І ось як це зробити.
Актуально станом на липень 2023.
Крок 1. Отримувати інформацію електронним листом
Для цього ...]]></description><link>https://vchkhr.com/lvivoblenerho-in-google-calendar-63bbfc1c0f0c</link><guid isPermaLink="true">https://vchkhr.com/lvivoblenerho-in-google-calendar-63bbfc1c0f0c</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Thu, 27 Jul 2023 11:00:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077491517/e3636a52-2fb3-4d96-85a6-f13c9317d2b7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Львівобленерго може надсилати інформацію про відключення світла вам на пошту, яку потім можна автоматично надсилати до Google Календаря. І ось як це зробити.</p>
<p>Актуально станом на липень 2023.</p>
<h3 id="heading-krok-1-otrimuvati-informaciyu-elektronnim-listom">Крок 1. Отримувати інформацію електронним листом</h3>
<p>Для цього потрібно зареєструвати <a target="_blank" href="https://info.loe.lviv.ua/">Персональний кабінет Львівобленерго</a>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077461384/25863268-8721-437e-8baf-aa5483cd531c.png" alt /></p>
<p>Після чого <a target="_blank" href="https://info.loe.lviv.ua/consumers/search">додати свою адресу</a>, натиснувши на кнопку “Додати споживача”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077462786/5e99983f-951e-491f-a797-cede233bac25.png" alt /></p>
<p>Вам знадобиться номер особового рахунку, який можна знайти у паперових рахунках або дізнатись в орендодавця, якщо ви винаймаєте житло.</p>
<p>Після додавання рахунок буде відображатись на головній сторінці:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077464383/36f31e12-758c-4504-a65c-cc7fb8ff365f.png" alt /></p>
<p>На вашу електронну пошту будуть надходити листи про відключення електроенергії:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077465584/3a7c3927-58cb-4cd2-b424-c12e11a91a8d.png" alt /></p>
<h3 id="heading-krok-2-reyestraciya-u-pipedream">Крок 2. Реєстрація у Pipedream</h3>
<p>Для того, аби додавати події до календаря, нам необхідно використовувати сервіс автоматизацій. Можна використовувати будь-який, де є інтеграція із поштою, Google Календарем та обробка тексту.</p>
<p>В цьому прикладі ми будемо використовувати сервіс <a target="_blank" href="https://pipedream.com/auth/signup">Pipedream</a>.</p>
<p>Перейдіть на <a target="_blank" href="https://pipedream.com/auth/signup">сторінку реєстрації</a> та створіть новий аккаунт:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077466869/74241453-201b-477d-a9ab-2f918f8eceb4.png" alt /></p>
<p>Після реєстрації відкриється інтерфейс створення нового workflow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077468223/92bd9d6f-f9b5-4038-a25c-e9b0ac07f435.png" alt /></p>
<h3 id="heading-krok-3-peresilannya-listiv-do-pipedream">Крок 3. Пересилання листів до Pipedream</h3>
<p>На сторінці створення workflow у Pipedream знайдіть додаток “Email”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077469548/7f167b83-0bae-40b9-a4ab-043c5f5663a0.png" alt /></p>
<p>Після натискання на додаток “Email” виберіть джерело “New Emails”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077471114/37ef30fb-fd4c-4b49-877b-84f64b105814.png" alt /></p>
<p>Розгорніть блок із подією, натиснувши на стрілочку біля тексту “Select event”.</p>
<p>Ви побачите адресу електронної пошти, на яку необхідно пересилати листи:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077472393/a0a1bc2b-c545-4a0c-b213-020e6883d65d.png" alt /></p>
<p>Для пересилання листів, перейдіть у налаштування Gmail в розділ “<a target="_blank" href="https://mail.google.com/mail/u/0/#settings/fwdandpop">Пересилання та POP/IMAP</a>”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077473722/1ee19699-c7f5-42e7-8159-a1fa69c90da4.png" alt /></p>
<p>Натисніть на кнопку “Додати адресу для пересилання” та вставте адресу електронної пошти із Pipedream із попереднього кроку.</p>
<p>Відкриється вікно підтвердження, натисніть “Продовжити”.</p>
<p>Тепер поверніться у Pipedream і ви побачите нову подію із листом, який надіслав Gmail:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077475390/48be6dea-a88a-403d-a4eb-f67d7b0a2b7b.png" alt /></p>
<p>Натисніть на нього, відкрийте вкладку “Results”. Потім розгорніть “steps.trigger”, “event”, “body” та“text”. Ви побачите посилання для підтвердження адреси пересилання, перейдіть за ним:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077476647/96463ace-4b26-4524-92a6-9d30a1f032d1.png" alt /></p>
<p>І натисніть “Підтвердити”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077478551/322d9aeb-0f41-4541-bc31-fc1fc2f4ba47.png" alt /></p>
<p>Тепер поверніться у налаштування Gmail та відкрийте вкладку “<a target="_blank" href="https://mail.google.com/mail/u/0/#settings/filters">Фільтри й заблоковані адреси</a>”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077479800/a47a1fe0-a719-4066-842f-db338e0e0414.png" alt /></p>
<p>Під списком натисніть “Створити новий фільтр”.</p>
<p>У полі “Від” введіть “<a target="_blank" href="mailto:online@loe.lviv.ua">online@loe.lviv.ua</a>”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077480889/093ed7ec-c4bc-4c77-a4fc-b14c5e1c39d2.png" alt /></p>
<p>Натисніть “Створити фільтр”.</p>
<p>Відмітьте пункт “Переслати на адресу” та оберіть адресу Pipedream із попереднього кроку:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077482430/4968a299-2b08-4bb5-aa79-03c4071cc4d2.png" alt /></p>
<p>Можна також відмітити “Видалити”, тоді листи не будуть залишатись у вхідних.</p>
<p>Натисніть на кнопку “Створити фільтр”.</p>
<h3 id="heading-krok-4-obrobka-listiv-u-pipedream">Крок 4. Обробка листів у Pipedream</h3>
<p>У Pipedream натисніть на “+” внизу сторінки та оберіть “Run custom code”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077483878/38bd0b8c-024d-4e37-8c1f-d9d085df848f.png" alt /></p>
<p>Тут вставте код для обробки листів:</p>
<p>function convertDateFormat(inputDate) {<br />  const [datePart, timePart] = inputDate.split(' ');  </p>
<p>  const [day, month, year] = datePart.split('.');  </p>
<p>  const [hours, minutes] = timePart.split(':');  </p>
<p>  return `${year}-${month}-${day}T${hours}:${minutes}:00`;<br />}  </p>
<p>export default defineComponent({<br />  async run({ steps, $ }) {<br />    const timezone = "03:00"  </p>
<p>    const description = steps.trigger.event.body.text  </p>
<p>    let dates = description.split("електроенергія з ")[1].split("\n")[0].split(" до ")  </p>
<p>    if (!dates[1].includes(" ")) {<br />      dates[1] = dates[0].split(" ")[0] + " " + dates[1]<br />    }  </p>
<p>    return {<br />      "start": `${convertDateFormat(dates[0])}+${timezone}`,<br />      "end": `${convertDateFormat(dates[1])}+${timezone}`,<br />      "reason": description.split("через ")[1].split(" відсутня електроенергія")[0].split(" з ")[0],<br />      "location": description.split("За адресою: ")[1].split(", кв.")[0].split(" через")[0].replace(", б.", ", ")<br />    }<br />  },<br />})</p>
<p>Дія має виглядати ось так:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077485387/57420cbc-5181-4bb5-9a93-3075ef0b05fd.png" alt /></p>
<h3 id="heading-krok-5-stvorennya-podiyi-v-kalendari">Крок 5. Створення події в календарі</h3>
<p>У Pipedream натисніть на “+” внизу сторінки та знайдіть додаток “Google Calendar”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077486636/6d696122-949c-4b50-9eec-edf128951aba.png" alt /></p>
<p>Оберіть подію “Create Event”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077488720/eaf03a47-7ae4-43d1-aca8-20fb205b3766.png" alt /></p>
<p>У полі “Google Calendar Account” натисніть “Connect account” та привʼяжіть свій Google Аккаунт, надавши всі необхідні дозволи.</p>
<p>У полі “Calendar ID” оберіть календар, до якого будуть додаватись події. Новий календар можна створити на сайті <a target="_blank" href="https://calendar.google.com/calendar/u/0/r/settings/createcalendar">Google Календаря</a>.</p>
<p>Наступні поля заповніть такими значеннями:</p>
<p>Event Title:<br />⚡ Відключення світла: {{steps.code.$return_value.reason}}  </p>
<p>Event Location:<br />{{steps.code.$return_value.location}}  </p>
<p>Event Description:<br />{{steps.trigger.event.body.text}}  </p>
<p>Event Start Date:<br />{{steps.code.$return_value.start}}  </p>
<p>Event End Date:<br />{{steps.code.$return_value.end}}</p>
<p>Тепер зверху справа натисніть на кнопку “Deploy”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077490234/1bc41ce3-f2b4-429d-bfa7-77f7f1e58a30.png" alt /></p>
<h3 id="heading-rezultat">Результат</h3>
<p>Тепер ви отримуватимете інформацію про відключення світла у своєму календарі:</p>
]]></content:encoded></item><item><title><![CDATA[How to delete Dialogflow agent if it is not listed?]]></title><description><![CDATA[If you are trying to delete the Google Cloud project, and seeing the error which says you already have an active Dialogflow agent, you will also have a link to this agent:

But, when you follow the link, you just see the home page of Dialogflow with ...]]></description><link>https://vchkhr.com/how-to-delete-dialogflow-agent-if-it-is-not-listed-9e709476f486</link><guid isPermaLink="true">https://vchkhr.com/how-to-delete-dialogflow-agent-if-it-is-not-listed-9e709476f486</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Thu, 20 Apr 2023 09:57:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077400851/af2596f3-3879-48d0-9c00-dca563054c5f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you are trying to delete the Google Cloud project, and seeing the error which says you already have an active Dialogflow agent, you will also have a link to this agent:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077399503/78fd9a49-f71c-4c3d-9466-fe9d71ecd12c.png" alt /></p>
<p>But, when you follow the link, you just see the home page of Dialogflow with the message that you don’t have any agents:</p>
<p>Here is an instruction on how to delete the agent:</p>
<ol>
<li>Go to the <a target="_blank" href="https://cloud.google.com/shell">Google Cloud Shell</a>. Make sure you selected the right project at the upper left corner of the page.</li>
<li>Type in <code>gcloud config set project id</code> with id of your project instead of <code>id</code>. To get the id, click on the name of the project in the upper left corner and find the id in the “ID” column of the table.</li>
<li>Run <code>gcloud alpha resource-manager liens list</code> in the G Cloud Shell. You will see the message with the following first line: “NAME: id” with the id of the lien to delete.</li>
<li>Type in <code>gcloud alpha resource-manager liens delete id</code> and replace the <code>id</code> with the lien’s id from the previous step. You should see the message “Deleted”.</li>
</ol>
<p>Now the Dialogflow agent is deleted and you can completely delete the Google Cloud project.</p>
<p><a target="_blank" href="https://stackoverflow.com/a/72587771">Source</a></p>
]]></content:encoded></item><item><title><![CDATA[Fix missing icons in Active Admin’s Bootstrap skin]]></title><description><![CDATA[If you’re experiencing missing icons in the Active Bootstrap skin for Active Admin in a Ruby on Rails application, then you’re not alone.
Active Bootstrap skin with missed icons
This article applies to the version [0.1.5](https://rubygems.org/gems/ac...]]></description><link>https://vchkhr.com/fix-missing-icons-in-active-admins-bootstrap-skin-c108120ae781</link><guid isPermaLink="true">https://vchkhr.com/fix-missing-icons-in-active-admins-bootstrap-skin-c108120ae781</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Fri, 10 Feb 2023 15:47:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077407757/17f23a0f-decb-4568-9fa4-497279bbfa22.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you’re experiencing missing icons in the <a target="_blank" href="https://github.com/vinhnglx/active_bootstrap_skin">Active Bootstrap skin</a> for <a target="_blank" href="https://github.com/activeadmin/activeadmin">Active Admin</a> in a Ruby on Rails application, then you’re not alone.</p>
<p>Active Bootstrap skin with missed icons</p>
<p>This article applies to the version <code>[0.1.5](https://rubygems.org/gems/active_bootstrap_skin/versions/0.1.5)</code> <a target="_blank" href="https://rubygems.org/gems/active_bootstrap_skin/versions/0.1.5">of the Active Bootstrap skin gem</a>.</p>
<p>To fix this issue, open the file <code>app/assets/stylesheets/active_admin.scss</code> and modify:</p>
<p>// @import "active_bootstrap_skin"; &lt;- remove or comment this line previously in your code<br />@import "active_bootstrap_skin_modified";</p>
<p>Then, create a new file <code>app/assets/stylesheets/active_bootstrap_skin_modified.scss</code>. Paste the content of the file <code>active_bootstrap_skin</code> from the original gem. Here is the link to this file on the gem’s repository: <a target="_blank" href="https://github.com/vinhnglx/active_bootstrap_skin/blob/master/app/assets/stylesheets/active_bootstrap_skin.scss">https://github.com/vinhnglx/active_bootstrap_skin/blob/master/app/assets/stylesheets/active_bootstrap_skin.scss</a></p>
<p>In this file, delete or comment following lines (note: <a target="_blank" href="https://gist.github.com/vchkhr/c469e614668545a2002c8363399c40e3">the completed code is presented here</a>):</p>
<p>// #main_content_wrapper .table_actions {<br />//   @extend .btn-toolbar;<br />//   min-width: 117px;  </p>
<p>//   &gt; .member_link {<br />//     margin: (-3px) 10px 0 0;  </p>
<p>//     &amp;:last-child {<br />//       margin-right: 0;<br />//     }<br />//   }<br />// }</p>
<p>// @extend .glyphicon;<br />// font-size: 0;<br />// text-align: center;<br />// padding: 3px 0;<br />// width: 28px;  </p>
<p>// &amp;:before {<br />//   font-size: 14px;<br />// }</p>
<p>// .ui-sortable-handle {<br />//   @extend .glyphicon-sort;<br />//   cursor: all-scroll;<br />// }  </p>
<p>// .view_link {<br />//   @extend .glyphicon-search;<br />// }  </p>
<p>// .edit_link {<br />//   @extend .glyphicon-pencil;<br />// }  </p>
<p>// .delete_link {<br />//   @extend .glyphicon-trash;<br />// }</p>
<p>Update the browser tab and you will see that buttons are now too big:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077404913/d097f8e4-b12f-47ef-ae87-fbf70589bef9.png" alt /></p>
<p>Buttons are too big</p>
<p>To fix this, add the following lines to the end of the file:</p>
<p>.member_link, .ui-sortable-handle {<br />  padding: 0px 10px;<br />}</p>
<p>The result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077406350/0e5cae51-da1a-4c0f-87f8-9b4b31e1741c.png" alt /></p>
<p>Buttons with the proper size and without icons</p>
<p>You can see the <a target="_blank" href="https://gist.github.com/vchkhr/c469e614668545a2002c8363399c40e3">completed file here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Fix error `gpg: keyserver receive failed: Server indicated a failure` on Ubuntu]]></title><description><![CDATA[Photo by Gabriel Heinzer on Unsplash
To fix this error:
gpg: keyserver receive failed: Server indicated a failure
In your command replace hkp://pool.sks-keyservers.net with keyserver.ubuntu.com .
For example:
gpg --keyserver hkp://pool.sks-keyservers...]]></description><link>https://vchkhr.com/fix-error-gpg-keyserver-receive-failed-server-indicated-a-failure-on-ubuntu-88881e757efa</link><guid isPermaLink="true">https://vchkhr.com/fix-error-gpg-keyserver-receive-failed-server-indicated-a-failure-on-ubuntu-88881e757efa</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Tue, 30 Aug 2022 15:36:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077412797/32b5660c-5080-4cc2-84ef-ae0eab6ada0c.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@6heinz3r?utm_source=medium&amp;utm_medium=referral">Gabriel Heinzer</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>To fix this error:</p>
<p>gpg: keyserver receive failed: Server indicated a failure</p>
<p>In your command replace <code>hkp://pool.sks-keyservers.net</code> with <code>keyserver.ubuntu.com</code> .</p>
<p>For example:</p>
<p>gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB<br /># Output: gpg: keyserver receive failed: Server indicated a failure</p>
<p>gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB<br /># Output is fine</p>
]]></content:encoded></item><item><title><![CDATA[Wrap a table row with a Turbo Frame tag in Rails]]></title><description><![CDATA[It’s impossible to wrap tr with turbo_frame tag in HTML.
Photo by Campaign Creators on Unsplash
To solve this problem, we should add a specific attribute to tr element:
https://gist.github.com/6f781c0d3482ba10068c3f14cc70b363And now we can perform tu...]]></description><link>https://vchkhr.com/wrap-a-table-row-with-a-turbo-frame-tag-in-rails-d1eb052a2f74</link><guid isPermaLink="true">https://vchkhr.com/wrap-a-table-row-with-a-turbo-frame-tag-in-rails-d1eb052a2f74</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Wed, 22 Jun 2022 17:45:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077418636/62a30da1-0c84-4277-a882-04b3de34c651.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It’s impossible to wrap <code>tr</code> with <code>turbo_frame</code> tag in HTML.</p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@campaign_creators?utm_source=medium&amp;utm_medium=referral">Campaign Creators</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>To solve this problem, we should add a specific attribute to <code>tr</code> element:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6f781c0d3482ba10068c3f14cc70b363"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/6f781c0d3482ba10068c3f14cc70b363" class="embed-card">https://gist.github.com/6f781c0d3482ba10068c3f14cc70b363</a></div><p>And now we can perform <code>turbo_stream.replace</code> in our controller:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="2a99b9937af71a3920c24a0e3ae22a3f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/2a99b9937af71a3920c24a0e3ae22a3f" class="embed-card">https://gist.github.com/2a99b9937af71a3920c24a0e3ae22a3f</a></div><p><a target="_blank" href="https://github.com/hotwired/turbo/pull/131">Source</a></p>
]]></content:encoded></item><item><title><![CDATA[Validate and Fix Phone Number with JavaScript]]></title><description><![CDATA[Photo by James Sutton on Unsplash
There is a standard for the phone number called ‘E.164’.
It says that the phone number should have a ‘+’ sign at the start and a maximum of 15 digits.
So, our JavaScript should:

Check if there is a ‘+’ sign at the s...]]></description><link>https://vchkhr.com/validate-and-fix-phone-number-with-javascript-1b3cabd13420</link><guid isPermaLink="true">https://vchkhr.com/validate-and-fix-phone-number-with-javascript-1b3cabd13420</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Mon, 13 Jun 2022 12:59:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077422124/985dfd58-bd06-4bbe-b84e-ee23fbad22d4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@jamessutton_photography?utm_source=medium&amp;utm_medium=referral">James Sutton</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>There is a standard for the phone number called ‘<a target="_blank" href="https://en.wikipedia.org/wiki/E.164">E.164</a>’.</p>
<p>It says that the phone number should have a ‘+’ sign at the start and a maximum of 15 digits.</p>
<p>So, our JavaScript should:</p>
<ol>
<li>Check if there is a ‘+’ sign at the start of the string and add it if necessary.</li>
<li>Do not allow to enter letters and other signs. Only digits.</li>
<li>Allow to enter up to 15 digits.</li>
</ol>
<p>The JavaScript code which implements this functionality:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6b2d02bbfc88d714ddb5c2df3be6b259"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/6b2d02bbfc88d714ddb5c2df3be6b259" class="embed-card">https://gist.github.com/6b2d02bbfc88d714ddb5c2df3be6b259</a></div><p>Demo:</p>
<iframe src="https://codepen.io/vchkhr/embed/preview/yLvGvvN?default-tabs=js%2Cresult&amp;height=600&amp;host=https%3A%2F%2Fcodepen.io&amp;slug-hash=yLvGvvN" width="700" height="525"></iframe>]]></content:encoded></item><item><title><![CDATA[Use Turbo Frame Tag in ViewComponent]]></title><description><![CDATA[Photo by James Harrison on Unsplash
You can see this error:
undefined method `turbo_frame_tag'
when trying to use turbo_frame_tag inside of your ViewComponent.
To solve this, add a helper to your ApplicationComponent:
https://gist.github.com/da9b92b7...]]></description><link>https://vchkhr.com/use-turbo-frame-tag-in-viewcomponent-be4b1a4916f6</link><guid isPermaLink="true">https://vchkhr.com/use-turbo-frame-tag-in-viewcomponent-be4b1a4916f6</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Tue, 31 May 2022 09:25:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077426414/5addceb5-7c94-4bac-9750-071fbdcae797.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@jstrippa?utm_source=medium&amp;utm_medium=referral">James Harrison</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>You can see this error:</p>
<pre><code><span class="hljs-literal">undefined</span> method <span class="hljs-string">`turbo_frame_tag'</span>
</code></pre><p>when trying to use <code>turbo_frame_tag</code> inside of your <code>ViewComponent</code>.</p>
<p>To solve this, add a helper to your ApplicationComponent:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://gist.github.com/da9b92b74320ce4b0e0a95c9eb6c1bcb.js">https://gist.github.com/da9b92b74320ce4b0e0a95c9eb6c1bcb.js</a></div>
<p>And inherit from <code>ApplicationComponent</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Update Rails 7 Credentials]]></title><description><![CDATA[Photo by Towfiqu barbhuiya on Unsplash
Update Credentials of Current Environment
To edit Rails 7 credentials in the preferred editor, run:
EDITOR= rails credentials:edit
Replace <editor> with editor name.
For example:
# nanoEDITOR=nano rails credenti...]]></description><link>https://vchkhr.com/update-rails-7-credentials-eb3068a5fe51</link><guid isPermaLink="true">https://vchkhr.com/update-rails-7-credentials-eb3068a5fe51</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Thu, 26 May 2022 14:31:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077429331/7cfdba6a-0bfd-495e-8c95-64ca828e8c88.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@towfiqu999999?utm_source=medium&amp;utm_medium=referral">Towfiqu barbhuiya</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<h3 id="heading-update-credentials-of-current-environment">Update Credentials of Current Environment</h3>
<p>To edit Rails 7 credentials in the preferred editor, run:</p>
<p>EDITOR= rails credentials:edit</p>
<p>Replace <code>&lt;editor&gt;</code> with editor name.</p>
<p>For example:</p>
<p># nano<br />EDITOR=nano rails credentials:edit</p>
<p># mate<br />EDITOR="mate --wait" rails credentials:edit</p>
<h3 id="heading-update-credentials-of-other-environment">Update Credentials of Other Environment</h3>
<p>To edit production’s credentials, run:</p>
<p>EDITOR=nano rails credentials:edit --environment </p>
<p>Replace <code>&lt;env_name&gt;</code>with needed environment name.</p>
<p>For example:</p>
<p># production:<br />EDITOR=nano rails credentials:edit --environment production</p>
<p># staging<br />EDITOR=nano rails credentials:edit --environment staging</p>
]]></content:encoded></item><item><title><![CDATA[Get a List of HTML Tags and Attributes Used in the Code]]></title><description><![CDATA[Photo by Florian Olivo on Unsplash
Get a List of HTML Tags used in your code:
https://gist.github.com/eaf3ac26fd3b91e9425c6f918727b592Get a List of HTML Attributes used in your code:
https://gist.github.com/ca326635b9e5e221bb149968ee448d2a]]></description><link>https://vchkhr.com/get-a-list-of-html-tags-and-attributes-used-in-the-code-3d12547b4707</link><guid isPermaLink="true">https://vchkhr.com/get-a-list-of-html-tags-and-attributes-used-in-the-code-3d12547b4707</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Wed, 20 Apr 2022 16:15:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077433210/6a954fd7-9823-45c1-a976-bc97a5bb32f0.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@florianolv?utm_source=medium&amp;utm_medium=referral">Florian Olivo</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>Get a List of HTML Tags used in your code:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="eaf3ac26fd3b91e9425c6f918727b592"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/eaf3ac26fd3b91e9425c6f918727b592" class="embed-card">https://gist.github.com/eaf3ac26fd3b91e9425c6f918727b592</a></div><p>Get a List of HTML Attributes used in your code:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="ca326635b9e5e221bb149968ee448d2a"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ca326635b9e5e221bb149968ee448d2a" class="embed-card">https://gist.github.com/ca326635b9e5e221bb149968ee448d2a</a></div>]]></content:encoded></item><item><title><![CDATA[How to Add JWT Auth API to Existing Rails Application]]></title><description><![CDATA[Photo by Jordan Harrison on Unsplash
First things first, add ‘JWT’ and ‘Blueprint’ gems to your Gemfile.
JWT gem is a ruby implementation of the RFC 7519 OAuth JSON Web Token (JWT) standard.
Blueprinter is a JSON Object Presenter for Ruby that takes ...]]></description><link>https://vchkhr.com/how-to-add-jwt-auth-api-to-existing-rails-project-a5f91130ca54</link><guid isPermaLink="true">https://vchkhr.com/how-to-add-jwt-auth-api-to-existing-rails-project-a5f91130ca54</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Mon, 04 Apr 2022 15:39:52 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077442296/e17ec87f-72c7-40b4-b037-145aa4b09465.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@jordanharrison?utm_source=medium&amp;utm_medium=referral">Jordan Harrison</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>First things first, add ‘JWT’ and ‘Blueprint’ gems to your <code>Gemfile</code>.</p>
<p>JWT gem is a ruby implementation of the <a target="_blank" href="https://tools.ietf.org/html/rfc7519">RFC 7519 OAuth JSON Web Token (JWT)</a> standard.</p>
<p>Blueprinter is a JSON Object Presenter for Ruby that takes business objects and breaks them down into simple hashes and serializes them to JSON.</p>
<p>So, your <code>Gemfile</code> should contain these new lines:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="4835b4184f61393f3f48b9cf7a3b920f"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/4835b4184f61393f3f48b9cf7a3b920f" class="embed-card">https://gist.github.com/4835b4184f61393f3f48b9cf7a3b920f</a></div><p>Then run <code>bundle</code> in the Terminal.</p>
<p>To be able to access API pages, add them to the <code>routes.rb</code> file:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="60542ac9a34c57ec879fdd5afa766174"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/60542ac9a34c57ec879fdd5afa766174" class="embed-card">https://gist.github.com/60542ac9a34c57ec879fdd5afa766174</a></div><p>Create <code>app/controllers/api</code> folder and put the <code>api_controller.rb</code> file there:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="29ba282289564510bd79030e07e35ba2"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/29ba282289564510bd79030e07e35ba2" class="embed-card">https://gist.github.com/29ba282289564510bd79030e07e35ba2</a></div><p>To implement the registration feature, create this <code>registrations_controller.rb</code> file. Note, that standard registration logic is reused from the version of the application before the API feature implementation. Here we used the DRY Monads.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="fad1714fd3f0a9dd598a4ee2947c237e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/fad1714fd3f0a9dd598a4ee2947c237e" class="embed-card">https://gist.github.com/fad1714fd3f0a9dd598a4ee2947c237e</a></div><p>Implement the authorization feature in <code>sessions_controller.rb</code>:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="8fe80b6c5860c791bd30813e465fbb69"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/8fe80b6c5860c791bd30813e465fbb69" class="embed-card">https://gist.github.com/8fe80b6c5860c791bd30813e465fbb69</a></div><p>To test the API we can try to get the profile data for an authenticated user with the <code>users_controller</code>:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="ef7324e170c2b186e6fca95d7a2d6e6e"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/ef7324e170c2b186e6fca95d7a2d6e6e" class="embed-card">https://gist.github.com/ef7324e170c2b186e6fca95d7a2d6e6e</a></div><p>Add Blueprint that will transform object’s data to JSON:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6b496ac6e9c7a733bd0187e67ae9fd0b"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/6b496ac6e9c7a733bd0187e67ae9fd0b" class="embed-card">https://gist.github.com/6b496ac6e9c7a733bd0187e67ae9fd0b</a></div><p>That’s it! You have JWT Auth API with DRY Monads in your existing Rails application.</p>
]]></content:encoded></item><item><title><![CDATA[Turbo Stream: Render ViewComponent]]></title><description><![CDATA[Photo by Goran Ivos on Unsplash
To render the ViewComponent with Turbo Stream in your controller do the following.
https://gist.github.com/629371d895a2d2317de4006f3469708dNow you can render the content in your SearchComponent.]]></description><link>https://vchkhr.com/turbo-stream-render-viewcomponent-bc236cbc80bb</link><guid isPermaLink="true">https://vchkhr.com/turbo-stream-render-viewcomponent-bc236cbc80bb</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Mon, 04 Apr 2022 10:25:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077438927/f76b1b11-e9ce-458a-be62-26d0a26bae95.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Photo by <a target="_blank" href="https://unsplash.com/@goran_ivos?utm_source=medium&amp;utm_medium=referral">Goran Ivos</a> on <a target="_blank" href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></p>
<p>To render the ViewComponent with Turbo Stream in your controller do the following.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="629371d895a2d2317de4006f3469708d"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/629371d895a2d2317de4006f3469708d" class="embed-card">https://gist.github.com/629371d895a2d2317de4006f3469708d</a></div><p>Now you can render the content in your <code>SearchComponent</code>.</p>
]]></content:encoded></item><item><title><![CDATA[Enable SynthWave ’84 Glow Effect on Ubuntu & Arch]]></title><description><![CDATA[SynthWave ’84
To enable the glow effect from the Synth Wave ’84 extension you should run the VS Code with administrative privileges.
In the Ubuntu & Arch systems, you shouldn’t run the VS Code with sudo.
Instead, run this command in the Terminal.
htt...]]></description><link>https://vchkhr.com/enable-synthwave-84-glow-effect-on-ubuntu-arch-a571f2871138</link><guid isPermaLink="true">https://vchkhr.com/enable-synthwave-84-glow-effect-on-ubuntu-arch-a571f2871138</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Mon, 04 Apr 2022 08:15:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077435643/38462901-921c-4628-b9fa-1e74fcef180a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>SynthWave ’84</p>
<p>To enable the glow effect from the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=RobbOwen.synthwave-vscode">Synth Wave ’84 extension</a> you should run the VS Code with administrative privileges.</p>
<p>In the Ubuntu &amp; Arch systems, you shouldn’t run the VS Code with <code>sudo</code>.</p>
<p>Instead, run this command in the Terminal.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="766f3bd71bd8ea180665f8e7481a0dcd"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/766f3bd71bd8ea180665f8e7481a0dcd" class="embed-card">https://gist.github.com/766f3bd71bd8ea180665f8e7481a0dcd</a></div><p>Open the Command Palette in VS Code with <code>Ctrl+Shift+P</code> and run <code>Enable Neon Dreams</code>.</p>
<p>Restart the VS Code and you will see the fancy glow effect.</p>
]]></content:encoded></item><item><title><![CDATA[How to solve “undefined method `documentations’ for RspecApiDocumentation:Module”]]></title><description><![CDATA[Photo by Jake Walker on Unsplash
If you encounter the following problem while using rspec_api_documentation gem:
/usr/local/bundle/gems/rspec_api_documentation-6.1.0/lib/rspec_api_documentation/api_formatter.rb:16:in `start': undefined method `docume...]]></description><link>https://vchkhr.com/how-to-solve-undefined-method-documentations-for-rspecapidocumentation-module-e9c7d38ed9ce</link><guid isPermaLink="true">https://vchkhr.com/how-to-solve-undefined-method-documentations-for-rspecapidocumentation-module-e9c7d38ed9ce</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Wed, 16 Mar 2022 13:44:35 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077445869/6541d170-c6f5-4721-97ab-06c1b07a4e56.jpeg" alt /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@jakewalker?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jake Walker</a> on <a target="_blank" href="https://unsplash.com/s/photos/computer-error?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<p>If you encounter the following problem while using <code>rspec_api_documentation</code> gem:</p>
<p>/usr/local/bundle/gems/rspec_api_documentation-6.1.0/lib/rspec_api_documentation/api_formatter.rb:16:in `start': undefined method `documentations' for RspecApiDocumentation:Module (NoMethodError)</p>
<p>RspecApiDocumentation.documentations.each(&amp;:clear_docs)</p>
<p>Try to add this at the top of <code>spec/spec_helper.rb</code> file:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="48364c9ee89577c2f2ef9d824b9d6064"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/48364c9ee89577c2f2ef9d824b9d6064" class="embed-card">https://gist.github.com/48364c9ee89577c2f2ef9d824b9d6064</a></div>]]></content:encoded></item><item><title><![CDATA[Auto Save Action Text Data in Rails]]></title><description><![CDATA[Automatically save rich text in local storage using Stimulus.

Photo by Goran Ivos on Unsplash

Create a Stimulus controller.

https://gist.github.com/f30572016568be2af01ed5f07f81d7fe2. Add controller to the index.js file.
https://gist.github.com/cf9...]]></description><link>https://vchkhr.com/auto-save-action-text-data-in-rails-c2a1d03c416a</link><guid isPermaLink="true">https://vchkhr.com/auto-save-action-text-data-in-rails-c2a1d03c416a</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Fri, 11 Mar 2022 20:20:43 GMT</pubDate><content:encoded><![CDATA[<p>Automatically save rich text in local storage using Stimulus.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077456443/8feb9a1c-6a94-4717-815f-71d1d2eea393.jpeg" alt="MacBook Air on gray armchair" /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@goran_ivos?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Goran Ivos</a> on <a target="_blank" href="https://unsplash.com/s/photos/writer-with-computer?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<ol>
<li>Create a Stimulus controller.</li>
</ol>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="f30572016568be2af01ed5f07f81d7fe"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/f30572016568be2af01ed5f07f81d7fe" class="embed-card">https://gist.github.com/f30572016568be2af01ed5f07f81d7fe</a></div><p>2. Add controller to the <code>index.js</code> file.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="cf96ee6220a69535d307aff0a4873e15"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/cf96ee6220a69535d307aff0a4873e15" class="embed-card">https://gist.github.com/cf96ee6220a69535d307aff0a4873e15</a></div><p>3. Add controller to the form in your view file.</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="c9b4ebc32a6c3bbf10597f0ad6b9f533"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/c9b4ebc32a6c3bbf10597f0ad6b9f533" class="embed-card">https://gist.github.com/c9b4ebc32a6c3bbf10597f0ad6b9f533</a></div>]]></content:encoded></item><item><title><![CDATA[How to solve “undefined method 'rich_text_area_tag'”]]></title><description><![CDATA[Photo by Sigmund on Unsplash
If you use ViewComponent, add the following to your base component:
https://gist.github.com/f8f08df3d725d695704a401521b81ae2]]></description><link>https://vchkhr.com/how-to-solve-undefined-method-rich-text-area-tag-f0342b09d759</link><guid isPermaLink="true">https://vchkhr.com/how-to-solve-undefined-method-rich-text-area-tag-f0342b09d759</guid><dc:creator><![CDATA[Viacheslav Kharchenko]]></dc:creator><pubDate>Wed, 09 Mar 2022 15:51:37 GMT</pubDate><content:encoded><![CDATA[<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1769077452724/d16e10d3-230f-418c-939b-e487622a4b5b.jpeg" alt /></p>
<p>Photo by <a target="_blank" href="https://unsplash.com/@sigmund?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Sigmund</a> on <a target="_blank" href="https://unsplash.com/s/photos/programmer-rails?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></p>
<p>If you use ViewComponent, add the following to your base component:</p>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="f8f08df3d725d695704a401521b81ae2"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/f8f08df3d725d695704a401521b81ae2" class="embed-card">https://gist.github.com/f8f08df3d725d695704a401521b81ae2</a></div>]]></content:encoded></item></channel></rss>