<?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: shakycode</title>
    <description>The latest articles on DEV Community by shakycode (@shakycode).</description>
    <link>https://dev.to/shakycode</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%2Fuser%2Fprofile_image%2F2688%2F13086902.jpeg</url>
      <title>DEV Community: shakycode</title>
      <link>https://dev.to/shakycode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shakycode"/>
    <language>en</language>
    <item>
      <title>Blake the Onshore/Offshore Programmer</title>
      <dc:creator>shakycode</dc:creator>
      <pubDate>Wed, 22 Feb 2017 00:33:53 +0000</pubDate>
      <link>https://dev.to/shakycode/blake-the-onshoreoffshore-programmer</link>
      <guid>https://dev.to/shakycode/blake-the-onshoreoffshore-programmer</guid>
      <description>&lt;p&gt;If you've read my previous post The &lt;a href="https://shakycode.com/the-story-of-the-fraudulent-coder-d4c6fcf273f7#.4mo0p2zct"&gt;Story of the Fraudulent Coder&lt;/a&gt; you know that I have little to no tolerance for bullshit. This is another developer war story that I'd like to share with you. For the sake of anonymity I will be calling this programmer, Blake. Everything else in the story is a true tale of major pain and conflict, ok that sounds dramatic, but just bare with me.&lt;/p&gt;

&lt;p&gt;So I was working for an awesome startup and we had a “Senior” programmer by the name of, “Blake”. Blake was a very polite guy who just happened to be on a H1-B Visa from overseas (India). We hired him with the intent to bring a stronger level of technical acumen onto our team since he had nearly 10 years of software development experience and 8 years of Ruby and Rails. We thought he would be an amazing addition to our team which really needed the help.&lt;/p&gt;

&lt;p&gt;At the time our company was a 100% distributed team which meant we worked from everywhere and anywhere just as long as the work got done. We kept in communication via Squiggle to do video conferencing and chat and all was well in the beginning. &lt;/p&gt;

&lt;p&gt;Blake was very quiet and was really hard to connect with as he always seemed to have something going on in his personal life. We initially dismissed this as being normal human nature as hey we all have shit going on but it's all about how you manage it. But after working alongside Blake for a month I started to notice some patterns and red flags.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #1 (Missing in Action)
&lt;/h4&gt;

&lt;p&gt;We kept lenient working hours but the majority of us were required to be online from 10:00 to 17:00 central time. Normally we would have our daily standup to start our sprint but most of the time Blake would have connectivity issues and not join our video conferences. He claimed to be on Google Fiber, but he was supposedly on the East Coast at the time and Google does not offer Fiber in his area. We would watch him bounce on and offline all day long. Part of working in a distributed team is having solid network access so that we can keep working and collaborate. We would see Blake online via Squiggle but whenever we reached out to him we'd either get no response or a canned messaged such as, “I'm analyzing this problem, I will report my findings later tonight”. The funny part was, there were no problems to be analyzed, he was doing basic programming tasks and simple debug triage which should take 1–2 hours max even for a newcomer much less a senior developer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #2 (Gender Changing Baby)
&lt;/h4&gt;

&lt;p&gt;Blake was a father to a newborn daughter so often had to step away and tend to his child while his wife was at work. This was not a problem for us as many of us multi-tasked while getting work done. In talks with Blake we asked him if he had a big family and he said, “nope just my wife and daughter”.&lt;/p&gt;

&lt;p&gt;A month later Blake didn't show up for work and we got a frantic email stating that his baby son had to go to the hospital because he was running a high fever so he would not be able to work today. My boss didn't catch it but I noticed that somehow his newborn daughter changed genders. Throughout our time with Blake he would switch between referring to his “son” and “daughter” when in fact he told us he only had one child which was a girl. Really whacky shit, but it gets worse.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #3 (No Daytime Work)
&lt;/h4&gt;

&lt;p&gt;We had a policy in place that we would be available during normal business hours to support our customers but we were flexible enough to where if you needed to duck out or take a break you could. We never encouraged our employees to work after-hours but many of us did because we were passionate about the work and vision. But we began to see a pattern emerge with Blake.&lt;/p&gt;

&lt;p&gt;During daytime hours (roughly 7–8 hours) we would not hear from Blake whatsoever. We'd ping him on Squiggle or Slack and he'd not respond. Hours later in the afternoon we'd get the typical response of “I'm analyzing the problem and will have answers tonight”.&lt;/p&gt;

&lt;p&gt;During the 3 months that we worked with Blake we never saw one commit during daytime hours. All commits were between 21:00–22:00 while the rest of us were steadily committing code during daytime hours and sometimes in the evenings. It's as if this guy was nocturnal. It ended up becoming a major problem because he was never available when the rest of the team was online and mid-sprint.&lt;br&gt;
This was really suspicious and as you will read later on we found out why this was.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #4 (My Wife's Car Broke Down)
&lt;/h4&gt;

&lt;p&gt;We were in the middle of an extremely tight deadline and we were counting on Blake to help us ship this feature. Myself and 3 other developers were handling most of the work with Blake running point on the feature sprint. He supposedly had some code to commit and we were running out of time to ship. We put the pressure on him the day of the deadline and he emailed us, “Guys, my wife's oil cap came off of her car on the freeway and she is stranded so I can't work today as I have to get the car towed and get her to work”.&lt;/p&gt;

&lt;p&gt;Um hello. Ever heard of AAA? Hell, 99% of auto insurance companies come with some form of roadside assistance. I mean it would be different if his wife was in a horrific accident and he needed to be here. But seriously her car broke down and she could have easily called a tow truck. Instead Blake decided that he needed to take care of it.&lt;/p&gt;

&lt;p&gt;We all felt this was a bullshit excuse and we simply took over his portion of the work and shipped without him meanwhile almost meeting our deadline. But really this was not a feasible excuse and sounded like some sort of bullshit made-up story. We were all suspicious of him from that point forward.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #5 (NodeJS/Cross Site Scripting)
&lt;/h4&gt;

&lt;p&gt;We were working on a new API that would help us better aggregate and normalize data. Our app was monolithic and was installed on several different servers (one per customer) so we had to introduce this API into the codebase and pass parameters to it so that it would transmit data from the proper organization that the app instance belonged to (i.e. Acme Company).&lt;br&gt;
During the development of the API Blake said that our API was subject to Cross Site Scripting and that we absolutely must use NodeJS to prevent the XSS attacks from happening.&lt;/p&gt;

&lt;p&gt;Now I'm not a NodeJS developer but I know enough to know that introducing a full blown MVC JavaScript framework would not prevent XSS attacks and that this was something that we would have to handle internally via Rails. Come to find out there was no attack vector surfaced that would result in a XSS attack. We found this very odd and he kept pushing for NodeJS. Not wanting to bloat our tech stack and having zero need for Node we pushed back and said NO to Node, handle it in Rails. His response was, “I cannot be held responsible for the open vulnerability in our application and API”.&lt;/p&gt;

&lt;p&gt;The funny thing is we sourced a very reputable security company to attack our staging server which ran the API and Rails framework and they were not able to execute a XSS attack or any successful attack besides a DDoS.&lt;/p&gt;

&lt;p&gt;So where he came up with the notion that NodeJS would solve a XSS attack vector I have no clue. We brought this up to our CTO and he was not happy because progress was not being made and said, “Fuck Node, we're sticking with Rails and the API we are building”. Still weird as shit.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #6 (Race Condition)
&lt;/h4&gt;

&lt;p&gt;I was tackling a scaling problem at the time which was basically a SQL stored procedure that computed a scoring-based algorithm in realtime. This was happening during a page load and on clients with many users page load times would be in excess of 1–2 minutes which is entirely unacceptable. So I decided that we didn't really need realtime score calculations on every single subject in the database and decided to move it into a Sidekiq Worker (Background job) that would fire every 3 minutes outside of the request which ended up resulting in &amp;gt; 400ms response times on page loads and “good enough” realtime scoring data.&lt;/p&gt;

&lt;p&gt;When I assigned the PR to Blake he rejected it and said that I'm introducing a race condition by not calculating in realtime. He went on to say that we would experience database deadlocks if we moved the scoring work to a background worker.&lt;/p&gt;

&lt;p&gt;Knowing what I know about our codebase and race conditions this made zero sense whatsoever. So myself and another developer jumped his head and went to our CTO and told him about the situation. Blake was put on the spot by the entire team asking for an explanation of his race condition and deadlock theory but all he could come up with was, “I'm still analyzing the problem but will have a solution by tonight”.&lt;br&gt;
If it smells like bullshit, it probably is.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #7 (The 1 month Flu)
&lt;/h4&gt;

&lt;p&gt;Blake had many excuses for not showing up to work or shipping code when we were trying to meet deadlines, however one in particular struck me as odd. One day Blake emailed us and said he had the flu and would not be able to work today. We wished him well and didn't hear from him for a week. We finally reached out again via email as he would not answer his phone and he responded that he was still sick and could not work. The funny thing was his wife was supposedly an ER doctor so she could have easily prescribed him some Tamiflu or other antiviral early on to combat the flu. I even asked him if his wife could prescribe him something and he said no because she was at work and couldn't be reached. This was very odd to me that he couldn't text his wife and have her write our a prescription for medication or have one of her physician colleagues do so. Or better yet, Blake could have simply sucked it up and driven to an urgent care clinic for treatment.&lt;/p&gt;

&lt;p&gt;A few weeks passed and we finally got Blake on Squiggle for a video chat and he looked healthy as can be but kept a box of kleenex nearby even though his nose wasn't running. He would cough a lot but you could tell they were forced coughs and not a true symptom of illness. Now I'm not a doctor by any means but I know that a typical strain of influenza treated at home usually lasts 14 days max before it peters out. After 4 weeks Blake was magically “recovered” and asked what needed to be done. Sorry dude, we've been cranking out code for a month without you. Meanwhile you've been paid (extremely well) and have contributed zero to the team.&lt;/p&gt;

&lt;h4&gt;
  
  
  Red Flag #7 (I Can't Pair With You)
&lt;/h4&gt;

&lt;p&gt;Being a distributed team meant we were heavy on pair programming. In my 3 months of working with Blake I paired with him once and it was really him just looking at code and then cutting me off and saying, “I need to analyze the problem, I will get back to you”. Now we're talking about small bugs like NILClass issues or data that wasn't normalized or simple 4 line functions that just needed a 5 minute refactoring to pass our test suite. Nothing major.&lt;/p&gt;

&lt;p&gt;He would only pair using Teamviewer which is available on all platforms but we were an Apple shop and we gave brand new Macbooks to every employee including Blake so that we could use pairing tools such as ScreenHero to keep the productivity going. Blake refused to use the Macbook and always came up with an excuse that it was crashing on him and it didn't work. We even replaced his Macbook twice and he still complained that it didn't work. So the end result was we never got to pair with Blake and that was really the antithesis of our culture. It should be noted that Blake had an Ubuntu and Windows desktop that he would work on, both of these were NOT approved by our CTO due to security restrictions and the nature of our data. We had 2FA VPN connectivity and it was our company policy to only use our work laptops for work, not personal machines. Blake was breaking the rules from the day we hired him by refusing to use the company supplied Macbook we sent him.&lt;/p&gt;

&lt;p&gt;So we tried our best to pair with Blake but each time we asked to pair up he would come up with the typical response of, “I'm analyzing the problem, I'll get back to you”. Then magically at 21:00–22:00 we'd see some sort of Github activity which relates to no daytime work as previously mentioned. And for the records the commits were horrible especially for a senior developer with this much experience. These were literally cut/pasted solutions from Stack Overflow with no credit given to the original source.&lt;/p&gt;

&lt;h4&gt;
  
  
  What We Found Out
&lt;/h4&gt;

&lt;p&gt;Because of all of these excuses and bullshit factors we decided to do some investigation covertly and here's what we found out before we fired him.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Blake had multiple logins on his Ubuntu machine from IP addresses originating from APNIC (Asia Pacific Network) specifically India. There were multiple user accounts on his machine all of which had a fork of our github repo in their home directories. Yes, Blake was using offshore developers to do his work while he worked his day job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We further found that he was offshoring his own job due to the time of his commits. In the 3 months that we worked with Blake we found his commits to be always between 21:00–22:00, no other commits were ever made outside of that time frame. Guess what? That's 08:00–09:00 in India.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also discovered that he was working another full-time job with his previous employer on contract. How did we find this out? He made the mistake of leaving his old employer on his Linkedin profile and in a covert mission one of our developers called the company and asked to speak to him, the company said he was out on lunch but would be back in an hour.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We also discovered via github that his account was being used by another developer (or perhaps several). How did we know? Because their git name configuration listed another name and when we looked it up it was an oDesk developer from Bangalore. Busted!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We looked at Blake's github to see what sort of projects he was working on and there were a bunch of basic Ruby and Rails tutorial repos forked into his account. Was he starting an education service? Negative Ghostrider, the guy really had no experience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We tallied up his commits for the 3 months that he worked with us and the end result was 8 commits and 27 lines of code committed. Meanwhile the rest of us were on long streaks and committing much more often. Blake was simply not getting the job done and when he was it was not his code. How did we know? Because we looked at the styling and comments and compared it to the oDesk developer we previously discovered and it matched to a T.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When Blake finally returned his Macbook after several threats of legal action for not returning company property it arrived in its original packaging that we sent out and was not setup whatsoever. He never used the Macbook come to find out and ended up using his Ubuntu desktop which was against policy.&lt;br&gt;
After Blake was terminated one of us started scoping out his github and sure enough he had repos related to his old company which he never stopped working for. Blake had pulled the wool over our eyes for sure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Lessons Learned
&lt;/h4&gt;

&lt;p&gt;We all operated on the honor system and believe in trust and integrity. This was the foundation of our company. Unfortunately Blake had no integrity and could not be trusted. It's just a shame that it took us 3 months to figure this all out, meanwhile we turned down several heavy hitting senior developers because the position had been filled by Blake.&lt;/p&gt;

&lt;p&gt;We learned a tough lesson and after Blake was terminated we upped our game as far as candidate vetting and ended up hiring legit developers who really took us to the next level.&lt;/p&gt;

&lt;p&gt;My advice for those of you out there working with the Blakes of the world. Call them out on their bullshit early and fire fast. The integrity of your company and team depend on having legitimate, honest, skilled people. You deserve better, I know we sure did.&lt;/p&gt;

&lt;p&gt;Such is the end of another dev war story.&lt;br&gt;
shakycode â¤&lt;/p&gt;

&lt;p&gt;Twitter: &lt;a href="https://twitter.com/shakycode"&gt;shakycode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally posted at &lt;a href="https://shakycode.com/blake-the-onshore-offshore-programmer-72d086df99ec#.ybiletrxb"&gt;shakycode.com&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rails ActionCable The Saga Continues</title>
      <dc:creator>shakycode</dc:creator>
      <pubDate>Fri, 03 Feb 2017 17:25:52 +0000</pubDate>
      <link>https://dev.to/shakycode/rails-actioncable-the-saga-continues</link>
      <guid>https://dev.to/shakycode/rails-actioncable-the-saga-continues</guid>
      <description>&lt;p&gt;Yesterday I wrote a post titled, “My Struggle With Rails ActionCable” which got a lot of good feedback and reviews. But overnight I thought long and hard about this problem that I faced in that I could not get the request origin aka TENANT to be delegated to the channel.rb file.&lt;/p&gt;

&lt;p&gt;There was an open issue on the Apartment Gem where several people were discussing Apartment and Actioncable. After doing my own research and coming up short I saw a light at the end of the tunnel. One of the contributors to the Apartment gem found some documentation on how the user is verified for connection and he discovered the following in the documentation.&lt;/p&gt;

&lt;p&gt;"Note that anything marked as an identifier will automatically create a delegate by the same name on any channel instances created off the connection."&lt;/p&gt;

&lt;p&gt;So I went to work to refactor my code and this is what I came up with in the connection.rb file&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PeLYKXwT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Am5tzRJ4kviE1LczEAI9TCA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PeLYKXwT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2Am5tzRJ4kviE1LczEAI9TCA.png" alt="connection.rb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you notice the ActionCable connection is now identified by &lt;code&gt;current_user&lt;/code&gt; and by &lt;code&gt;tenant&lt;/code&gt; by setting the &lt;code&gt;tenant&lt;/code&gt; in the &lt;code&gt;connect&lt;/code&gt; method by simply calling &lt;code&gt;self.tenant = request.subdomain&lt;/code&gt; then immediately following we switch the tenant and connect to the proper channel based on tenant. Since we are now delegating tenant to the channel it's a relatively easy fix to get the channel wired up and switch the tenant in our &lt;code&gt;send_message&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yN_G4qx_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AlP8CDseOefW7aDh9nF3FBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yN_G4qx_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AlP8CDseOefW7aDh9nF3FBA.png" alt="channel.rb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now if you look at the &lt;code&gt;send_message&lt;/code&gt; method in the channel file you'll notice we're switching the tenant as such &lt;code&gt;Apartment::Tenant.switch!(tenant)&lt;/code&gt; which is possible now because we delegated &lt;code&gt;tenant&lt;/code&gt; from the &lt;code&gt;connection.rb&lt;/code&gt; file so that it's available to the channel.&lt;/p&gt;

&lt;p&gt;End result, ActionCable and Multi-tenancy now working across the board. I honestly haven't seen a use case (trust me I've googled for hours) where someone was building a multi-tenant SaaS platform and integrating ActionCable.&lt;/p&gt;

&lt;p&gt;So now this feature is near completion, just ironing out some coffeescript bugs and issues with the Background Job processor.&lt;/p&gt;

&lt;p&gt;I'm hoping to write a full tutorial soon on this topic, but for now the problem is solved and I have to give a big thanks to the Apartment and Rails community for helping to steer me in the right direction to solve my specific use case.&lt;/p&gt;

&lt;p&gt;What are you building with ActionCable? Are you implementing multi-tenancy? If so, give me a shout and let's compare notes!&lt;/p&gt;

&lt;p&gt;Cheers!&lt;br&gt;
shakycode â¤&lt;br&gt;
Twitter: &lt;a href="https://twitter.com/shakycode"&gt;shakycode&lt;/a&gt;&lt;br&gt;
Email: &lt;a href="mailto:shakycode@gmail.com"&gt;shakycode@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://shakycode.com/rails-actioncable-the-saga-continues-7c29301be0df#.rsxhmuduh"&gt;Originally posted here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>actioncable</category>
    </item>
    <item>
      <title>My Struggle With Rails ActionCable</title>
      <dc:creator>shakycode</dc:creator>
      <pubDate>Thu, 02 Feb 2017 21:43:56 +0000</pubDate>
      <link>https://dev.to/shakycode/my-struggle-with-rails-actioncable</link>
      <guid>https://dev.to/shakycode/my-struggle-with-rails-actioncable</guid>
      <description>&lt;p&gt;Let me give you a bit of background on this article. I'm building a multi-tenant SaaS platform that connects Physicians with Patients. Included in this is the ability to have realtime chat sessions between two parties. This is all built on Ruby on Rails, my framework of choice using Ruby which is my primary language.  In Rails 5 ActionCable was introduced which facilitates dead-simple websocket functionality replacing the need for external dependencies such as FAYE or 3rd-party services like pusher.io. This is baked in and a pleasure to work with. Or so I thought.&lt;/p&gt;

&lt;p&gt;You see multi-tenancy is a difficult problem to solve and ActionCable likes to transmit its websockets on a specific request origin. The request origin could be for example: &lt;a href="https://acme.engagemd.co" rel="noopener noreferrer"&gt;https://acme.engagemd.co&lt;/a&gt; so all socket requests connect and stream from that request origin. If you aren't sure what a request origin is in Rails, think of a the request as where the HTTP request is coming from. In my case this is a multi-tenant app so the requests would come from a plethora of subdomain names. Actioncable looks for specific request origins based off of a whitelist that you specify in the production.rb environment file. Now you can get clever and use some Regex matching to allow subdomains from a parent domain i.e. acme.engagemd.co, doctor.engagemd.co, etc. But this is not enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem #1
&lt;/h3&gt;

&lt;p&gt;In my new platform I am using the Apartment gem to give each tenant their own database schema and have written the platform so that the entire app will switch Tenants based on the request origin. When I first started writing a simple chat feature into the app I was presented with the issue of how to get ActionCable to connect based on the request origin. After some help from a friend and doing my own research I was able to get the connection.rb file which drives ActionCable to read the request origin and switch the tenant in realtime. This got rid of the rejected connections and the streams started flowing properly. This is my connection.rb file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7305sp8uy8xwobuvedpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7305sp8uy8xwobuvedpc.png" alt="connection.rb" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see when we go to connect we set the tenant to the request subdomain then call switch on the second line of the connect method to switch the tenant and following that verifying that the user is part of the tenant and allowed to receive websocket traffic. That part was solved relatively easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem #2 aka The Show Stopper
&lt;/h3&gt;

&lt;p&gt;In the channel file which is responsible for sending data to the client, there's really no way to access the request origin and switch the tenant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fxiiq1xbeq8upy7r24a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fxiiq1xbeq8upy7r24a.png" alt="channel.rb" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in both the subscribed and &lt;code&gt;send_message&lt;/code&gt; methods in the channel file it's required that we switch tenants. In the subscribed method I hardcoded a tenant just to see if it would switch and it did. In the &lt;code&gt;send_message&lt;/code&gt; method (and the connect method) I really need to be able to access the request's subdomain so that I can switch tenants and livestream the chat.&lt;/p&gt;

&lt;p&gt;Now here is the showstopper. After reading the ActionCable docs and Googling for what must have been 4 hours yesterday there's really no way to get the request into the channel file. That being said this is a complete failure and I'm not able to use ActionCable for multi-tenant realtime chat since the request is unavailable in the channel file.&lt;/p&gt;

&lt;p&gt;So I went on a witchhunt trying to figure this god damned thing out. My first thought was to set a global like $request in the application controller and allowing the channel file to access that. This works in theory but has multiple problems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Globals are a security risk and are prone to mutex conditions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When you have more than one tenant and user the global variable &lt;code&gt;$request&lt;/code&gt; gets overwritten and ActionCable will not transmit after the tenant is switched. Or worse yet the global variable gets lost entirely and the tenant will attempt to switch but having no subdomain which to switch on fails and messages are not created.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've opened up an issue on Rails core to see if anyone can help as the documentation is lacking and I'm pretty sure I can't be the only one with this specific use case. So I'm hoping for some feedback on this soon. In the meantime I'm tearing apart ActionCable in rails to see if there's a way to pass the request to the channel file. If I can figure this out I will do a PR against master and hope for inclusion in the next release of Rails, but I'm not holding my breath as the Rails community is an opinionated bunch and multi-tenancy is not what everyone is doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Case for Polling
&lt;/h3&gt;

&lt;p&gt;Considering the fact that I'm falling face first on my desk dealing with this ActionCable issue I've decided that a good alternative is do Ajax polling in the chatrooms where an ajax call is made every 2–3s and polls for new content and refreshes the div/partial. Surprisingly enough this is how Basecamp does it in their campfire chat instead of using ActionCable. I watched a good talk with DHH about Rails performance and he went into a bit how they are using Ajax polling for their campfire chat instead of livestreaming via websockets. Their thought was not realtime chat, but “realtime enough”. 99% of end users will not notice a 2–3s delay in chat which is plenty of time for the system to poll and refresh the partial showing new messages.&lt;/p&gt;

&lt;p&gt;This is not what I wanted to build nor the way I wanted to build it but at this point I see no other choice but to move forward with Ajax polling and eventually ActionCable will introduce the request origin being passed from connection.rb to the channel file. Or I'll write a PR that introduces this behavior and hope that it's accepted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;Writing software is hard. Just when you think you have it figured out an 800lb gorilla hops on your back and takes you for a pony ride. I know that I'm making good progress on my platform and will continue to do so but all of these roadblocks can be discouraging. I'm doing my best to take these challenges as opportunities to grow and think outside of the box, but it's a bummer none the less.&lt;/p&gt;

&lt;p&gt;Are you working with ActionCable and multitenancy? If so, let's chat and maybe we can come up with a solution that works for all!&lt;/p&gt;

&lt;p&gt;Cheers!&lt;br&gt;
Shakycode â¤&lt;/p&gt;

&lt;p&gt;Twitter: &lt;a href="https://twitter.com/shakycode" rel="noopener noreferrer"&gt;shakycode&lt;/a&gt;&lt;br&gt;
Email: &lt;a href="mailto:shakycode@gmail.com"&gt;shakycode@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>multitenancy</category>
      <category>actioncable</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Hi, I'm shakycode</title>
      <dc:creator>shakycode</dc:creator>
      <pubDate>Thu, 02 Feb 2017 21:33:14 +0000</pubDate>
      <link>https://dev.to/shakycode/hi-im-shakycode</link>
      <guid>https://dev.to/shakycode/hi-im-shakycode</guid>
      <description>&lt;p&gt;I have been coding for 5 years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/shakycode" rel="noopener noreferrer"&gt;shakycode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Houston.&lt;/p&gt;

&lt;p&gt;I work for many companies&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: Ruby, Python, Javascript, and Rust.&lt;/p&gt;

&lt;p&gt;I am currently learning more about Event Driven Architecture and SOA Architecture.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
