<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Tiger &amp; Dormouse</title>
    <description>Thoughts of a mountain based software developer.
</description>
    <link>http://pvcarrera.github.com/</link>
    <atom:link href="http://pvcarrera.github.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 20 Sep 2020 12:33:36 +0000</pubDate>
    <lastBuildDate>Sun, 20 Sep 2020 12:33:36 +0000</lastBuildDate>
    <generator>Jekyll v3.9.0</generator>
    
      <item>
        <title>Rails fixtures and PostgreSQL referencial integrity</title>
        <description>&lt;p&gt;Recently, on a Rails project, I had the need to create a disposable Heroku app to show features in progress and get quick feedback from the stakeholders. Not a long time ago, I’d read about the &lt;a href=&quot;https://devcenter.heroku.com/articles/github-integration-review-apps&quot;&gt;Heroku Review App functionality&lt;/a&gt; and I though this would be a good opportunity to try it out.&lt;/p&gt;

&lt;p&gt;Following the &lt;a href=&quot;https://devcenter.heroku.com/articles/github-integration-review-apps&quot;&gt;Heroku documentation&lt;/a&gt; I configured the Review apps for the project and, in no time, I had the ability to spin up a disposable Heroku app per pull request. The next step was populating these apps with demo data.&lt;/p&gt;

&lt;p&gt;In this project we have a QA/UAT Heroku app with a database containing demo data. My first thought was cloning the UAT db in the review boxes, but Heroku is clear about this approach: “Copying full database contents from parent to Review Apps (similar to heroku fork) is not currently supported”. Instead, they recommend seeding the database with a post deploy script.&lt;/p&gt;

&lt;p&gt;As this is a Rails project, I created some fixtures with demo data and loaded them using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rake db:fixtures:load&lt;/code&gt;. Fixtures loaded fine in my local machine but in the review boxes I was getting a referential integrity violation error. What was happening?&lt;/p&gt;

&lt;p&gt;We use PostgreSQL as database and PostgreSQL does integrity checks, like foreign key constraints. Rails fixtures are loaded in alphabetical order, so it’s common to find cases where a table that is being created has a reference to another table which hasn’t been created yet.&lt;/p&gt;

&lt;p&gt;If we take a look at &lt;a href=&quot;https://github.com/rails/rails/blob/master/activerecord%2Flib%2Factive_record%2Ffixtures.rb#L523&quot;&gt;ActiveRecord code base&lt;/a&gt; we can see how it calls the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disable_referential_integrity&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;create_fixtures&lt;/code&gt; method. &lt;a href=&quot;https://github.com/rails/rails/blob/master/activerecord%2Flib%2Factive_record%2Fconnection_adapters%2Fpostgresql%2Freferential_integrity.rb#L25&quot;&gt;This method&lt;/a&gt; contains a warning which says “Rails needs superuser privileges to disable referential integrity”. That was the reason why it worked in my machine, I had super user privileges for the local database.&lt;/p&gt;

&lt;p&gt;As expected, in Heroku it’s not possible to change PostreSQL database privileges, so I had to search for a different approach. After a bit of researching about PostgreSQL and referencial integrity, I found a &lt;a href=&quot;http://www.hagander.net/blog/automatically-dropping-and-creating-constraints-131&quot;&gt;post&lt;/a&gt; which shows how to drop and recreate PostgreSQL constraints.&lt;/p&gt;

&lt;p&gt;Using the scripts in the &lt;a href=&quot;http://www.hagander.net/blog/automatically-dropping-and-creating-constraints-131&quot;&gt;mentioned post&lt;/a&gt; I created a new &lt;a href=&quot;https://gist.github.com/pvcarrera/123280c58eca51ccebe3&quot;&gt;Rake task&lt;/a&gt; called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;populate_sample_data&lt;/code&gt;. This task resets the database, drops the PostgreSQL constraints, loads the fixtures and then recreates the previous constraints.&lt;/p&gt;

&lt;p&gt;Finally, I added the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;populate_sample_data&lt;/code&gt; rake task to the Review Apps post deploy script and everything started to work as expected.&lt;/p&gt;

&lt;p&gt;Rails contributors are working on a &lt;a href=&quot;https://github.com/rails/rails/pull/21233/files#r38946048&quot;&gt;solution&lt;/a&gt; for this problem, but for now it’s a work in progress and it doesn’t cover PostgreSQL versions older than 9.4.&lt;/p&gt;

&lt;p&gt;Hopefully this post will help other people facing the same problem, or someone can come up with a better solution.&lt;/p&gt;

</description>
        <pubDate>Mon, 15 Feb 2016 18:00:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2016/02/15/rails-fixtures-and-referencial-integrity.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2016/02/15/rails-fixtures-and-referencial-integrity.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Persisting Value Objects in Rails - Denormalised database</title>
        <description>&lt;p&gt;In &lt;a href=&quot;/general/2015/12/13/persisting-value-objects-in-a-relational-database.html&quot;&gt;my previous post&lt;/a&gt;, I talked about some of the options we have to persist value objects in a relational database. In this one, I’m going to show an example using Rails and the denormalised database approach.&lt;/p&gt;

&lt;p&gt;Let’s say we want to model a Client entity which has an Address. In the &lt;a href=&quot;/general/2015/10/22/entities-and-value-objects.html&quot;&gt;Entities and Value Objects post&lt;/a&gt;, I already used an Address value object as an example, let’s bring it back&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:postcode&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@postcode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;freeze&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;postcode&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;kp&quot;&gt;alias_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:eql?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:==&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Following the denormalised database approach, we’ll put together in the same database table the Client and the Address attributes. In Rails this would result in a migration similar to this&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CreateClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Migration&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;change&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_street&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_postcode&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In Rails we can say that ActiveRecord models are entities where the identity is provided by the ActiveRecord id. If we model the Client as an entity, the Client class could be something like&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;address&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address_street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address_postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:address_street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;street&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:address_postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;postcode&lt;/span&gt;

      &lt;span class=&quot;vi&quot;&gt;@address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;attr_writter&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:address_postcode&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since one of the value objects’ main characteristics is immutability, in order to prevent unwanted modification attempts from the Client, this implementation restricts the access of Rails attribute writers to private.&lt;/p&gt;

&lt;p&gt;It’s also worth mentioning that this denormalised approach can be handy when you are trying to extract behaviour from a convoluted Rails model. Imagine a Client model in which the Address attributes are already part of it, extracting a value object is trivial since there is no need to touch the database scheme. In fact, this refactor is a common one in articles that talk about refactoring fat ActiveRecord models.&lt;/p&gt;

&lt;p&gt;And that’s it, we have a Client entity that has a value object Address where all its attributes (Client and Address attributes) are persisted in the same database table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://leanpub.com/tr4w&quot;&gt;The Rails Way&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models&quot;&gt;7 Patterns to Refactor Fat ActiveRecord Models&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sun, 10 Jan 2016 18:00:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2016/01/10/persisting-value-objects-in-rails-denormalised-database.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2016/01/10/persisting-value-objects-in-rails-denormalised-database.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Persisting Value Objects in a Relational Database</title>
        <description>&lt;p&gt;How a VO persists has nothing to do with Entity/VO semantics, but it’s something that has to be considered since business data frequently has to be persistent. When you want to persist a value object in a relational database, there are tree main options. As always, there is not a correct one and all of them have pros and cons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Use a normalised database approach
    &lt;ul&gt;
      &lt;li&gt;How:
        &lt;ul&gt;
          &lt;li&gt;Use the auto generated id to identify the table but hiding it in the VO objects.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Pros:
        &lt;ul&gt;
          &lt;li&gt;Efficient database access. All the benefits of normalised databases: easily query, merge and update data.&lt;/li&gt;
          &lt;li&gt;Provides an easy way to solve one to many relations between VO objects.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Cons:
        &lt;ul&gt;
          &lt;li&gt;Difficult to hide/manage the id at class/object level.&lt;/li&gt;
          &lt;li&gt;Disconnection of the object from its database id. Easy to end with more than one database row for the same object.&lt;/li&gt;
          &lt;li&gt;Not easy to clean a destroyed VO from the database. Can lead to stale data in the DB.&lt;/li&gt;
          &lt;li&gt;Slow global update of entities with value objects in the DB.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Use a denormalised database
    &lt;ul&gt;
      &lt;li&gt;How:
        &lt;ul&gt;
          &lt;li&gt;Since VO objects don’t make sense without their Entity, at least at DB level, we can merge all the attributes in the same table.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Pros
        &lt;ul&gt;
          &lt;li&gt;True value objects without database ids.&lt;/li&gt;
          &lt;li&gt;This approach makes it easy to move out a value object from an entity. Only the objects and the ORM mapping would need to change, there is no need to change the database scheme.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Cons
        &lt;ul&gt;
          &lt;li&gt;Can be very tricky to implement properly with distributed systems.&lt;/li&gt;
          &lt;li&gt;Difficult to implement when the relation is not one to one.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Serialise representation next to the entities
    &lt;ul&gt;
      &lt;li&gt;How:
        &lt;ul&gt;
          &lt;li&gt;Store the object graph in a column. This can be accomplished using serialisation.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Pros
        &lt;ul&gt;
          &lt;li&gt;Efficient database loading.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Cons
        &lt;ul&gt;
          &lt;li&gt;Can be very tricky to implement properly with distributed systems.&lt;/li&gt;
          &lt;li&gt;Deserialisation.&lt;/li&gt;
          &lt;li&gt;Query limitations.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is my overview/index on persistence and value objects. I’ll try to dig more and illustrate with some examples each of these alternatives in future posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related posts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://gojko.net/2009/09/30/ddd-and-relational-databases-the-value-object-dilemma&quot;&gt;DDD and relational databases&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://thepaulrayner.com/persisting-value-objects&quot;&gt;Persisting value objects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://stackoverflow.com/questions/679005/how-are-value-objects-stored-in-the-database&quot;&gt;How are value objects stored in the database&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://vaughnvernon.co/?p=942&quot;&gt;The Ideal Domain-Driven Design Aggregate Store&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 13 Dec 2015 11:30:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/12/13/persisting-value-objects-in-a-relational-database.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/12/13/persisting-value-objects-in-a-relational-database.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Entities and Value Objects</title>
        <description>&lt;p&gt;Entities and value objects are key concepts when talking about &lt;a href=&quot;http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215&quot;&gt;Domain Driven Design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Entities are objects represented by its identity. For example, in our system we can have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; object with multiple attributes like name, password, etc. This object, regardless of its attributes, is going to be represented by an id. This means we can change any of the object’s attributes (name, password) and it will remain the same object. Example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:password&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;name&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'pablo'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;User:0x007fc0199c5028 @name=&quot;pablo&quot;, @password=&quot;password&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'peter'&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;User:0x007fc0199c5028 @name=&quot;peter&quot;, @password=&quot;password&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;second_user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'peter'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'password'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;lt;User:0x007fc01a171c90 @name=&quot;peter&quot;, @password=&quot;password&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;second_user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;On the other hand we have value objects. These objects represent something that measures, quantifies or describes an entity, and they don’t have an identity. Value objects are described by its attributes. Following the previous example, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; can have an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt; where the address is a characteristic of this user. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt; is characterised by its street and postal code attributes. If we change any of these attributes, we get a different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since any change in its attributes turn value objects into different objects, value objects should be treated as immutable objects. When you change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt; of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt;, you don’t change the attributes of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt; object, instead you create a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt; and assign it to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As we can have multiple objects representing the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Address&lt;/code&gt;, a common practice when working with value objects is to override the equality and hash methods.&lt;/p&gt;

&lt;p&gt;Value object example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Address&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;attr_reader&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:postcode&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@postcode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;freeze&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;is_a?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;street&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;postcode&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;alias_method&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:eql?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:==&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'NW18NH'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Address:0x007fc35205aba0 @street=&quot;my address&quot;, @post_code=&quot;NW18NH&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;second_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'second address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'NW28JH'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Address:0x007fc352051578 @street=&quot;second address&quot;, @post_code=&quot;NW28JH&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;copy_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'my address'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'NW18NH'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&amp;lt;Address:0x007fc352049008 @street=&quot;my address&quot;, @post_code=&quot;NW18NH&quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second_address&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# false&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;copy_address&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This was my introduction to entities and value objects. I’m currently reviewing my knowledge about &lt;a href=&quot;http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215&quot;&gt;Domain Driven Design&lt;/a&gt; and I mean to write a series of posts about it. If you want to read more about value objects and entities, here are some resources:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://martinfowler.com/bliki/ValueObject.html&quot;&gt;Matin Fowler: Value Object&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://martinfowler.com/bliki/EvansClassification.html&quot;&gt;Martin Fowler: Evans Classification&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215&quot;&gt;Domain Driven Design&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Thu, 22 Oct 2015 20:30:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/10/22/entities-and-value-objects.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/10/22/entities-and-value-objects.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>ROSSConf Berlin</title>
        <description>&lt;p&gt;Last weekend, I attended the &lt;a href=&quot;http://www.rossconf.io/event/berlin/&quot;&gt;ROSSConf&lt;/a&gt; in Berlin. This is not a classic conference where speakers talk about a subject and you listen to them, but  a gathering of Ruby open source maintainers with Ruby developers who are interested in collaborating in their projects. The conference was divided into two parts: firstly the mantainers gave an overview of their projects and the areas where they wanted help; the second part was a hands-on session where attendees could choose one of the projects and work on it.&lt;/p&gt;

&lt;p&gt;One thing that I really liked is the fact that the mantainers were right there, available all the time. It was easy to have a chat with them, get the overall idea of their projects, solve any doubts quickly and, in general, get that kind of context that it’s difficult to grasp from emails, irc channels and similar. And, of course, it’s also nice to see and know the person behind the project.&lt;/p&gt;

&lt;p&gt;The project I chose was &lt;a href=&quot;https://github.com/rom-rb&quot;&gt;ROM&lt;/a&gt; which, to be honest, I’d decided to join before the conference. I’d read some blog posts and watched some talks by his mantainer, &lt;a href=&quot;http://solnic.eu/&quot;&gt;Piotr Solnica&lt;/a&gt;, before RossConf, and I liked and agreed with some of the ideas he showed on them.&lt;/p&gt;

&lt;p&gt;So, what did I manage to do in this project? Well, not as much as I would have liked. I didn’t spend enough time before the conference reviewing and understanding the code base, so I dedicated most of the event to read the documentation. Despite the lack of context, I managed to do a small pull request and, more importantly, I saw &lt;a href=&quot;https://github.com/mbj/mutant&quot;&gt;mutation tests&lt;/a&gt; running for the first time in my life. I still don’t know much about this technique, but thanks to this conference I think I’m going to dig a bit more into it.&lt;/p&gt;

&lt;p&gt;What could be improved from my point of view? If I have to complain about anything, it would be the lack of time to write code. I know that we can now continue to contribute from home, but I’d have liked to have used the motivation you get when you are surrounded by other highly involved developers to do a bit more. It would have been nice to have a second full day of coding.&lt;/p&gt;

&lt;p&gt;Aside from looking at the ROM project, it was really nice to chat with other Ruby developers about the Berlin scene and the state of the art in general.&lt;/p&gt;

&lt;p&gt;Thanks a lot to the RossConf organisers and sponsors, it was a great event!&lt;/p&gt;

</description>
        <pubDate>Wed, 30 Sep 2015 20:00:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/09/30/ross-conf-berlin.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/09/30/ross-conf-berlin.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Remote work</title>
        <description>&lt;p&gt;In my current company, &lt;a href=&quot;https://www.upmysport.com&quot; target=&quot;_blank&quot;&gt;upmysport&lt;/a&gt;, the dev team is distributed half in London (UK) and half in Chamonix (France). This is my first experience with a fully remote work. I’d worked from home some days before, but I wouldn’t consider it to amount to a remote job. These are my thoughts after nine months working remotely.&lt;/p&gt;

&lt;h2 id=&quot;lifestyle&quot;&gt;Lifestyle&lt;/h2&gt;

&lt;p&gt;My lifestyle has experienced a 360 degrees change. Even if I couldn’t complain of my previous life in London, Chamonix fits better with my interests and I can practise the sports I love. In addition, working remotely makes it easier for me to travel to other countries to visit family and friends while keeping my workflow going.&lt;/p&gt;

&lt;p&gt;The lifestyle factor can seem to benefit only the employee, but I think that thanks to my new way of living my levels of stress and burnout have droped massively.  I now feel fresher, happier and more focused at work, so my productivity is higher than before.&lt;/p&gt;

&lt;h2 id=&quot;team-interaction&quot;&gt;Team interaction&lt;/h2&gt;

&lt;p&gt;Chats and videoconference are not as good as a face to face conversation or a coffee together, which usually means less brainstorming and less informal feedback. On the other hand, the lack of personal communication makes the time we spend face to face more special, with everybody involved trying to get the most of it.&lt;/p&gt;

&lt;p&gt;One thing I’ve noticed is the reduction of interruptions. When you are in an open-plan office, quite often people just come to your desk with a comment on a football match, last night’s TV show and so on. In a remote environment this kind of interruption is easier to filter, so you can “plan” your procrastination time.&lt;/p&gt;

&lt;p&gt;The lack of human interaction also makes it more difficult to create a company culture and a group of work-friends, but this effect can be mitigated with a bit of discipline and company effort. For example, among other practices we have company events from time to time to gather toguether and get to know each other better. We are also always available via chat or videoconference, and we share the progress inside teams and among them then quite often. All these small things keep the team united.&lt;/p&gt;

&lt;h2 id=&quot;code-practices&quot;&gt;Code practices&lt;/h2&gt;

&lt;p&gt;Apart from some face to face pairing, I’ve not found any major differences between my previous onsite jobs and my current remote code practices. We (developers) already work with “ready to remote” tools: remote repositories, pull requests, CI systems, bug trackers, online boards, management tools, and a long etc.&lt;/p&gt;

&lt;p&gt;To sum up, I believe that remote work is working quite well for &lt;a href=&quot;https://www.upmysport.com&quot; target=&quot;_blank&quot;&gt;upmysport&lt;/a&gt;, and I’m really enjoying it. Of course their context makes it easy to work remotely: it’s a startup with a small number of employees, there’s not a big time difference between both offices and the hierarchy is quite flat. It would be interesting to hear other people’s experience with remote work in big enterprises.&lt;/p&gt;

</description>
        <pubDate>Mon, 31 Aug 2015 10:00:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/08/31/remote-work.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/08/31/remote-work.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Rails polymorphic associations</title>
        <description>&lt;p&gt;Working on a Rails project, I faced a problem similar to this:
Given an ActiveRecordModel called Booking which can have multiple bills:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:booking&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Booking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bills&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The amount of the Bill comes from the Booking’s amount:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:booking&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;to: :booking&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now we need a new model, Subscription, and a Subscription can also have a Bill so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:subscription&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:booking&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;to: :booking&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Subscription&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bills&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And here is the problem, it isn’t possible to delegate to both Booking and Subscription.&lt;/p&gt;

&lt;p&gt;Ok, let’s stop thinking about Rails and try to solve this with OO and plain Ruby. In plain Ruby, the Bill class would probably look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;booking&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@booking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;booking&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;amount&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@booking&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;amount&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, when the Subscription entity enters the game, the only thing we need to take care of is the fact that Booking and Subscription have a common interface with one method amount. This can be written as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initializer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;billable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@billable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;billable&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;amount&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@billable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;amount&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, the Bill class doesn’t have to mind about Bookings or Subscriptions anymore.&lt;/p&gt;

&lt;p&gt;Good, back to Rails. How do I model this in Rails? I would have to change the previous Rails code to something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:billable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The answer is polymorphic associations. This type of association allows Bill to belong_to an interface. The only thing we have to do is mark this relation as polymorphic, and the Booking and Subscription models as billable&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;belongs_to&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:billable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;polymorphic: &lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Booking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bills&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;as: :billable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Subscription&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;has_many&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:bills&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;as: :billable&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Maybe in a future post I dig into how Rails maps these models to the database, but that’s it for today. Here I leave other posts about Rails polymorphic associations that I found interesting:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://about.futurelearn.com/blog/refactoring-rails-sti&quot;&gt;Refactoring rails STI&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://robots.thoughtbot.com/whats-the-deal-with-rails-polymorphic-associations&quot;&gt;Whats the deal with Rails polymorphic associations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Mon, 27 Jul 2015 20:12:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/07/27/rails-polymorphic-associations.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/07/27/rails-polymorphic-associations.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Heroku Rake tasks II</title>
        <description>&lt;p&gt;In the &lt;a href=&quot;/general/2015/06/07/heroku-rake-tasks.html&quot;&gt;previous post&lt;/a&gt;, I wrote a couple of &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; tasks to manage &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; db backups. Once I had this tasks in place I realised that it would be handy to have another one to load them into my local &lt;a href=&quot;http://www.postgresql.org&quot;&gt;Postgres&lt;/a&gt; database, so I wrote this in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;database.rake&lt;/code&gt; file:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:db&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Load remote database backup to local database'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:load_backup&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'latest.dump does not exist'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exist?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'latest.dump'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_clean_env&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;sb&quot;&gt;`pg_restore --verbose --clean --no-acl --no-owner \
      -h localhost -U postgres_dev -d development latest.dump`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Load completed.'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This worked fine, but if you take a look at the &lt;a href=&quot;https://github.com/ruby/rake#resources&quot;&gt;Rake documentation&lt;/a&gt; it’s easy to spot that &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; uses a dependency based style of computation rather than the usual imperative style.This means you can add dependent tasks and &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; will evaluate and run them first. Thanks to this &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; feature I rewrote my task to look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:db&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Load remote database backup to local database'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:load_backup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'heroku:download_backup'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_clean_env&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;sb&quot;&gt;`pg_restore --verbose --clean --no-acl --no-owner \
      -h localhost -U postgres_dev -d development latest.dump`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Load completed.'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With these changes, the task &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heroku:download_backup&lt;/code&gt;, which was created in the &lt;a href=&quot;/general/2015/06/07/heroku-rake-tasks.html&quot;&gt;previous post&lt;/a&gt;, runs before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;load_backup&lt;/code&gt; task, so I can ensure that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastest.dump&lt;/code&gt; file is going to be in place. As a side effect I don’t need to check for the dump file existence anymore.&lt;/p&gt;

&lt;p&gt;It looks good, but after using these tasks a couple of times I felt the inconvenience of having to wait for the db dump to download. The solution to this problem was using the &lt;a href=&quot;http://ruby-doc.org/stdlib-2.2.2/libdoc/rake/rdoc/Rake/FileTask.html&quot;&gt;Rake file taks&lt;/a&gt;. It’s like a normal &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; task, but it checks for the file timestamps. This is how I rewrote my &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; task&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Download database backup'&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:download_backup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;latest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dump&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'latest.dump'&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;app: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_APP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_clean_env&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`heroku pg:backups public-url --app &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;sb&quot;&gt;`curl -o latest.dump &quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&quot;`&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exitstatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Database downloaded.'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Download failed.'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;a href=&quot;http://ruby-doc.org/stdlib-2.2.2/libdoc/rake/rdoc/Rake/FileTask.html&quot;&gt;Rake file task&lt;/a&gt; only runs if the file doesn’t exist, so I can now run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rake db:load_backup&lt;/code&gt; and it’ll only download the database dump file the first time.&lt;/p&gt;

&lt;p&gt;It would also be nice if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heroku:download_backup&lt;/code&gt; ran when there is a new backup available in &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt;, but I’ll leave that for the future since this post is long enough.&lt;/p&gt;

</description>
        <pubDate>Sat, 04 Jul 2015 14:41:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/07/04/heroku-rake-tasks-ii.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/07/04/heroku-rake-tasks-ii.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Heroku Rake tasks</title>
        <description>&lt;p&gt;In the project I’m currently working on, we use &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; as infrasture provider. &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; has its own command line operations to execute tasks like db backups, managing addons, etc.&lt;/p&gt;

&lt;p&gt;Last March, &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; &lt;a href=&quot;https://devcenter.heroku.com/changelog-items/623&quot;&gt;deprecated its PG Backups addon&lt;/a&gt;, so the CLI syntax changed. The project I’m working on is a Rails project, so by default we already use &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; to run tasks like database migrations. Thus, instead of learning the new &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; syntax, I’ve decide to write a couple of &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; tasks to wrap the new &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; commands.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:heroku&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;no&quot;&gt;DEFAULT_APP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'my_app'&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Create database backup'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:backup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;app: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_APP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_clean_env&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;sb&quot;&gt;`heroku pg:backups capture --app &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exitstatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Backup created.'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Backup failed.'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;desc&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Download latest database backup'&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:download_backup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;app: &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_APP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Bundler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;with_clean_env&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`heroku pg:backups public-url --app &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:app&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
      &lt;span class=&quot;sb&quot;&gt;`curl -o latest.dump &quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&quot;`&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;exitstatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Database downloaded.'&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'Download failed.'&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Next time &lt;a href=&quot;http://www.heroku.com&quot;&gt;Heroku&lt;/a&gt; updates its command line syntax, I’ll only need to update the commands in my &lt;a href=&quot;http://docs.seattlerb.org/rake/&quot;&gt;Rake&lt;/a&gt; tasks and I won’t have to learn the nex syntax.&lt;/p&gt;

</description>
        <pubDate>Sun, 07 Jun 2015 14:41:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/06/07/heroku-rake-tasks.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/06/07/heroku-rake-tasks.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>Hub commands</title>
        <description>&lt;p&gt;During these last weeks, I’ve been trying out some Hub commands and finally decided to include some of them in my day to day workflow. Hub is a command line wrapper for Git that adds some GitHub specific functionality.&lt;/p&gt;

&lt;p&gt;To install it&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;hub&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To mix the classic Git commands with the new Hub commands, add to the bash profile&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;hub &lt;span class=&quot;nb&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All the commands available are in the &lt;a href=&quot;https://github.com/github/hub&quot;&gt;project page&lt;/a&gt;, but the ones I’ve incorporated into my workflow are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git compare&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull-request -o -b&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git ci-status -v&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the way I use them:&lt;/p&gt;

&lt;p&gt;Given that I’m in a feature, bug, etc. branch, when at some point I want to review my changes and compare them with the master branch, I use the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git compare&lt;/code&gt;. It launches the default browser with the GitHub diff view, comparing the current branch and master.&lt;/p&gt;

&lt;p&gt;When I’m happy with my branch, I push my changes to remote with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin my_branch&lt;/code&gt;. This action triggers the CI server which runs the test suite and confirms that tests work not only on my machine. While the CI server is running, I use the Hub command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git ci-status&lt;/code&gt; which returns a string with the current status of the CI server. Sometimes I run the command with the option -v, which also returns the CI server status plus the URL to CI build results.&lt;/p&gt;

&lt;p&gt;Once the CI server runs ssuccessfully, I proceed to open a pull request. In order to do that, I use the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git pull-request&lt;/code&gt;, usually with the option -o which automatically opens the GitHub pull request page in the default browser. Another option I sometimes use is -b, which allows opening a pull request to a specific branch.&lt;/p&gt;

&lt;p&gt;And that’s it. These are the three Hub commands I’ve incoporated to my git workflow.&lt;/p&gt;

</description>
        <pubDate>Sat, 23 May 2015 20:15:00 +0000</pubDate>
        <link>http://pvcarrera.github.com/general/2015/05/23/hub-commands.html</link>
        <guid isPermaLink="true">http://pvcarrera.github.com/general/2015/05/23/hub-commands.html</guid>
        
        
        <category>general</category>
        
      </item>
    
  </channel>
</rss>
