<?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: Mikołaj Wawrzyniak</title>
    <description>The latest articles on DEV Community by Mikołaj Wawrzyniak (@szaszolak).</description>
    <link>https://dev.to/szaszolak</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%2F23694%2F456bed47-f462-4851-9a19-b3d58302a9b2.jpeg</url>
      <title>DEV Community: Mikołaj Wawrzyniak</title>
      <link>https://dev.to/szaszolak</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/szaszolak"/>
    <language>en</language>
    <item>
      <title>Extracting Rails Engine by example - Vikings social media</title>
      <dc:creator>Mikołaj Wawrzyniak</dc:creator>
      <pubDate>Mon, 01 Jul 2019 17:19:26 +0000</pubDate>
      <link>https://dev.to/szaszolak/extracting-rails-engine-by-example-vikings-social-media-4014</link>
      <guid>https://dev.to/szaszolak/extracting-rails-engine-by-example-vikings-social-media-4014</guid>
      <description>&lt;p&gt;This post will describe step by step extraction process of a Rails engine from a monolithic application. This is a follow-up to my previous piece, where I explained the pros and cons of Rails engines as a solution for modularizing big monolithic applications. The full source code of application used for this post can be found &lt;a href="https://gitlab.com/szaszolak/valhalla/merge_requests/2" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Engine preparation

&lt;ul&gt;
&lt;li&gt;
Engine initilization &lt;/li&gt;
&lt;li&gt;RSpec initialization&lt;/li&gt;
&lt;li&gt;Databse connection configuration&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Parent app preparation

&lt;ul&gt;
&lt;li&gt;Request test creation&lt;/li&gt;
&lt;li&gt;
Engine instalation &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Code transfer

&lt;ul&gt;
&lt;li&gt;Migrations&lt;/li&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;li&gt;Factories&lt;/li&gt;
&lt;li&gt;Rest of Rails parts&lt;/li&gt;
&lt;li&gt;Not standard Rails components&lt;/li&gt;
&lt;li&gt;External dependencies&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To set a scene, let's imagine that we are earls (aka chieftains) of Viking communities. As a forward-minded leader, we've already created a simple social media website for our people. It allows townsmen to enlist as warriors or farmers, and browse lists of each profession, to find companions or suppliers for upcoming raids. It also has a separate section where special e-seer gives its daily weather prophecies. It all works together, but now we've decided that it is time to improve architecture, and maybe share some parts of our systems with other Viking communities as an open source. With no further ado let's get to work, and extract seer module into the engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuvss1u7xl4y9w7njdez.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuvss1u7xl4y9w7njdez.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Engine preparation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before We can move any of the existing code from the parent app into the engine, we need to initialize it, set up a unit test framework and configure development and test database connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize engine &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To initialize engine We can use Rails generator with this command.&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;$ &lt;/span&gt;rails plugin new seer &lt;span class="nt"&gt;--mountable&lt;/span&gt; &lt;span class="nt"&gt;--dummy-path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;spec/dummy &lt;span class="nt"&gt;--skip-test&lt;/span&gt; &lt;span class="nt"&gt;--databse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql &lt;span class="nt"&gt;--skip-git&lt;/span&gt;  


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It accepts a number of flags that adjust the generated engine scaffold to our needs. Most important ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--mountable&lt;/code&gt;, it instructs the generator that we want a 'mountable' engine, and it should be namespace isolated from the host application. This prevents constants name collision, between the code of the host app and the engine.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--dummy-path&lt;/code&gt;, sets the location of 'dummy' app generated by &lt;em&gt;Rails&lt;/em&gt; for unit test purposes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--skip-test&lt;/code&gt;, instructs generator to not scaffold tests, it is useful if you prefer to use another test framework over &lt;em&gt;Minitest&lt;/em&gt;. For me preferred one is &lt;em&gt;Rspec&lt;/em&gt; (which will be configured later on).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--database&lt;/code&gt;, configures database adapter which will be used. It is the best to set it, to the same as the one used by the application from which we want to extract an engine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--skip-git&lt;/code&gt;, prevents new &lt;em&gt;git&lt;/em&gt; repository initialization. I prefer to do that at the very end of a whole process when I'm moving the engine from a subdirectory of the parent app into a separate repository. Before that, I work on a separate branch of the main repository and compare changes in the merge (aka pull) request. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After the command is executed, the generator scaffolds the requested engine in a subdirectory of the parent app. As the generator is working we can see typical output upon the terminal. Among standard parts like controllers, models, we can also notice a few additional files has been generated&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

create  lib/seer.rb
create  lib/seer/engine.rb
create  seer.gemspec
create  lib/seer/version.rb
vendor_app  spec/dummy


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Those files are really interesting for two reasons, one they clearly indicate that engine is a specialized gem, and two each of them has a special role:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lib/seer.rb&lt;/code&gt; is an entry point to the engine, this file will be required when the host application of the engine loads its dependencies. It can be used to make engines external dependencies configurable and loads &lt;code&gt;lib/seer/engine.rb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/seer/engine.rb&lt;/code&gt; informs the parent application that this given gem is an engine. It also can be used to configure engine parameters (similar &lt;code&gt;config/application.rb&lt;/code&gt; file is used in a standard &lt;em&gt;Rails&lt;/em&gt; app). In fact, the generator already configured one parameter for us: &lt;code&gt;isolate_namespace Seer&lt;/code&gt;, it declares that the whole engine is isolated in the namespace named after the engine.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seer.gemspec&lt;/code&gt; contains metadata about engine and gems upon which it depends.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lib/seer/version.rb&lt;/code&gt; this file declares the current version of the engine&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spec/dummy&lt;/code&gt; is previously mentioned 'dummy' Rails app which will be used in unit tests of the engine&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rspec initialization &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;After the engine is initialized, we should configure a unit test framework. Although there is no limitation on which one we can use, it is the most convenient to choose the same one, as it is used in the parent app. That way, we can simply reuse most of the already existing unit test code. At first, we need to add development dependencies into the &lt;code&gt;gemspec&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="no"&gt;Gem&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Specification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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;spec&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;  
  &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
  &lt;span class="nf"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"spec/**/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;            

  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_development_dependency&lt;/span&gt; &lt;span class="s1"&gt;'rspec-rails'&lt;/span&gt;
  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_development_dependency&lt;/span&gt; &lt;span class="s1"&gt;'factory_bot_rails'&lt;/span&gt;
  &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_development_dependency&lt;/span&gt; &lt;span class="s1"&gt;'dotenv-rails'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can proceed &lt;code&gt;lib/seer/engine.rb&lt;/code&gt; and set up generators.&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;module&lt;/span&gt; &lt;span class="nn"&gt;Seer&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Engine&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;
    &lt;span class="n"&gt;isolate_namespace&lt;/span&gt; &lt;span class="no"&gt;Seer&lt;/span&gt;


    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generators&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;generators&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test_framework&lt;/span&gt; &lt;span class="ss"&gt;:rspec&lt;/span&gt;
      &lt;span class="n"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fixture_replacement&lt;/span&gt; &lt;span class="ss"&gt;:factory_bot&lt;/span&gt;
      &lt;span class="n"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;factory_bot&lt;/span&gt; &lt;span class="ss"&gt;dir: &lt;/span&gt;&lt;span class="s1"&gt;'spec/factories'&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;And at least we should install new dependencies and &lt;em&gt;RSpec&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

developer@macbook engines-directory &lt;span class="nv"&gt;$ &lt;/span&gt;bundle &lt;span class="nb"&gt;install
&lt;/span&gt;developer@macbook engines-directory &lt;span class="nv"&gt;$ &lt;/span&gt;rails g rspec:install
  create  .rspec
  exist  spec
  create  spec/spec_helper.rb
  create  spec/rails_helper.rb


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After &lt;code&gt;rails_helper.rb&lt;/code&gt; file gets created, we have to adjust the environment path in it, to point onto the 'dummy' app.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expand_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../dummy/config/environment.rb'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And now we are ready for the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database connection configuration &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;A first step to configure 'dummy' app database connection is to adjust &lt;code&gt;database.yml&lt;/code&gt; file in 'dummy' &lt;code&gt;db&lt;/code&gt; directory, for that most of the &lt;code&gt;database.yml&lt;/code&gt; file from the parent app can be reused, except for databases names.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;default&lt;/span&gt;
&lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgresql&lt;/span&gt;
&lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_HOST') %&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_USER') %&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_PASSWORD') %&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_PORT') %&amp;gt;&lt;/span&gt;

&lt;span class="na"&gt;development&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_DB') %&amp;gt;_development&lt;/span&gt;

&lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*default&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;%= ENV.fetch('POSTGRES_DB') %&amp;gt;_test&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I've decided to store sensitive data outside the &lt;em&gt;git&lt;/em&gt; repository, inside environment variables. In this case, we should prepare a tool to load locally environment variables for us. I've chosen &lt;a href="https://github.com/bkeepers/dotenv" rel="noopener noreferrer"&gt;Dotenv&lt;/a&gt;, so I've created a &lt;code&gt;.env&lt;/code&gt; file in 'dummy' app directory and required &lt;code&gt;dotenv&lt;/code&gt; before dummy apps boots. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;#seer/spec/dummy/config/application.rb&lt;/span&gt;
&lt;span class="no"&gt;Bundler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"seer"&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'dotenv-rails'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Dummy&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;At least we should execute two Rails database-related tasks.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

developer@macbook engines-directory &lt;span class="nv"&gt;$ &lt;/span&gt;rails db:setup
developer@macbook engines-directory &lt;span class="nv"&gt;$ &lt;/span&gt;rails db:migrate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If all steps are correctly performed inside the 'dummy' app &lt;code&gt;db&lt;/code&gt; catalog, &lt;code&gt;schema&lt;/code&gt; file should get created. &lt;/p&gt;

&lt;p&gt;After that, we are ready to take the next step. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9sx3e4kdkjpjgg4pkyt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr9sx3e4kdkjpjgg4pkyt.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parent app preparation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With the initialized engine next, we need to plug it into the parent app, so the changes we are going to make Can be iteratively verified as we proceeded with code transfer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request test creation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Before we extract any piece of code, it will be very handy to ensure, that the whole system from an end-user perspective has not changed after the process is completed. To assure that, I prefer to add requests test for the extracted module.&lt;/p&gt;

&lt;div class="highlight js-code-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;'rails_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'WeatherProphecies'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:villager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:villager&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;sign_in&lt;/span&gt; &lt;span class="n"&gt;villager&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'GET /weather_prophecies'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'returns current prophecy'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;weather_prophecies_path&lt;/span&gt;

      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'rain'&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;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Engine installation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To use newly created engine we need to include it in &lt;code&gt;Gemfile&lt;/code&gt; of thr parent app &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s1"&gt;'https://rubygems.org'&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;

&lt;span class="c1"&gt;# engines&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'seer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="s1"&gt;'seer'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And mount it in the routes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;draw&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;mount&lt;/span&gt; &lt;span class="no"&gt;Seer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;at: &lt;/span&gt;&lt;span class="s1"&gt;'/seer'&lt;/span&gt;  
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Code transfer &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With the parent app and the engine ready, we can start moving pieces of code from one to another. I prefer to start from the database and continue up the layers until I got to the controllers. That way we have less external dependencies to handle at the time. &lt;/p&gt;
&lt;h3&gt;
  
  
  Migrations &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the end, the engine and the parent app will use the same database. However for test and development purposes, and also to make the engine truly mountable, even to other apps, we have to copy all migrations related to transferred database tables into the engine. While coping migrations from the parent, &lt;strong&gt;we should leave migrations names intact&lt;/strong&gt;, so when the engine is installed those migrations will not get duplicated. &lt;/p&gt;

&lt;p&gt;By default all tables of the engine are prefixed with the name of the engine (&lt;code&gt;seer&lt;/code&gt; in this case) since that could not be the case before the extraction when all existing migrations are copied to the engine, we must add new ones which will rename transferred tables with the correct prefix.&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;RenameWeatherPropheciesToSeerWeatherProphecies&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;rename_table&lt;/span&gt; &lt;span class="ss"&gt;:weather_prophecies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:seer_weather_prophecies&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;To copy and apply the migrations of the engine to the parent app, we can use the following commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

developer@macbook host-app-directory &lt;span class="nv"&gt;$ &lt;/span&gt;rails seer:install:migrations
NOTE: Migration 20170809130629_create_weather_prophecies.rb from seer has been skipped. Migration with the same name already exists.
developer@macbook host-app-directory &lt;span class="nv"&gt;$ &lt;/span&gt;rails db:migrate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Models &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To transfer models from the parent into the engine, we can simply run the bash command, or use the cut and paste method.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

developer@macbook host-app-directory &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;app/models/weather_prophecy.rb seer/app/models/seer/weather_prophecy.rb


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We should be careful to place each file in the correct directory, which represents the namespace of the engine (eg: &lt;strong&gt;seer/app/models/seer&lt;/strong&gt;) otherwise, an autoloader will ignore them and we will get an error &lt;code&gt;NameError: uninitialized constant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After each model with the corresponding spec is transferred, we need to wrap their code in the module of the engine.&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;module&lt;/span&gt; &lt;span class="nn"&gt;Seer&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherProphecy&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="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;h3&gt;
  
  
  Factories &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;When models and their specs are moved, the one thing we lack to make test back to the green state are factories.&lt;/p&gt;

&lt;p&gt;To use &lt;a href="https://github.com/thoughtbot/factory_bot_rails" rel="noopener noreferrer"&gt;FactoryBot&lt;/a&gt; at first we need to adjust &lt;code&gt;rails_helper.rb&lt;/code&gt; file and point set a path to a directory which will contain factories definitions&lt;/p&gt;
&lt;div class="highlight js-code-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;'factory_bot'&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;definition_file_paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'factories'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find_definitions&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&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;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="no"&gt;FactoryBot&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Syntax&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Methods&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can move factory definitions just like we've done with the model files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rest of Rails parts &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The rest of the &lt;em&gt;Rails&lt;/em&gt; parts like controllers, jobs, channels can be moved the same way as we've transferred models.&lt;/p&gt;

&lt;p&gt;As for the routes, they should be cut out from the &lt;code&gt;routes.rb&lt;/code&gt; file of the parent app and placed in the one that belongs to the engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not standard Rails components &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In this scenario I've created an additional &lt;code&gt;services&lt;/code&gt; layer, there is one gotcha with such an approach. To ensure that autoloader loads these parts of the code as well we can do one of two things, either we extend autoloader paths, or we place these additional layers in the app directory of the engine. I've chosen the latter for this scenario.&lt;/p&gt;

&lt;p&gt;Besides that, we can move them like the rest.&lt;/p&gt;

&lt;h3&gt;
  
  
  External dependencies &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The last finishing touch is to make external dependencies configurable.&lt;br&gt;
Although while developing the engine, we could refer to parents app modules and classes, by using their qualified names (prefixed with &lt;code&gt;::&lt;/code&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;module&lt;/span&gt; &lt;span class="nn"&gt;Seer&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;ApplicationController&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;Unfortunately, this introduces thigh coupling between the engine and the parent app. To address that, and make our engine more flexible we should allow others to configure external dependencies upon engine initialization.&lt;/p&gt;

&lt;p&gt;Because of that, we should add a module accessor which would store such dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# lib/seer.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Seer&lt;/span&gt;
  &lt;span class="n"&gt;mattr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:application_controller_class&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application_controller_class&lt;/span&gt;
    &lt;span class="vc"&gt;@@application_controller_class&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constantize&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;To configure them, we need to create an initializer in the parent app.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# parent_app/config/initializers/seer.rb&lt;/span&gt;

&lt;span class="no"&gt;Seer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application_controller_class&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ApplicationController'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Inside the engine, we can use them in the following manner.&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;ApplicationController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Seer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application_controller_class&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After this last step, our engine is ready to be used. We could leave it as a subdirectory of parents app, or move it to stand alone repository and use it freely in a number of apps. &lt;/p&gt;

&lt;p&gt;As we've just accomplished this challenging task our system is better structuralized and easier to navigate, a test suite is running faster, it is easier to work in parallel on different parts of the system without worry about merge conflicts. We are now ready to celebrate our glory on a Viking feast.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf6oiuptmk0n67atsavh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flf6oiuptmk0n67atsavh.gif"&gt;&lt;/a&gt;  &lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Modularizing old monolith - Rails Engines to the rescue!</title>
      <dc:creator>Mikołaj Wawrzyniak</dc:creator>
      <pubDate>Tue, 21 May 2019 12:08:25 +0000</pubDate>
      <link>https://dev.to/szaszolak/modularizing-old-monolith-rails-engines-to-the-rescue-4jm0</link>
      <guid>https://dev.to/szaszolak/modularizing-old-monolith-rails-engines-to-the-rescue-4jm0</guid>
      <description>&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;This post is a shout out to the amazing features of Rails that allow developers to extract code fairly easily from monolith application into stand-alone modules. It aims to point out the advantages of Rails engines over microservices and acknowledges the cons of engines solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I’m a back-end developer, and I got hooked up on Rails over 4.5 years ago. Since then, I’ve spent almost three years as a professional working on a single product initially developed in 2011. This is my first post, and I hope you like it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A few weeks ago, I started researching ways to improve the architecture of my company’s main application, which is fairly old and fairly big (81,980 commits and counting). Over time, many developers have tried to keep it in the best possible shape. Despite going beyond the standard MVC model and adding layers to the application, it is no longer sufficient. We have encountered typical problems related to big monolith systems: very large cognitive load required to maintain the mental model of a system, slow test suite, dead code, etc.&lt;br&gt;
In such a situation, the first idea that pops out is to transition such a system into a shiny microservice world. As tempting it sounds, such as transition is not always easy or even possible for a number of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It moves application codebase complexity into the system infrastructure architecture&lt;/li&gt;
&lt;li&gt;It introduces new kinds of problems, mostly with communication, synchronization, and integration.&lt;/li&gt;
&lt;li&gt;It requires a significant amount of base work to prepare the system for such change before even a single business module can be moved out of a monolith&lt;/li&gt;
&lt;li&gt;It makes the local development environment setup more complex&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teams choosing a microservices approach should have a number of skilled software architects along with dev ops specialists, and a fair amount of time, to accomplish such goal.&lt;br&gt;
As for my case, microservices are off the table. I have continued looking, and I have noticed a convenient middle way, as you will read on . . . .&lt;/p&gt;

&lt;h2&gt;
  
  
  Rails Engines
&lt;/h2&gt;

&lt;p&gt;Engines are similar to a standard Rails application but in miniaturized form. Their structure is very similar to a typical Rails project; one can find inside all familiar MVC parts of Rails architecture, such as models, views, controllers, jobs, and channels.  There are a few minor differences, but what is most important, and which makes them such a useful tool, is that &lt;strong&gt;instead of being run as separate applications, Rails engines are mounted inside larger systems&lt;/strong&gt;. This feature also implements a convenient mechanism that prevents name collisions between host application and engine code, while still allowing for cross-referencing when needed.&lt;br&gt;
With that in mind, one of the coolest use cases of engines is the ability to extract code grouped in namespaces inside monolith host application into engines that are mounted in the parent application. This solution delivers most of the promises of microservices, such as system modularity, reduced cognitive load required to work on a single service and decreased execution time of test suite. &lt;br&gt;
Moreover, Rails engines shine in a few particular areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Because they are mounted inside the host application, they are not affected by communication and integration issues related to independent microservices.&lt;/li&gt;
&lt;li&gt;There is an easy setup; in fact, Rails engines could be initiated with a single Rails command.&lt;/li&gt;
&lt;li&gt;The smoothness of extracting bits of code, as an engine, at first could be merely a subdirectory of a host application. Files could be moved between them using drag and drop.&lt;/li&gt;
&lt;li&gt;The ability to be extracted to a stand-alone repository, in the form of a gem. And be reused by the number of applications.&lt;/li&gt;
&lt;li&gt;Different versions could be included in different apps, based on the used gem version number, which makes developing new features and A/B testing simpler.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because there is no silver bullet in software development, this approach also has its cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The host application, besides being composed with many independent modules, is still a single system that could be affected by dependencies conflicts among multiple engines.&lt;/li&gt;
&lt;li&gt;Rails engines do not offer the technological freedom of microservices.&lt;/li&gt;
&lt;li&gt;The host application still requires a significant amount of hardware resources, as a monolith would.&lt;/li&gt;
&lt;li&gt;Despite its convenience, the ability to cross-reference the host application and the mounted engine also makes it easier to produce unwanted coupling between them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Based on the above analysis, the pros outweigh the cons by far, particularly for smaller developer teams that do not have many resources to perform a transition to microservices. Even in terms of such transition, Rails engines could be used as a middle step, allowing a series of smaller changes rather than one big leap. Each previously extracted engine could be mounted later on in a smaller Rails app and used as microservices itself. What also should be mentioned is that engines are well ‘battle tested’ as some very popular solutions adopt them (e.g. devise and spree gems),&lt;br&gt;
I hope you’ve enjoyed this post. In my next one, I’ll provide a tutorial for ‘Hello World’ in the Rails engines world.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>microservices</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Learning from backend to full stack dev </title>
      <dc:creator>Mikołaj Wawrzyniak</dc:creator>
      <pubDate>Thu, 28 Feb 2019 09:09:33 +0000</pubDate>
      <link>https://dev.to/szaszolak/learning-from-backend-to-full-stack-dev--49c</link>
      <guid>https://dev.to/szaszolak/learning-from-backend-to-full-stack-dev--49c</guid>
      <description>&lt;p&gt;Hi fellow devs! &lt;/p&gt;

&lt;p&gt;I've been working as RoR developer since couple of years now. Recently I've decided to widen my skills with some frontend knowledge. &lt;/p&gt;

&lt;p&gt;Since then I'm looking around web, to find best jump start resources for person with my type of background. Beside strong backend and programming knowledge. I'm also familiar with fairly basics of javascript, html, and css (but all of this is surely heavily outdated and unorganized). I want to follow current &lt;a href="https://github.com/kamranahmedse/developer-roadmap"&gt;frontend roadmap&lt;/a&gt;. Could You suggest any books and courses which are worth of interesting in?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
