<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: PostCo</title>
    <description>The latest articles on DEV Community by PostCo (@postco).</description>
    <link>https://dev.to/postco</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1678%2Fcf23f37b-bdea-425e-a397-d8b75329ebe8.png</url>
      <title>DEV Community: PostCo</title>
      <link>https://dev.to/postco</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/postco"/>
    <language>en</language>
    <item>
      <title>Solve node-gyp build error due to PYTHONPATH</title>
      <dc:creator>Andy Chong</dc:creator>
      <pubDate>Fri, 07 Feb 2020 09:54:25 +0000</pubDate>
      <link>https://dev.to/postco/solve-node-gyp-build-error-due-to-pythonpath-3kk6</link>
      <guid>https://dev.to/postco/solve-node-gyp-build-error-due-to-pythonpath-3kk6</guid>
      <description>&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://github.com/nodejs/node-gyp/pull/2012" rel="noopener noreferrer"&gt;node-gyp@5.1.0&lt;/a&gt; onwards, python3 will be used for the build, therefore please follow the steps below, but replace the last step with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;python3 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Recently, I faced the problem where &lt;code&gt;node-gyp rebuild&lt;/code&gt; failed due to PYTHONPATH is pointing to python3. This is due to python2 is being deprecated, and &lt;code&gt;python&lt;/code&gt; now points to python3 by default. While node-gyp requires python2 to build.&lt;/p&gt;

&lt;p&gt;To solve this on macOS, just make sure you reinstall python 2 and python 3 and point PYTHONPATH environment variable to python2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Only do this if `where python2` output nothing&lt;/span&gt;
brew uninstall &lt;span class="nt"&gt;--ignore-dependencies&lt;/span&gt; python2 python3
brew &lt;span class="nb"&gt;install &lt;/span&gt;python2 python3 


&lt;span class="nv"&gt;PYTHONPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;python2 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DONE!&lt;/p&gt;




&lt;p&gt;References&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nodejs/node-gyp/issues/1643#issuecomment-456011575" rel="noopener noreferrer"&gt;https://github.com/nodejs/node-gyp/issues/1643#issuecomment-456011575&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>npm</category>
      <category>macos</category>
      <category>node</category>
    </item>
    <item>
      <title>[TIL]  Debugging external gem in Ruby </title>
      <dc:creator>YC Yap</dc:creator>
      <pubDate>Tue, 04 Feb 2020 09:12:31 +0000</pubDate>
      <link>https://dev.to/postco/til-debugging-external-gem-in-ruby-742</link>
      <guid>https://dev.to/postco/til-debugging-external-gem-in-ruby-742</guid>
      <description>&lt;p&gt;Sometimes there comes a time where an external gem that you installed is not behaving as expected. It was not until a week ago that i learned from my colleague that you can actually open the gems to inspect the code inside the gem and debugging it using a debugger. &lt;/p&gt;

&lt;p&gt;Firstly, you can open the gem by running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="n"&gt;countries&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Identify the part of the code which you wish to debug. For example i would like to understand why a method in the  gem 'countries' is not returning values as expected. &lt;/p&gt;

&lt;p&gt;Start inserting calls to debugger in places you expect it to call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'byebug'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ISO3166&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Country&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;country_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;byebug&lt;/span&gt;
      &lt;span class="vi"&gt;@country_data_or_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;country_data&lt;/span&gt;
      &lt;span class="n"&gt;reload&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Using debugger allows you to better understand the code execution, so that variables which are causing the unexpected behaviours during the execution call be be inspected.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>My Transition From Mechanical to Software Engineering</title>
      <dc:creator>MarcusZ</dc:creator>
      <pubDate>Tue, 31 Dec 2019 02:55:27 +0000</pubDate>
      <link>https://dev.to/postco/my-transition-from-mechanical-to-software-engineering-44dd</link>
      <guid>https://dev.to/postco/my-transition-from-mechanical-to-software-engineering-44dd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This post is dedicated to &lt;strong&gt;PostCo&lt;/strong&gt;, a company that believes in me and offer me a full-time position as a software developer. In this blog post, I will briefly share my experiences on three different phases starting from the pre-interview preparation, the actual interview and finally on the working experience after I accepted the offer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-interview Preparation
&lt;/h3&gt;

&lt;p&gt;Before I move on, allow me to briefly introduce myself. My name is Marcus, a fresh graduate mechanical engineering student from the University of Malaya. My career interest has shifted towards software engineering since my third year of mechanical study. From then on, I started teaching myself how to code through many of the online resources. Other than taking online courses, I had also gone through a 3 months internship as a software developer intern at a local startup. After the internship, I am convinced that software engineering is what I want to do as a career. Immediately after my graduation, I started firing out my resume applying for junior developer positions at many different companies while studying the book - Cracking the Coding Interview.&lt;/p&gt;

&lt;h3&gt;
  
  
  Actual Interview
&lt;/h3&gt;

&lt;p&gt;I do not have high hope of receiving any replies from any of the companies simply for the reason that I am not a computer science student. However, the result turned out to be pretty good. Six out of the many companies I had applied to, offered me the opportunities to interview and I attended 4 of them. PostCo is the third interview that I went to and I am very happy to share my interview experience with PostCo here.&lt;/p&gt;

&lt;p&gt;The interview was divided into 2 rounds, the first round was the CEO round and followed by the technical interview. During the CEO round, I was asked questions like how would I use technology to help solve PostCo's business problems. I did okay for the first round, not very good but not that bad. &lt;/p&gt;

&lt;p&gt;After the CEO round, two developers from PostCo walked into the meeting room preparing for the technical interview. I was excited and nervous at the same time because that was my first interview with developers. In my previous two interviews, those sessions were conducted by HR with some paper and online coding tests. Just as they were walking in the room, in my mind, I started imagining that they would ask me to code on the whiteboard solving some difficult algorithms and data structures problems. Turned out I was wrong again, they were more interested in the reasons why I decided to switch from mechanical to software engineering. Our conversation went pretty well, I managed to explain myself and at the same time learn more about the tech stack PostCo is using and also the day to day job as a software developer there. After that, I had a pair programming session with one of the developers solving the common coding interview question - converting snake_case to camelCase. And that's all for the technical interview. At the end of the session, I was told that the result will be out in two weeks' time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accepting the offer
&lt;/h3&gt;

&lt;p&gt;While waiting for the reply from PostCo, I did not think that I hold a chance to receive an offer from them for two main reasons. The first reason is that PostCo is a startup, and usually, a startup will want to hire someone who can hit the ground running. The second reason is that the main tech stack at PostCo is &lt;code&gt;Ruby on Rails&lt;/code&gt; which is something that I have never done before. I was expecting a &lt;code&gt;No&lt;/code&gt; from them and started looking out for other opportunities.&lt;/p&gt;

&lt;p&gt;However, I was very glad that my expectation was wrong again this time. I received a call from one of the developers just one week after my interview and he told me that PostCo is offering me a two months software associate program with the opportunity to turn full-time depending on my performance. With PostCo's offer, I have a total of 3 &lt;code&gt;Yes&lt;/code&gt; out of the 4 interviews that I had attended. After careful consideration, I have decided to go with PostCo because I like the mission, colleagues, and environment at PostCo.&lt;/p&gt;

&lt;p&gt;This month is my fourth month working as a software developer at PostCo, which means that I passed my "probation" and I am now a full-timer. To keep this short and sweet, I will not go into details on my day to day job but just listing down what new tech stacks I have learned so far and also what I like the most working at PostCo.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;New Tech Stack:

&lt;ul&gt;
&lt;li&gt;Ruby on Rails&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What I like the most working at PostCo:

&lt;ul&gt;
&lt;li&gt;My opinions are heard even though I am a fresh graduate.&lt;/li&gt;
&lt;li&gt;I was given the trust to develop new features for the product.&lt;/li&gt;
&lt;li&gt;Help and guides are always there whenever I needed them.&lt;/li&gt;
&lt;li&gt;Colleagues who are eager to learn.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Last But Not Least
&lt;/h3&gt;

&lt;p&gt;It was a very hard decision for me when I decided to switch from mechanical to software engineering. Until now, I am not sure if it was a good decision but I have no regret at all. I followed my heart, and now I am enjoying my job working as a software developer. To be honest, it was not an easy journey, I have so many new things to learn every day at work and sometimes I felt like I know nothing. I think they call it &lt;code&gt;imposter syndrome&lt;/code&gt;. But, there is no free lunch in this world, you have to work hard for what you want to achieve. I know that my journey ahead will be filled by a lot of new challenges and new things to learn but yeah, let's bring it on! If I were to give one piece of advice to anyone out there thinking of switching into software development, I will say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never stop learning and have more confidence in yourself. No one knows you better than yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks &lt;strong&gt;PostCo&lt;/strong&gt; again for this amazing opportunity!&lt;/p&gt;

</description>
      <category>startup</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Running a book club in PostCo </title>
      <dc:creator>YC Yap</dc:creator>
      <pubDate>Mon, 30 Dec 2019 06:34:52 +0000</pubDate>
      <link>https://dev.to/postco/running-a-book-club-in-postco-1dbp</link>
      <guid>https://dev.to/postco/running-a-book-club-in-postco-1dbp</guid>
      <description>&lt;p&gt;This article will be about our learnings running a tech book club in PostCo for the past 3 months. &lt;/p&gt;

&lt;p&gt;Our motivation&lt;br&gt;
We want to try to cultivate a strong learning culture in PostCo, book clubs are a fast way to encourage cross learning and healthy discussion among team members.  We decided to start with a book that is simple enough and is on everybody’s reading list, Pragmatic Programmer by Dave Thomas and Andy Hunt.&lt;/p&gt;

&lt;p&gt;Running the book club &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup a recurring calendar invite &lt;/li&gt;
&lt;li&gt;A Github wiki to keep track of the discussions.&lt;/li&gt;
&lt;li&gt;Inform ahead to the participants which chapter will be in discussion.&lt;/li&gt;
&lt;li&gt;We encourage everyone to go through the chapters, so that everyone is in line with the topics that will be discussed in the book club sessions. This allows conversation and discussion to flow more smoothly. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Learnings: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We would encourage active participation by encouraging questions in the middle of the session.&lt;/li&gt;
&lt;li&gt;Create a page, in which participants can propose new books for the book club. &lt;/li&gt;
&lt;li&gt;One person leading the talk normally does not work,  participants will rely too much on the lead to delivery book’s content rather than reading the content themselves.&lt;/li&gt;
&lt;li&gt;Active participation, where participants should bring up topics they found interesting in the chapter. &lt;/li&gt;
&lt;li&gt;Generate follow-up discussion in Slack channel participants can post interesting blogs, videos, papars that related to the day.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some of the books which are currently in our list. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Seven Databases in Seven weeks&lt;/li&gt;
&lt;li&gt;99 Bottles by Sandi Metz&lt;/li&gt;
&lt;li&gt;Structure and Interpretation of Computer Programs &lt;/li&gt;
&lt;li&gt;Design patterns in Ruby &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conclusion&lt;br&gt;
Book clubs are a great way to level up your team, and encourage healthy discussion between members. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Ruby on Rails Graphiti file attachment/file upload</title>
      <dc:creator>Andy Chong</dc:creator>
      <pubDate>Sun, 29 Dec 2019 15:09:25 +0000</pubDate>
      <link>https://dev.to/postco/ruby-on-rails-file-attachment-with-graphiti-resource-77i</link>
      <guid>https://dev.to/postco/ruby-on-rails-file-attachment-with-graphiti-resource-77i</guid>
      <description>&lt;p&gt;I have been using &lt;a href="https://www.graphiti.dev/guides/" rel="noopener noreferrer"&gt;Graphiti&lt;/a&gt; gem to build the API for the upcoming product in PostCo. While it is great that it makes building &lt;a href="https://jsonapi.org/" rel="noopener noreferrer"&gt;JSON:API&lt;/a&gt; compliant API endpoints a breeze, and made API resource the first-class citizen, it still quite lacks some important features, which includes file attachment support. I will talk about Graphiti in some other time but right now lets dive into today's topic.&lt;/p&gt;

&lt;p&gt;In this article, you will understand how to add the file attachment functionality into the Graphiti resource. I will cover 2 of the most popular file attachment libraries recently, &lt;a href="https://edgeguides.rubyonrails.org/active_storage_overview.html" rel="noopener noreferrer"&gt;Active Storage&lt;/a&gt; and &lt;a href="https://shrinerb.com/" rel="noopener noreferrer"&gt;Shrine&lt;/a&gt;, and I will be uploading the file in Base64 string format.&lt;/p&gt;

&lt;p&gt;Assuming the User model file looks something like this, where it contains 2 attachments, an avatar photo, and an ID card photo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# some other codes&lt;/span&gt;
  &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:id_card&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;

  &lt;span class="c1"&gt;## Active Storage&lt;/span&gt;
  &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;  
    &lt;span class="n"&gt;has_one_attached&lt;/span&gt; &lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# or&lt;/span&gt;
  &lt;span class="c1"&gt;# has_one_attached :avatar&lt;/span&gt;
  &lt;span class="c1"&gt;# has_one_attached :id_card&lt;/span&gt;

  &lt;span class="c1"&gt;## Shrine&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ImageUploader&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attachment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:avatar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ImageUploader&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Attachment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:id_card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# some more codes&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;span class="c1"&gt;## Shrine&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ImageUploader&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Shrine&lt;/span&gt;
  &lt;span class="n"&gt;plugin&lt;/span&gt; &lt;span class="ss"&gt;:data_uri&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Write
&lt;/h3&gt;

&lt;p&gt;During &lt;em&gt;POST&lt;/em&gt; and &lt;em&gt;PUT&lt;/em&gt; API call, the Graphiti Resource will assign all the submitted attributes and save it. But both file attachment libraries do not support attaching files by assigning the attribute.&lt;/p&gt;

&lt;p&gt;Therefore, we need to extract the attachment data out from the submitted attributes and attach them separately. Luckily, Graphiti exposes the &lt;a href="https://www.graphiti.dev/guides/concepts/resources#persistence-lifecycle-hooks" rel="noopener noreferrer"&gt;persistence lifecycle hooks&lt;/a&gt; to allow developers to add in additional logic during persisting the data.&lt;/p&gt;

&lt;p&gt;To achieve the goal, we overwrite the &lt;code&gt;assign_attributes&lt;/code&gt; to do exactly what we need to, extract the attachment data and assign them separately!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserResource&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationResource&lt;/span&gt;

  &lt;span class="c1"&gt;# some other codes...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assign_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attach_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_pair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;attach_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;## Active Storage&lt;/span&gt;
      &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;data: &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;## Shrine&lt;/span&gt;
      &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_data_uri="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_attachments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# some more codes&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Read
&lt;/h3&gt;

&lt;p&gt;To return the attachment's URL when reading, we simply check each attachment and return the URL if it is available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserResource&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationResource&lt;/span&gt;

  &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;## Active Storage&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attached?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;rails_blob_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only_path: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;

      &lt;span class="c1"&gt;## Shrine&lt;/span&gt;
      &lt;span class="vi"&gt;@object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_url"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# other attributes...&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;writable: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;writable: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;

  &lt;span class="c1"&gt;# some other codes...&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Here's what the final Resource code will look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserResource&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationResource&lt;/span&gt;

  &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;## Active Storage&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attached?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;rails_blob_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;only_path: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;

      &lt;span class="c1"&gt;## Shrine&lt;/span&gt;
      &lt;span class="vi"&gt;@object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_url"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;# other attributes...&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;writable: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:updated_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;writable: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assign_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;extract_attributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attach_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_pair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;attach_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;## Active Storage&lt;/span&gt;
      &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;data: &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;## Shrine&lt;/span&gt;
      &lt;span class="n"&gt;model_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;attribute&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_data_uri="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_attachments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ATTACHMENT_ATTRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;attachments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;attachment_attr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attachment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;present?&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;attachments&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And Voilà! Now you can upload attachments through the Graphiti API!&lt;/p&gt;

&lt;p&gt;If you find this article is useful, please do give a ❤️! If you have any questions or suggestions, please do comment in the discussion area below!&lt;/p&gt;

</description>
      <category>activestorage</category>
      <category>shrine</category>
      <category>rails</category>
      <category>graphiti</category>
    </item>
  </channel>
</rss>
