<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Paul Franzen on Medium]]></title>
        <description><![CDATA[Stories by Paul Franzen on Medium]]></description>
        <link>https://medium.com/@paul.franzen?source=rss-6cc102ffa702------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*Ch818TT400r-qTlH.</url>
            <title>Stories by Paul Franzen on Medium</title>
            <link>https://medium.com/@paul.franzen?source=rss-6cc102ffa702------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 17:29:18 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@paul.franzen/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[5 steps for fearless refactoring]]></title>
            <link>https://medium.com/wework-engineering/5-steps-for-fearless-refactoring-3d6e77e17672?source=rss-6cc102ffa702------2</link>
            <guid isPermaLink="false">https://medium.com/p/3d6e77e17672</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[refactoring]]></category>
            <category><![CDATA[rails]]></category>
            <dc:creator><![CDATA[Paul Franzen]]></dc:creator>
            <pubDate>Thu, 07 Jun 2018 15:03:13 GMT</pubDate>
            <atom:updated>2023-04-21T15:39:58.628Z</atom:updated>
            <content:encoded><![CDATA[<p>You’ve just been paroled from your bi-weekly planning session and you’re frothing at the mouth to Write. Some. Code. You snatch the juiciest ticket from the top of your Jira board and start digging.</p><blockquote><em>There’s too much logic in this controller? This model has callbacks </em><strong><em>and</em></strong><em> observers?! Line 340 doesn’t seem to do anything at all. What am I looking at?</em></blockquote><p>The sweat beads on your upper lip. You already assigned that task to yourself.</p><blockquote><em>Take my name off it, pretend it never happened. No one will notice.</em></blockquote><p>Sweeter temptations.</p><blockquote><em>I can fulfill this ticket with only a couple of lines of code! It would be irresponsible to spend so much time on this when we can provide the user all the value with 1/10th the effort.</em></blockquote><p>Out of the corner of your eye, you see the intern: Jessie. So young. So naive. So idealistic. What will they say when they see your PR? What kind of world are you leaving them? A world not worth living in? Not worth <strong>coding</strong> in?</p><blockquote><em>No! I can do better. Be better. I’ll see this through to the bitter end!</em></blockquote><p>So, how do we eat this elephant?</p><blockquote><em>One bite at a time!</em></blockquote><p>Exactly! Here’s your playbook:</p><ol><li><strong>Fully understand the code</strong>. State of mind is the key to success. Its difficult, but keep try thinking <em>curiously, </em>instead of<em> judgmentally. </em>Follow every rabbit hole, summon your limited social skills and actually talk to those whose names turn up on git blame. <em>You know this is a mess and you’re doing god’s work to improve it, so whats the point of getting all worked up?</em></li><li><strong>Write the tests first</strong>. Now that you understand the code, write and/or refactor the tests. Having proper test coverage will deepen your understanding of the nuances of the code and give you <em>the confidence to make changes.</em></li><li><strong>Code review early and often</strong>. The temptation to turn this into a Christmas morning for the team will be high, don’t opt for the big reveal, keep the lines of communication open. <em>Make sure the rest of the team sees progress early, and often.</em></li><li><strong>Test and deploy your changes <em>without</em> the new feature</strong>. I know, I know, the whole point of this was the new feature, but make sure the more readable, more maintainable and more scalable code<em> actually</em> <em>works</em>.</li><li><strong>Write the feature</strong>. You did your job right, the new code is substantially more elegant and the task is easier to <em>complete, test and deploy.</em></li></ol><p>You did it! the repo is now in a better state than when you started, users have added value and the team is now faster and more agile than before.</p><p>Years from now, after you’ve passed into that great middle management team in the sky. Jessie will update the code to conform to the PanAsianEuroUnion’s privacy requirements, and they’ll ask their IDE’s AI, “Who wrote this?” And your name will be echo through the halls of Valhalla.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3d6e77e17672" width="1" height="1" alt=""><hr><p><a href="https://medium.com/wework-engineering/5-steps-for-fearless-refactoring-3d6e77e17672">5 steps for fearless refactoring</a> was originally published in <a href="https://medium.com/wework-engineering">WeWork</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Freeze Tag: A gem for a more “stateless” tagging experience]]></title>
            <link>https://medium.com/wework-engineering/introducing-freeze-tag-a-gem-for-a-more-stateless-tagging-experience-df1617e3d125?source=rss-6cc102ffa702------2</link>
            <guid isPermaLink="false">https://medium.com/p/df1617e3d125</guid>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[tagging]]></category>
            <category><![CDATA[gem]]></category>
            <category><![CDATA[stateless]]></category>
            <dc:creator><![CDATA[Paul Franzen]]></dc:creator>
            <pubDate>Wed, 18 Apr 2018 20:21:59 GMT</pubDate>
            <atom:updated>2023-04-21T15:41:43.495Z</atom:updated>
            <content:encoded><![CDATA[<p>Check it out on Github: <a href="https://github.com/wework/freeze-tag">https://github.com/wework/freeze-tag</a></p><p>For as long as I can remember, the de facto tagging library for almost every Ruby on Rails project has been <a href="https://github.com/mbleigh/acts-as-taggable-on">Acts As Taggable On Gem</a> which provides a simple interface to polymorphic-ally tag your models.</p><p>As excellent as acts-as-taggable-on is, <a href="https://github.com/wework/freeze-tag">FreezeTag</a> offers some unique features which you may consider when choosing how to implement tagging in your project.</p><ol><li>FreezeTag allows for a more “stateless” approach to tagging; tags are never deleted, instead they have an “expired_at” column, which is updated to make them inactive.</li><li>The associations are simpler; tags are held in a single table which holds the content of the tag (its name), any list it is attached to, and the association back to the model instance its attached to, which has some advantages including simpler querying, joining, etc.</li></ol><h4>Installation</h4><p>Add this line to your application’s Gemfile:</p><pre>gem &#39;freeze_tag&#39;</pre><p>And then execute:</p><pre>$ bundle</pre><p>Create the tables:</p><ol><li>Run the installer:</li></ol><pre>$ rails g freeze_tag:install</pre><p>This adds a migration to create your “freeze_tags” table</p><ol><li>Confirm your implementation.</li></ol><p>Since Freeze tags creates a polymorphic association between tags and models, its necessary to confirm the type of primary keys the models in your application use. Open the migration and choose the correct option for you.</p><p>2. Run the migration</p><pre>rake db:migrate</pre><p>3. Add:</p><pre>include FreezeTag::Taggable</pre><p>to the top of any model you’d like to start tagging.</p><p>4. Case sensitivity, add:</p><pre>def self.freeze_tag_case_sensitive<br>  true<br>end</pre><p>To your model. All tags, for that model, will be saved as lowercase</p><h4>Tagging a record:</h4><p>A single tag:</p><pre>my_model_instance.freeze_tag(as: &quot;Fancy&quot;)</pre><p>Or apply multiple tags:</p><pre>my_model_instance.freeze_tag(as: [&quot;Fancy&quot;, &quot;Schmancy&quot;])</pre><p>Or apply multiple tags and expire all other ones:</p><pre>my_model_instance.freeze_tag(as: [&quot;Fancy&quot;, &quot;Schmancy&quot;], expire_others: true)</pre><p>There may be times you want multiple lists of tags, i.e. users with skills, AND hobbies:</p><p>All the same methods above work, simply pass a list as an argument.</p><pre>my_model_instance.freeze_tag(as: &quot;Web Design&quot;, list: &quot;Skills&quot;)</pre><p>You can also use the same style/attributes to tag while creating instances</p><pre>my_model_instance = MyModel.new(name: &quot;MyModelName&quot;, freeze_tagged: [{<br>  as: [&quot;Cool&quot;, &quot;Beans&quot;],<br>  list: &quot;Ideas&quot;,<br>  expire_others: true<br>}])</pre><pre>my_model_instance.save</pre><h4>Accessing tags:</h4><p>All the current “active” tags as a simple array of strings.</p><pre>my_model_instance.freeze_tag_list<br>[&quot;Happy&quot;, &quot;Go&quot;, &quot;Lucky&quot;]</pre><p>All the tags as a simple array of strings.</p><pre>my_model_instance.freeze_tag_list(only_active: false)<br>[&quot;Happy&quot;, &quot;Go&quot;, &quot;Lucky&quot;, &quot;Sad&quot;]</pre><p>All the tags, in a list, as a simple array of strings.</p><pre>my_model_instance.freeze_tag_list(list: &quot;Skills&quot;)<br>[&quot;Web Design&quot;, &quot;Illustration&quot;]</pre><p>Active Record association of all tags</p><pre>my_model_instance.freeze_tags</pre><p>Active Record association of all “active” tags</p><pre>my_model_instance.active_freeze_tags</pre><p>You can change queries to the above to filter by anything.</p><pre>my_model_instance.freeze_tags.where(list: &quot;Skills&quot;)<br>my_model_instance.active_freeze_tags.where(list: &quot;Skills&quot;)</pre><h4>Retrieving records that have been tagged:</h4><p>Currently tagged with (only unexpired)</p><pre>MyModel.freeze_tagged(as: &quot;Fancy&quot;)</pre><p>Previously tagged with (only expired)</p><pre>MyModel.previously_freeze_tagged(as: &quot;Fancy&quot;)</pre><p>Ever tagged with (expired and unexpired)</p><pre>MyModel.ever_freeze_tagged(as: &quot;Fancy&quot;)</pre><p>All the above methods work with a “list” argument as well</p><pre>MyModel.ever_freeze_tagged(as: &quot;Fancy&quot;, list: &quot;Skills&quot;)</pre><h4>Accessing the model directly.</h4><pre>FreezeTag::Tag</pre><p>Will give you direct access to the freeze tags table in a very standard way.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=df1617e3d125" width="1" height="1" alt=""><hr><p><a href="https://medium.com/wework-engineering/introducing-freeze-tag-a-gem-for-a-more-stateless-tagging-experience-df1617e3d125">Introducing Freeze Tag: A gem for a more “stateless” tagging experience</a> was originally published in <a href="https://medium.com/wework-engineering">WeWork</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build your own chat-bot using AWS Lex and Ruby on Rails]]></title>
            <link>https://medium.com/wework-engineering/build-your-own-chat-bot-using-aws-lex-and-ruby-on-rails-58da37d106ea?source=rss-6cc102ffa702------2</link>
            <guid isPermaLink="false">https://medium.com/p/58da37d106ea</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[chatbots]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[aws-lex]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Paul Franzen]]></dc:creator>
            <pubDate>Wed, 10 Jan 2018 20:53:32 GMT</pubDate>
            <atom:updated>2023-04-21T15:42:46.996Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>TLDR; If you don’t want to go through all this trouble, and think you’ve got a handle on both Lex and RoR, you can skip directly to the <a href="https://github.com/wework/lex_faq">sample repo</a>, and kick the tires! Live on the web <a href="https://ww-lex-faq.herokuapp.com/">here</a>.</blockquote><p>Oh Amazon! The great provider of same-day-toilet-paper, second-day-flat-screen-TVs and most improbably: <a href="https://aws.amazon.com/">Amazon Web Services</a>. Amazon’s commitment to <a href="https://en.wikipedia.org/wiki/Service-oriented_architecture">Service-oriented-architecture</a> has allowed them to make their in-house technologies available to less gargantuan engineering organizations.</p><p>This devotion to SOA has had some unforeseen consequences. Most notably the wacky, glitchy and sometimes painful UX that comes in the admin area of your AWS services console.</p><p>A more <em>experts-only </em>space<em> </em>is hard to imagine. Poking around here is likely to cause grief for you, your systems’ administrators, your security team and anyone else who considers themselves “DevOps” or “InfoSec”.</p><p><strong>In other words, don’t expect a simple interface to make a simple, functional chat bot.</strong></p><p>This brings us to the subject of this post: How to make, <a href="https://aws.amazon.com/lex">Lex</a>, the natural language processing service, one of the newest, sexiest services, the service that powers Alexa, something you can <em>actually use</em>. This tutorial aims to get you started with an app which will act as an interface to manage a simple, FAQ style powered by Lex bot.</p><h3>Part I: Create &amp; configure your Lex bot</h3><ol><li>Login to your AWS console and navigate to the Lex interface</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/1*YdyngkoUUX0oL09pY9JiPA.png" /></figure><p>2. Create a bot</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/402/1*XHpYaSccmKZRsKWZ_1eroQ.png" /><figcaption>Click on the blue “Create” button to get started</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/956/1*zUwMqqLpAt1HohitLSIFdw.png" /><figcaption>You’ll want to choose a custom bot, instead of using sample (the 3 to 1 choice of samples bots vs a custom bots, gives you an idea of just how new this service / technology is)</figcaption></figure><p>2.1. Give your bot a name, consider using “TestFAQ” which will allow you to follow this tutorial very closely.</p><p>2.2. Choose a voice, this bot functions as text-only, so it doesn’t really matter.</p><p>2.3. Choose a <a href="http://docs.aws.amazon.com/lex/latest/dg/context-mgmt.html#context-mgmt-session-timeout">session timeout</a>. I recommend keeping the default 5 minutes.</p><p>2.4. AWS helpfully chooses the IAM role, so no worries there.</p><p>2.5. Finally, since this example is not intended for children, we leave the “No” checked for COPPA.</p><p>2.6. Now click “Create”, like a boss.</p><h3>Part II: Create an IAM service account</h3><p>Your app will need programmatic access to AWS Lex in order to do its job.</p><blockquote>NOTE: AWS Identity and Access Management (IAM) enables you to securely control access to AWS services and resources for your users. Using IAM, you can create and manage AWS users and groups, and use permissions to allow and deny their access to AWS resources.</blockquote><ol><li>Navigate to the IAM service</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/679/1*1DL2ONfxVvUfUlioslpFmA.png" /><figcaption>Use the autocomplete to access IAM</figcaption></figure><p>2. Select Users from the side menu, then click the “Add user” button</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/289/1*rBlejQvf-nmBg8wEO4DTLg.png" /></figure><p>3. Name and allow programatic access for the service account</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*akA9qK26zuWHLewTklxhdg.png" /></figure><p>4. Give the account the AmazonLexFullAccess Policy</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cQUQIJog04jUJ2T_9FW-sQ.png" /></figure><p>5. Finally review and create the account. Then grab the account’s <a href="https://docs.aws.amazon.com/general/latest/gr/managing-aws-access-keys.html">Access ID and Secret Access Key</a>. Store them somewhere secure for later access :-)</p><h3>Part III: The Ruby on Rails backend</h3><p>1. Clone this <a href="https://github.com/wework/lex_faq">GitHub repository</a>. This sample app contains lots of simple code to kick-start your project. You should consider all of this code boilerplate and don’t put too much stock in its structure or patterns. <em>Make it your own</em>.</p><p>2. Get it up and running in typical Rails fashion.</p><p>3. Set up the following environment variables using the aforementioned services account:</p><pre>ENV[&#39;LEX_FAQ_AWS_ACCESS_ID&#39;] # From above<br>ENV[&#39;LEX_FAQ_AWS_SECRET_ACCESS_KEY&#39;] # From above<br>ENV[&#39;LEX_FAQ_AWS_REGION&#39;] # &#39;us-east-1&#39; or where you are :-)<br>ENV[&#39;LEX_FAQ_ADMIN_NAME&#39;] # Basic Auth Name for admin panel<br>ENV[&#39;LEX_FAQ_ADMIN_PASSWORD&#39;] # Duh</pre><p>4. Create your first Answer via the console.</p><pre>$ rails c<br>a = Answer.new<br>a.name = &quot;First Answer Response&quot;<br>a.utterances = [&quot;Whats your favorite programming language?&quot;, &quot;What do you like to program in?&quot;]<br>a.response = &quot;I like Javascript and Python, but Ruby is my favorite.&quot;<br>a.save</pre><p>5. The answer model contains the code responsible for pushing to Lex:</p><pre>def push_to_lex <br>  begin<br>    data = { <br>      name: self.lex_mapped_intent_name,<br>      description: self.name,<br>      sample_utterances: self.utterances,<br>      fulfillment_activity: {<br>        type: &quot;ReturnIntent&quot;<br>      },<br>    }</pre><pre>    resp = CLIENT.get_intent({<br>      version: &quot;$LATEST&quot;, <br>      name: self.lex_mapped_intent_name<br>    }) rescue nil</pre><pre>    checksum = resp.try(:checksum)</pre><pre>    if checksum.present?<br>      data[:checksum] = checksum<br>    end</pre><pre>    CLIENT.put_intent(data)</pre><pre>    bot = Lex::Bot.current<br>    bot.attach_answer_as_intent!(self)<br>  rescue =&gt; error<br>    puts &quot;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; #{error.inspect}&quot;<br>  end<br>end</pre><p>5.1. <strong>Breakdown</strong>: The data hash A simplified version of the payload outlined <a href="https://docs.aws.amazon.com/lex/latest/dg/API_PutIntent.html">here</a>.:</p><pre>data = { <br>  name: self.lex_mapped_intent_name,<br>  description: self.name,<br>  sample_utterances: self.utterances,<br>  fulfillment_activity: {<br>    type: &quot;ReturnIntent&quot;<br>  }<br>}</pre><p>5.2. <strong>Breakdown</strong>: Does this already exist?</p><pre>resp = CLIENT.get_intent({<br>  version: &quot;$LATEST&quot;, <br>  name: self.lex_mapped_intent_name<br>}) rescue nil</pre><pre>checksum = resp.try(:checksum)</pre><pre>data[:checksum] = checksum if checksum.present?</pre><p>Checks to see if this intent already exists. If it does, it pulls the <a href="https://docs.aws.amazon.com/lex/latest/dg/API_PutBotAlias.html#API_PutBotAlias_RequestSyntax">checksum</a> and attaches it to the above payload. This updates the intent, instead of trying to create one with a conflicting name.</p><p>5.3. <strong>Breakdown</strong>: Put it:</p><pre>CLIENT.put_intent(data)</pre><blockquote>NOTE: There is <strong>a lot</strong> more code in the bot and answer models that makes this work, so take a peek, the source is commented</blockquote><p>6: Now <em>actually</em> push your Answer to lex</p><pre>a.push_to_lex</pre><p>7. Back to Lex, Use the auto-complete to navigate back to your Lex Web Interface.</p><p>7.1. Confirm your answer has been pushed and appears as an intent on your bot</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tmir9OC-yif90ioJkEjhRQ.png" /><figcaption>Your intent should appear here with the same name as your <strong>lex_mapped_intent_name</strong> that your Answer has locally. The <strong>Sample utterances</strong> should also match up to what you created locally.</figcaption></figure><p>7.2. Build your bot:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sT3bHY0IxpuqS4CazsmvJw.png" /><figcaption>Click the build button, and follow the prompt</figcaption></figure><p>You can also build your bot via your Rails app by running:</p><pre>Lex::Bot.current.build!</pre><p>It can take several minutes for AWS to finish the build process.</p><blockquote>NOTE: You won’t be able to “publish” your Bot until the build process is completed.</blockquote><p>7.3. Publish your Bot:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_3jAlbZScFd_54W2XFdXnQ.png" /><figcaption>Clicking publish shows the versions modal</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F_GMY4CdpEAWzX-o67byFw.png" /><figcaption>For the purposes of this demo application, just create an alias called “alpha” and continue to publish over that.</figcaption></figure><p>You can also publish your bot via your Rails app by running:</p><pre>Lex::Bot.current.publish!</pre><h3>Part IVa: The Rails front-end, User-facing</h3><p>The sample app also includes a simple interface for potential users. So, if you haven’t already, start up your rails server and navigate to <a href="http://localhost:3000/">http://localhost:3000/</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/369/1*x-M2p7Tooyiwgn8OYKEtAQ.png" /><figcaption>Now you have a <strong>basic</strong> interface to interact with your bot and if you type one of the questions you put in the utterances…</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/338/1*6gTpftcl5OKmhNu4da2BNg.png" /><figcaption>TADA!!! You’ll see that Lex’s NLP allows for typing a “similar” string and figures out what the user “probably” meant.</figcaption></figure><h3>Part IVb: The Rails front-end, admin interface</h3><p>The second part of the front-end is the admin interface. Navigate to <a href="http://localhost:3000/admin/answers">http://localhost:3000/admin/answers</a> and enter the admin name and password you set in Part III, Step 3.</p><p>1. The admin home screen: A simple list of all the answers you’ve created.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uKEInLnPMMyW2OAApNOk6Q.png" /><figcaption>Should display the answer you created through the console.</figcaption></figure><p>2. Create a new answer via the admin interface.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PCqfymQGWUB3i6txUTSSVA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*18Kqng1f0GT4Z0AeecWuQw.png" /><figcaption>Follow the form to create a new answer</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*16GLxYm5JT9OspJYUmjbdA.png" /><figcaption>You’ll be redirected back to the admin home page</figcaption></figure><p>3. Back to the Lex Screen:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VkqCXDtEIJ2ao7gUQIMxTw.png" /><figcaption>Navigate back to your Lex bot page you’ll see that your new answer has been added to the intent!</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V0J21WdjSgL4gcGv2bBhHg.png" /><figcaption>Now follow the instructions to build and publish the bot!</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/331/1*iYwNzgpJvWM8vYiVcbuBSw.png" /><figcaption>Now return to your client (you may have to clear your userID from localStorage to make it work instantly) and ask it… TADA!!!!</figcaption></figure><h3>Part V: The data flow</h3><ol><li>Text, a user_id, and an auth token are submitted from the client to your Rails app</li><li>The Rails app uses the <a href="https://aws.amazon.com/sdk-for-ruby/">AWS Ruby SDK</a> to construct the appropriate payload and submit the text to Lex.</li><li>Lex processes the input and returns an “intent_name” in its payload.</li><li>The Rails app looks up an “Answer” based on the aforementioned intent_name.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/778/1*cprL-O-p5R2LSWeiJNGrqg.png" /></figure><h3>Conclusion</h3><p>I hope you found this tutorial helpful and you take from it inspiration to do even crazier things using Amazon’s incredibly powerful services including Lex.</p><p>Interested in joining our team? WeWork is hiring software engineers in Tel-Aviv and New York. <a href="https://www.wework.com/careers/search?department=Digital"><strong><em>View openings</em></strong></a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=58da37d106ea" width="1" height="1" alt=""><hr><p><a href="https://medium.com/wework-engineering/build-your-own-chat-bot-using-aws-lex-and-ruby-on-rails-58da37d106ea">Build your own chat-bot using AWS Lex and Ruby on Rails</a> was originally published in <a href="https://medium.com/wework-engineering">WeWork</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>