tag:edelpero.svbtle.com,2014:/feedEzequiel Delpero2015-04-14T13:40:52-07:00Ezequiel Delperohttps://edelpero.svbtle.comedelpero@gmail.comSvbtle.comtag:edelpero.svbtle.com,2014:Post/search-filters-and-object-oriented-design2015-04-14T13:40:52-07:002015-04-14T13:40:52-07:00Search Filters and Object Oriented Design<p>Search filters are a very common feature in any application.</p>
<p>I’ve used two gems for several projects I worked on: <a href="https://github.com/plataformatec/has_scope">has_scope</a> and <a href="https://github.com/nathanl/searchlight">searchlight</a>. </p>
<p>Both gems work out of the box, but they are not as flexible as I would like them to be, and that’s why I decided to create my gem, <a href="https://github.com/edelpero/lupa">Lupa</a>.</p>
<p>I decided to write an overview about these 3 gems:</p>
<h1 id="a-hrefhttpsgithubcomplataformatechasscopehass_1">
<a href="https://github.com/plataformatec/has_scope">HasScope</a> <a class="head_anchor" href="#a-hrefhttpsgithubcomplataformatechasscopehass_1">#</a>
</h1>
<p>has_scope will map your controller filters to your model scopes.</p>
<pre><code class="prettyprint lang-ruby"># app/controllers/products_controller.rb
class ProductsController < ApplicationController
has_scope :featured, type: :boolean
has_scope :by_price
has_scope :by_period, using: [:started_at, :ended_at], type: :hash
def index
@products = apply_scopes(Product).all
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/models/product.rb
class Product < ActiveRecord::Base
scope :featured, -> { where(featured: true) }
scope :by_price, -> price { where(price: price) }
scope :by_period, -> started_at, ended_at { where("started_at = ? AND ended_at = ?", started_at, ended_at) }
end
</code></pre>
<h3 id="pros_3">Pros <a class="head_anchor" href="#pros_3">#</a>
</h3>
<ul>
<li>Simple to use.</li>
<li>Minimal DSL.</li>
</ul>
<h3 id="cons_3">Cons <a class="head_anchor" href="#cons_3">#</a>
</h3>
<ul>
<li>Only works with Rails.</li>
<li>Couples logic to controllers.</li>
<li>Controller filters only can be applied to one resource at the time.</li>
<li>Architecture doesn’t encourage object-oriented design.</li>
<li>Hard to test.</li>
</ul>
<h1 id="a-hrefhttpsgithubcomnathanlsearchlightsearchl_1">
<a href="https://github.com/nathanl/searchlight">Searchlight</a> <a class="head_anchor" href="#a-hrefhttpsgithubcomnathanlsearchlightsearchl_1">#</a>
</h1>
<p>Searchlight does a similar work as HasScope but with a different approach by moving all the logic to its own class.</p>
<pre><code class="prettyprint lang-ruby"># app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
@products = ProductSearch.search(search_params).results
end
protected
def search_params
params.require(:product_search).permit(:featured, :by_price, :by_period)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/searches/product_search.rb
class ProductSearch < Searchlight::Search
search_on Product.all
searches :featured, :by_price, :by_period
def search_featured
search.where(featured: true)
end
def search_by_price
search.where(price: price)
end
def search_by_period
started_at = by_period[:started_at]
ended_at = by_period[:end_at]
search.where("started_at = ? AND ended_at = ?", started_at, ended_at)
end
end
</code></pre>
<h3 id="pros_3">Pros <a class="head_anchor" href="#pros_3">#</a>
</h3>
<ul>
<li>You can use it with any Framework, ORM or Object.</li>
<li>Decouples logic from the controller. You can use your search class wherever you want.</li>
<li>You can use different search classes inside your controller at the same time.</li>
<li>Easy to test.</li>
</ul>
<h3 id="cons_3">Cons <a class="head_anchor" href="#cons_3">#</a>
</h3>
<ul>
<li>Search classes are attached to the defined target by using <strong>search_on</strong> method. This means that you can’t reuse this class with another resource.</li>
<li>Search methods are not encapsulated; they are accessible from outside of the class itself.</li>
<li>Search class definition is complex.</li>
</ul>
<h1 id="a-hrefhttpsgithubcomedelperolupalupaa_1">
<a href="https://github.com/edelpero/lupa">Lupa</a> <a class="head_anchor" href="#a-hrefhttpsgithubcomedelperolupalupaa_1">#</a>
</h1>
<p>Lupa works similar to Searchlight but only uses POROs and has no DSL.</p>
<pre><code class="prettyprint lang-ruby"># app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
@products = ProductSearch.new(Product.all).search(search_params)
end
protected
def search_params
params.permit(:featured, :by_price, :by_period)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/searches/product_search.rb
class ProductSearch < Lupa::Search
class Scope
def featured
scope.where(featured: true)
end
def by_price
scope.where(price: search_attributes[:price])
end
def search_by_period
started_at = by_period[:started_at]
ended_at = by_period[:end_at]
scope.where("started_at = ? AND ended_at = ?", started_at, ended_at)
end
end
end
</code></pre>
<h3 id="pros_3">Pros <a class="head_anchor" href="#pros_3">#</a>
</h3>
<ul>
<li>You can use it with any Framework, ORM or Object.</li>
<li>Decouples logic from the controller. You can use your search class wherever you want.</li>
<li>You can use different search classes inside your controller at the same time.</li>
<li>Easy to test.</li>
<li>Search classes are not attached to a specific resource. You can use any resource with your search class.</li>
<li>Search methods are encapsulated; they are not accessible from outside the class itself.</li>
<li>No DSL used to define your search class, only POROs.</li>
<li>Encourages Object Oriented Design and the use of Design Patterns.</li>
</ul>
<h1 id="benchmarks_1">Benchmarks <a class="head_anchor" href="#benchmarks_1">#</a>
</h1>
<p>Besides the pros and cons of each gem, I decided benchmark this gems. I used <a href="https://github.com/evanphx/benchmark-ips">benchmark-ips</a> to perform the benchmarks.</p>
<h3 id="lupa-vs-hasscope_3">Lupa vs HasScope <a class="head_anchor" href="#lupa-vs-hasscope_3">#</a>
</h3>
<pre><code class="prettyprint">Calculating -------------------------------------
lupa 265.000 i/100ms
has_scope 254.000 i/100ms
-------------------------------------------------
lupa 3.526k (±24.7%) i/s - 67.045k
has_scope 3.252k (±24.8%) i/s - 61.976k
Comparison:
lupa: 3525.8 i/s
has_scope: 3252.0 i/s - 1.08x slower
</code></pre>
<h3 id="lupa-vs-searchlight_3">Lupa vs Searchlight <a class="head_anchor" href="#lupa-vs-searchlight_3">#</a>
</h3>
<pre><code class="prettyprint">Calculating -------------------------------------
lupa 480.000 i/100ms
searchlight 232.000 i/100ms
-------------------------------------------------
lupa 7.273k (±25.1%) i/s - 689.280k
searchlight 2.665k (±14.1%) i/s - 260.072k
Comparison:
lupa: 7273.5 i/s
searchlight: 2665.4 i/s - 2.73x slower
</code></pre>
<h1 id="conclusion_1">Conclusion <a class="head_anchor" href="#conclusion_1">#</a>
</h1>
<p>The 3 gems have a lot a cool features that I did not mention in this article. If you don’t know some of the gems, I suggest you to check out the documentation on the repository of them.</p>
tag:edelpero.svbtle.com,2014:Post/everything-you-always-wanted-to-know-about-writing-good-rake-tasks-but-were-afraid-to-ask2014-09-17T06:14:14-07:002014-09-17T06:14:14-07:00Everything You Always Wanted to Know About Writing Good Rake Tasks * But Were Afraid to Ask<p>Rake tasks are a very important component of our Rails Apps, because we usually use it to do maintenance or data migration jobs over a collection of data.</p>
<p>One of the guys at the office asked me. What things should I keep in mind when writing a rake task and how do I know if my rake task is well written.</p>
<p>The answer is not simple, because most of the time depends on the task you need to accomplish. <strong>I have a few rules I use to make my rake task what I consider good rake task</strong>.</p>
<h2 id="what-makes-a-rake-task-a-good-task_2">What Makes a Rake Task a Good Task? <a class="head_anchor" href="#what-makes-a-rake-task-a-good-task_2">#</a>
</h2>
<p>I think a rake task is good if:</p>
<ul>
<li>It has a meaningful and simple description.</li>
<li>It uses namespace to group similar or related tasks.</li>
<li>Its file structure follows the namespaces structure.</li>
<li>It’s isolated on a class so we can re use it and test it with ease.</li>
<li>It displays details about it progress without being too verbose.</li>
<li>Its has it own log file containing start datetime, end datetime, how much did the task last and all the errors.</li>
</ul>
<h2 id="writing-meaningful-descriptions_2">Writing Meaningful Descriptions <a class="head_anchor" href="#writing-meaningful-descriptions_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/import_topics.rake
task import_topics: :environment do
...
end
</code></pre>
<p>Writing a description it’s useful because it give us some details without reading the code. Also it’s useful when you want to inspect the list of available rake tasks using <code class="prettyprint">rake -T</code>. Now we only know that this task imports topics, nothing else.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Adding a good description for the previous task like <strong>“Migrate topics from legacy database to new database”</strong> give us more details about what the previous task do or should do. Now we know that these topics are imported from the legacy database to our current app database.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_topics.rake
desc 'Migrate topics from legacy database to new database'
task migrate_topics: :environment do
...
end
</code></pre>
<p><strong>Note:</strong> If you can’t explain your rake task in one sentence, that would probably mean that your rake task is doing more than one job and you should consider splitting your rake task.</p>
<h2 id="group-your-tasks-using-namespaces_2">Group Your Tasks Using Namespaces <a class="head_anchor" href="#group-your-tasks-using-namespaces_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_topics.rake
desc 'Migrate topics from legacy database to new database'
task migrate_topics: :environment do
...
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_users.rake
desc 'Migrate users from legacy database to new database'
task migrate_users: :environment do
...
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_questions.rake
desc 'Migrate questions from legacy database to new database'
task migrate_questions: :environment do
...
end
</code></pre>
<p>All these task has one thing in common. They are used to migrate information. So you should group this similar tasks under a common namespace, <code class="prettyprint">migrate</code>.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/topics.rake
namespace :migrate do
desc 'Migrate topics from legacy database to new database'
task topics: :environment do
...
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/users.rake
namespace :migrate do
desc 'Migrate users from legacy database to new database'
task users: :environment do
...
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/questions.rake
namespace :migrate do
desc 'Migrate questions from legacy database to new database'
task questions: :environment do
...
end
end
</code></pre>
<p>Now we know all these rake tasks are related. Using namespaces will help you keeping your code organized, clean and understandable.</p>
<h2 id="rake-file-structure_2">Rake File Structure <a class="head_anchor" href="#rake-file-structure_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_topics.rake
desc 'Migrate topics from legacy database to new database'
task migrate_topics: :environment do
...
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_users.rake
desc 'Migrate users from legacy database to new database'
task migrate_users: :environment do
...
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate_questions.rake
desc 'Migrate questions from legacy database to new database'
task migrate_questions: :environment do
...
end
</code></pre>
<p><strong>File Structure:</strong></p>
<pre><code class="prettyprint lang-bash">lib
└── tasks
├── recalculate_badges_for_users.rake
├── migrate_users.rake
├── migrate_topics.rake
├── migrate_questions.rake
├── migrate_answers.rake
├── recalculate_best_answer.rake
├── topic_accessible_by_url.rake
├── invalid_questions.rake
├── remove_duplicated_topics.rake
├── calculate_last_activity_for_question.rake
├── ...
├── clean_votes.rake
└── cache_visits.rake
</code></pre>
<p>Although the file name has an intention revealing name, having 30 or more rake tasks on the same folder makes hard to indetify quickly which rake belongs to which resource.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Every rake task perform operations over a resource or several resources (but it always works around a main resource). Identifying this main resource helps us building a good file structure and group our rake task under namespaces and folders.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/topics.rake
namespace :migrate do
desc 'Migrate topics from legacy database to new database'
task topics: :environment do
...
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/users.rake
namespace :migrate do
desc 'Migrate users from legacy database to new database'
task users: :environment do
...
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/migrate/questions.rake
namespace :migrate do
desc 'Migrate questions from legacy database to new database'
task questions: :environment do
...
end
end
</code></pre>
<p>The main resource here it’s the <strong>migration</strong>, so we used <code class="prettyprint">migrate</code> namespace and create a folder under tasks folder named as the namespace.</p>
<p>And so on with the remaining tasks.</p>
<p><strong>File Structure:</strong></p>
<p>This is how our rake file structure will look like when applying this rule over all the rake tasks.</p>
<pre><code class="prettyprint lang-bash">lib
└── tasks
├── migrate
│ ├── users.rake
│ ├── topics.rake
│ ├── questions.rake
│ └── answers.rake
├── users
│ ├── recalculate_badges.rake
│ └── cache_visits.rake
├── ...
├── questions
│ ├── recalculate_best_answer.rake
│ ├── topic_accessible_by_url.rake
│ ├── clean_votes.rake
│ ├── log_invalid.rb
│ └── calculate_last_activity.rake
└── topics
└── remove_duplicated.rb
</code></pre>
<p>Now our files are more organized and it’s easier to find an specific task.</p>
<h2 id="isolating-your-task-using-a-class_2">Isolating Your Task Using a Class <a class="head_anchor" href="#isolating-your-task-using-a-class_2">#</a>
</h2>
<p>I’ll start with an example because it make easy to understand the concept.</p>
<p>We have an App kind of StackOverflow, our users can make questions, answer them, leave comments and so, and we already have a lot of information in our database. Sunddenly we decided to implement a Badge System in our app.</p>
<p>Now that we developed the Badge System, we only need to recalculate the badges for every user. Now it’s the time to use a rake task.</p>
<h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
User.find_each do |user|
# Grants teacher badge
if user.answers.with_votes_count_greater_than(5).count >= 1
user.grant_badge('teacher')
end
...
# Grants favorite question badge
user.questions.find_each do |question|
if question.followers_count >= 25
user.grant_badge('favorite question') && break
end
end
# Grants stellar question badge
user.questions.find_each do |question|
if question.followers_count >= 100
user.grant_badge('stellar question') && break
end
end
end
end
end
</code></pre>
<p>This task may seem simple to understand but it has a lot of problems:</p>
<ul>
<li>It’s hard to test.</li>
<li>We have a lot of logic that is not isolated.</li>
<li>We have duplication.</li>
<li>This task is very large and almost imposible to read. Imagine that you have 25 badges and one condition per badge. This task would have more than 150 lines.</li>
</ul>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Now that we pointed all things that’s wrong with this task, let’s fix it. We’ll extract all the logic and move it to a Service Object.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
User.find_each do |user|
RecalculateBadges.new(user).all
end
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/services/recalculate_badges.rb
class RecalculateBadges
attr_reader :user, :questions, :answers
def initialize(user)
@user = user
@questions = user.questions
@answers = user.answers
end
def all
teacher
favorite_question
stellar_question
end
def teacher
...
grant_badge('teacher')
end
def favorite_question
question_followers_count_badge(25, 'favorite question')
end
def stellar_question
question_followers_count_badge(100, 'stellar question')
end
private
def grant_badge(badge_name)
return unless badge_name
user.grant_badge(badge_name)
end
def question_followers_count_badge(followers_count, badge_name)
...
grant(badge_name)
end
end
</code></pre>
<p>Now we extracted all the logic to an specific class you will notice the following benefits:</p>
<ul>
<li>Our rake’s logic is easier to read and understand, now every method on our RecalculateBadges class represents a badge and we have the <code class="prettyprint">all</code> method which triggers all badge methods.</li>
<li>We can test every badge logic on isolation and it will be very easy to test.</li>
<li>We removed duplication.</li>
</ul>
<p>There are some important concepts I would like to highlight:</p>
<ul>
<li>For Service Objects always prefer instance methods over class methods, they are much easier to refactor.</li>
<li>Notice that our Service Object performs operation over a single user and not the entire collection, this give us more flexibility if we want to re use this class anywhere else on our application.</li>
</ul>
<h2 id="display-details-about-task-progress-without-b_2">Display Details About Task Progress Without Being Too Verbose <a class="head_anchor" href="#display-details-about-task-progress-without-b_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<p>One of the things that I find very annoying is displaying irrelevant information when running a task. This makes harder to monitor the progress and only pollutes your terminal.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
User.find_each do |user|
puts "#{user.first_name} #{user.last_name} - #{user.email}"
RecalculateBadges.new(user).all
end
end
end
</code></pre>
<p>Terminal Output:</p>
<pre><code class="prettyprint lang-bash">Mario Krols - mkrols@gmail.com
Kristen Delt - kdelt@gmail.com
Monica Lewinsky - mlewinsky@clinton.com
...
Fake User - fuser@outlook.com
</code></pre>
<p>As you can see this task will display user’s first name, last name and email, and it will not notify you about any errors or how many users have processed so far. Also on this particular case, we don’t need to display user’s first name or last name, they are polluting our terminal.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Now lets say that <code class="prettyprint">RecalculateBadges#all</code> method returns true if badges recalculated successfully and returns false and saves the errors on an instance variable <code class="prettyprint">@errors</code> if it fails. Also we have a new instance method <code class="prettyprint">errors</code> which returns the value of <code class="prettyprint">@errors</code> as a string.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
users_count = User.count
User.find_each.with_index do |user, index|
recaulculate_badges = RecalculateBadges.new(user)
if recalculate_badges.all
puts "#{index}/#{users_count} - #{user.email}".green
else
puts "#{index}/#{users_count} - #{user.email} - #{recalculate_badges.errors}".red
end
end
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/services/recalculate_badges.rb
class RecalculateBadges
attr_reader :user, :questions, :answers, :errors
def initialize(user)
@user = user
@questions = user.questions
@answers = user.answers
end
def all
if user.can_receive_badges?
teacher
favorite_question
stellar_question
true
else
@errors = user.badges_validation_messages
false
end
end
def teacher
...
grant_badge('teacher')
end
def favorite_question
question_followers_count_badge(25, 'favorite question')
end
def stellar_question
question_followers_count_badge(100, 'stellar question')
end
private
def grant_badge(badge_name)
return unless badge_name
user.grant_badge(badge_name)
end
def question_followers_count_badge(followers_count, badge_name)
...
grant_badge(badge_name)
end
end
</code></pre>
<p>Terminal Output:</p>
<pre><code class="prettyprint">1/100 - mkrols@gmail.com
2/100 - kdelt@gmail.com
3/100 - mlewinsky@clinton.com - This user can't receive any badge because it's blocked
...
100/100 - fuser@outlook.com
</code></pre>
<p>This task display all necessary details without being too verbose. Now you can see:</p>
<ul>
<li>The user being processed and how much left to be processed.</li>
<li>The email of the user that was processed so you can identify them by a unique attribute other than the id.</li>
<li>A detailed error message in case of failure.</li>
</ul>
<p>Remember to display only the information you need, anything else will end up being too verbose and will only make harder to read and understand the information you’re displaying.</p>
<p><strong>Note:</strong> If you are not interested on displaying any kind of information, a useful output will be printing a green dot for every element processed successfully and a red X for every element that fails, this way you’ll know that the task is running.</p>
<pre><code class="prettyprint">.................X...........X.......XX........X.
</code></pre>
<h2 id="always-use-a-log-file_2">Always Use a Log File <a class="head_anchor" href="#always-use-a-log-file_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<p>Imagine now that our application has 100.000 users and we need to recalculate badges for everyone.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
users_count = User.count
User.find_each.with_index do |user, index|
recaulculate_badges = RecalculateBadges.new(user)
if recalculate_badges.all
puts "#{index}/#{users_count} - #{user.email}".green
else
puts "#{index}/#{users_count} - #{user.email} - #{recalculate_badges.errors}".red
end
end
end
end
</code></pre>
<p>The main problem you have here it’s that you may need infinite scroll on your terminal to keep track, also processing 100.000 will take some time and you probably won’t pay attention all the time. Also how about if you are running this task remotely or in background, you won’t be able to see any information.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>I think having a log file is a MUST when writing rake tasks. This helps you to keep track for every task triggered, consult it every time you want to and share it with anyone easily.</p>
<pre><code class="prettyprint lang-ruby"># lib/tasks/users/recalculate_badges.rake
namespace :users do
desc 'Recalculates Badges for All Users'
task recalculate_badges: :environment do
log = ActiveSupport::Logger.new('log/users_recalculate_badges.log')
start_time = Time.now
users_count = User.count
log.info "Task started at #{start_time}"
User.find_each.with_index do |user, index|
recaulculate_badges = RecalculateBadges.new(user)
if recalculate_badges.all
log.info "#{index}/#{users_count} - #{user.email}"
else
log.info "#{index}/#{users_count} - #{user.email} - #{recalculate_badges.errors}"
end
end
end_time = Time.now
duration = (start_time - end_time) / 1.minute
log.info "Task finished at #{end_time} and last #{duration} minutes."
log.close
end
end
</code></pre>
<p>Tracking start time, end time and duration is very important. If you have a rake task that you run every one hour and your rake task takes one and a half hour to be completed, your task will overlap with the same task and you’ll end up running out of memory on your server for example.</p>
<p><strong>Note:</strong> Besides using a log file, you should also print some output, that way you’ll know that your rake it’s working. I didn’t add any output on this example because I wanted to keep this example as simple as possible.</p>
tag:edelpero.svbtle.com,2014:Post/most-common-mistakes-on-legacy-rails-apps2014-07-15T09:00:47-07:002014-07-15T09:00:47-07:00Most Common Mistakes On Legacy Rails Apps<p>Lately I’ve been supporting several legacy projects. </p>
<p>As many of you may know, working on legacy projects sucks most of the time, usually because most of the code is ugly and difficult to understand or read.</p>
<p>I decided to make a list of common bad practices, or what I consider bad practices, and how to improve the code or avoid this bad practices.</p>
<h2 id="summary_2">Summary <a class="head_anchor" href="#summary_2">#</a>
</h2>
<ul>
<li>Using Query Methods Outside Models</li>
<li>Using Logic Inside The Views</li>
<li>Using Meaningless Names On Variables Or Methods</li>
<li>Using Unless Or Negative Expressions On Conditionals</li>
<li>Not Using Tell, Don’t Ask</li>
<li>Using Complex Conditionals</li>
<li>Using “self.” On Models Instace Methods When There’s No Need To</li>
<li>Using Conditionals And Returning The Condition</li>
<li>Using Inline CSS In Your Views</li>
<li>Using JavaScript Inside Your Views</li>
<li>Passing Method Call As An Argument When Calling A Method</li>
<li>Not Isolating Rake Tasks Using Classes</li>
<li>Not Following Sandi Metz’ Rules</li>
</ul>
<h2 id="using-query-methods-outside-models_2">Using Query Methods Outside Models <a class="head_anchor" href="#using-query-methods-outside-models_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.where(active: true).order(:last_login_at)
end
end
</code></pre>
<p>This code is not reusable or easy to test. If you want to look for all active users and order them again somewhere else on your code, you’ll end up duplicating code.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Instead of using query methods on your controllers, we just isolate them using scopes on your model as the example below. This makes the code reusable, easier to test and read.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
scope :active, -> { where(active: true) }
scope :by_last_login_at, -> { order(:lasst_login_at) }
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
@users = User.active.by_last_login_at
end
end
</code></pre>
<p>Everytime you’re about to use <code class="prettyprint">where</code>, <code class="prettyprint">order</code>, <code class="prettyprint">joins</code>, <code class="prettyprint">includes</code>, <code class="prettyprint">group</code>, <code class="prettyprint">having</code> or some other query method, remember to use them inside your models.</p>
<h2 id="using-logic-inside-the-views_2">Using Logic Inside The Views <a class="head_anchor" href="#using-logic-inside-the-views_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-html"><!-- app/views/posts/show.html.erb -->
...
<h2>
<%= "#{@comments.count} Comment#{@comments.count == 1 ? '' : 's'}" %>
</h2>
...
</code></pre>
<p>This small piece of code might seem not causing harm at first but this makes the HTML a bit complicated to read and it’s for sure that if you added one piece of logic in the view, you’ll end up adding more logic in the future. The other problem this code presents it’s that we can’t reuse it or test it in isolation.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Isolate the logic using Rails’ helpers.</p>
<pre><code class="prettyprint lang-ruby"># app/helpers/comments_helper.rb
module CommentsHelper
def comments_count(comments)
"#{comments.count} Comment#{comments.count == 1 ? '' : 's'}"
end
end
</code></pre>
<pre><code class="prettyprint lang-html"><!-- app/views/posts/show.html.erb -->
<h2>
<%= comments_count(@comments) %>
</h2>
</code></pre>
<p>The first benefit we get to see at first sight is that the HTML is easier to read. Also we can re use the code and test easily.</p>
<p>Another good aproach to avoid this problem is using decorators. Please refer to <a href="https://github.com/drapergem/draper">draper gem</a>.</p>
<p><strong>Note:</strong> You can use pluralize method to achieve the same result. I just used this code to make a point.</p>
<h2 id="using-meaningless-names-on-variables-or-metho_2">Using Meaningless Names On Variables Or Methods <a class="head_anchor" href="#using-meaningless-names-on-variables-or-metho_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/models/topic.rb
class Topic < ActiveRecord::Base
def self.r_topics(questions)
rt = []
questions.each do |q|
topics = q.topics
topics.each do |t|
if t.enabled?
rt << t
end
end
end
Topic.where(id: rt)
end
end
</code></pre>
<p>The main problem with this kind of legacy code is that you spend most of time trying to figure what does the code do. What does method like <code class="prettyprint">r_topics</code> do, or variables like <code class="prettyprint">rt</code> means. Other variables meaning like the one used on blocks can be deducted, but they do not reveal the intention at first sight.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Always use intention revealing names when naming methods or variables. This will help other developers to understand your code easily.</p>
<pre><code class="prettyprint lang-ruby"># app/models/topic.rb
class Topic < ActiveRecord::Base
def self.related(questions)
related_topics = []
questions.each do |question|
topics = question.topics
topics.each do |topic|
if topic.enabled?
related_topics << topic
end
end
end
Topic.where(id: related_topics)
end
end
</code></pre>
<p>The benefits of this approach are:</p>
<ul>
<li>The first time you read the method name, you may have an idea of what the method will return. A collection of topics related to a collection of questions.</li>
<li>Now you know that <code class="prettyprint">related_topics</code> is an array which stores the collection of the topics related to a collection of questions. In the previous code, it wasn’t clear what was the meaning of <code class="prettyprint">rt</code>.</li>
<li>Using <code class="prettyprint">topic</code> instead of <code class="prettyprint">t</code> and <code class="prettyprint">question</code> instead of <code class="prettyprint">q</code>, makes your code easier to read the first time, because you don’t have to do <strong><em>Mental Compilation</em></strong>. Now you just read it and the code speaks for itself.</li>
</ul>
<h2 id="using-unless-or-negative-expressions-on-condi_2">Using Unless Or Negative Expressions On Conditionals <a class="head_anchor" href="#using-unless-or-negative-expressions-on-condi_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/services/charge_user.rb
class ChargeUser
def self.perform(user, amount)
return false unless user.enabled?
PaymentGateway.charge(user.account_id, amount)
end
end
</code></pre>
<p>This code may not be difficult to understand at all, but using <code class="prettyprint">unless</code> or <code class="prettyprint">negative expressions</code> will add a little additional complexity to the code, because you have to do <strong><em>Mental Compilation</em></strong>.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>The example above it’s easier to read if we use <code class="prettyprint">if</code> or <code class="prettyprint">positive expressions</code>.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def disabled?
!enabled?
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/services/charge_user.rb
class ChargeUser
def self.perform(user, amount)
return false if user.disabled?
PaymentGateway.charge(user.account_id, amount)
end
end
</code></pre>
<p>Don’t you think this way it’s easier to read? Prefer the use of <code class="prettyprint">if</code> instead of <code class="prettyprint">unless</code> and <code class="prettyprint">positive expressions</code> over <code class="prettyprint">negative expressions</code>. Remember to create opposite methods if you don’t have one, just like we did on the User model.</p>
<h2 id="not-using-tell-don39t-ask_2">Not Using Tell, Don’t Ask <a class="head_anchor" href="#not-using-tell-don39t-ask_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def enable!
update(enabled: true)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/users_controller.rb
class UsersController < ApplicationController
def enable
user = User.find(params[:id])
if user.disabled?
user.enable!
message = "User enabled"
else
message = "User already disabled"
end
redirect_to user_path(user), notice: message
end
end
</code></pre>
<p>The problem with this is that you’re adding control logic where it doesn’t belong. You are asking if a user is disabled, and if that’s the case, then it should enable that user.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>A good approach would be to move that control logic inside our <code class="prettyprint">enable!</code> method.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def enable!
if disabled?
update(enabled: true)
end
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/users_controller.rb
class UsersController < ApplicationController
def enable
user = User.find(params[:id])
if user.enable!
message = "User enabled"
else
message = "User already disabled"
end
redirect_to user_path(user), notice: message
end
end
</code></pre>
<p>Now our controller doesn’t need to know which conditions needs to meet a user to get enabled. The responsable of that is the User model and the <code class="prettyprint">enable!</code> method.</p>
<h2 id="using-complex-conditionals_2">Using Complex Conditionals <a class="head_anchor" href="#using-complex-conditionals_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/controllers/posts_controller.rb
class PostsController < ApplicationController
def destroy
post = Post.find(params[:id])
if post.enabled? && (user.own_post?(post) || user.admin?)
post.destroy
message = "Post destroyed."
else
message = "You're not allow to destroy this post."
end
redirect_to posts_path, notice: message
end
end
</code></pre>
<p>This conditional is asking too many things, when it should really be asking for one thing. <strong>Can this user destroy this post?</strong>.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Now we realised that a user needs to own a post or be an admin to destroy that post, and also that post needs to be enabled. Extracting that conditional to a method which we can re use later would be the best way to go.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def can_destroy_post?(post)
post.enabled? && (own_post?(post) || admin?)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/posts_controller.rb
class PostsController < ApplicationController
def destroy
post = Post.find(params[:id])
if user.can_destroy_post?(post)
post.destroy
message = "Post destroyed."
else
message = "You're not allow to destroy this post."
end
redirect_to posts_path, notice: message
end
end
</code></pre>
<p>Whenver you have a conditional that uses <code class="prettyprint">&&</code> or <code class="prettyprint">||</code> extract that conditional into a method which you can re use later.</p>
<h2 id="using-quotselfquot-on-models-instace-methods_2">Using “self.” On Models Instace Methods When There’s No Need To <a class="head_anchor" href="#using-quotselfquot-on-models-instace-methods_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def full_name
"#{self.first_name} #{self.last_name}"
end
end
</code></pre>
<p>This code it’s simple to read but there’s no need to use <code class="prettyprint">self.</code>, removing <code class="prettyprint">self.</code> will make the code easier to read and the code will keep working.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>On your models, <code class="prettyprint">self.</code> is only needed on instance methods when you need to make assignments, otherwise, using <code class="prettyprint">self.</code> will make your code a bit complicated to read.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def full_name
"#{first_name} #{last_name}"
end
end
</code></pre>
<h2 id="using-conditionals-and-returning-the-conditio_2">Using Conditionals And Returning The Condition <a class="head_anchor" href="#using-conditionals-and-returning-the-conditio_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def full_name
if name
name
else
"No name"
end
end
end
</code></pre>
<p>or</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def full_name
name ? name : "No name"
end
end
</code></pre>
<p>The problem with this codes is that they add control when there’s no need to.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>There’s an easier way to get the same result.</p>
<pre><code class="prettyprint lang-ruby"># app/models/user.rb
class User < ActiveRecord::Base
def full_name
name || "No name"
end
end
</code></pre>
<p>Basically this code returns the name if it’s different from false or nil, otherwise, it will return “No name”.</p>
<p><code class="prettyprint">||</code> and <code class="prettyprint">&&</code> are very powerful operators which can help you to improve your code quality if you use it right.</p>
<h2 id="using-inline-css-in-your-views_2">Using Inline CSS In Your Views <a class="head_anchor" href="#using-inline-css-in-your-views_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-html"><!-- app/views/projects/show.html.erb -->
...
<h3 style="font-size:20px;letter-spacing:normal;color:#95d60a;line-height:100%;margin:0;font-family:'Proxima Nova';">
SECRET PROJECT
</h3>
...
</code></pre>
<p>Here we have only one tag which is receiving all that style. Now, imagine all your tags receiving inline styling. This will turn our HTML into an unreadable document and not only that, we will have to duplicate our styling code every time we have to introduce another <code class="prettyprint">h3</code> element with the same style.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<pre><code class="prettyprint lang-css">// app/assets/stylesheets/application.css
.project-title {
font-size: 20px;
letter-spacing: normal;
color: #95d60a;
line-height: 100%;
margin: 0;
font-family:'Proxima Nova';
}
</code></pre>
<pre><code class="prettyprint lang-html"><!-- app/views/projects/show.html.erb -->
...
<h3 class="project-title">
SECRET PROJECT
</h3>
...
</code></pre>
<p>Now we can re use our style on any elements we want and our HTML is more readable and easy to understand.</p>
<p><strong><u>Note</u>:</strong> This example is pretty simple, you should consider splitting your CSS into several small files and use your application.css to load the css your need. Also you can and you should use inline CSS for email templates only.</p>
<h2 id="using-javascript-inside-your-views_2">Using JavaScript Inside Your Views <a class="head_anchor" href="#using-javascript-inside-your-views_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-html"><!-- app/views/questions/show.html.erb -->
...
<textarea rows="4" cols="50" class='wysihtml5'>
Insert your question details here.
</textarea>
...
<script>
$(document).ready(function(){
$('textarea.wysihtml5').wysihtml5({
"font-styles": true, //Font styling, e.g. h1, h2, etc. Default true.
"emphasis": true, //Italics, bold, etc. Default true.
"lists": true, //(Un)ordered lists, e.g. Bullets, Numbers. Default true.
"html": false, //Button which allows you to edit the generated HTML. Default false.
"link": true, //Button to insert a link. Default true.
"image": true, //Button to insert an image. Default true.
"color": true //Button to change color of font. Default true.
});
});
<script>
</code></pre>
<p>This is bad because this logic gets attached to this specific view. You can’t re use this code.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>Rails has it own place to store and organize all your javascript, the <code class="prettyprint">app/assets/javascripts/</code> path.</p>
<pre><code class="prettyprint lang-javascript">// app/assets/javascripts/application.js
...
$(document).ready(function(){
$('textarea.wysihtml5').wysihtml5({
"font-styles": true, //Font styling, e.g. h1, h2, etc. Default true.
"emphasis": true, //Italics, bold, etc. Default true.
"lists": true, //(Un)ordered lists, e.g. Bullets, Numbers. Default true.
"html": false, //Button which allows you to edit the generated HTML. Default false.
"link": true, //Button to insert a link. Default true.
"image": true, //Button to insert an image. Default true.
"color": true //Button to change color of font. Default true.
});
});
...
</code></pre>
<pre><code class="prettyprint lang-html"><!-- app/views/questions/show.html.erb -->
...
<textarea rows="4" cols="50" class='wysihtml5'>
Insert your question details here.
</textarea>
...
</code></pre>
<p>Now we can re use our code in any view. We just need to add a textarea element with the wysihtml5 class and our javascript code will be executed.</p>
<p><strong><u>Note</u>:</strong> This example is pretty simple, you should consider splitting your JavaScript into several small files and use your application.js to load the JavaScript your need. Also, if you are using CoffeeScript instead of JavaScript, please, be consistent and stick with it, don’t write some code using CoffeeScript and other in JavaScript.</p>
<h2 id="passing-method-call-as-an-argument-when-calli_2">Passing Method Call As An Argument When Calling A Method <a class="head_anchor" href="#passing-method-call-as-an-argument-when-calli_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/services/find_or_create_topic.rb
class FindOrCreateTopic
...
def self.perform(user, name)
find(user, sluggify(name)) || create(user, name)
end
...
end
</code></pre>
<p>The issue with this relies when calling <code class="prettyprint">find</code> and passing as arguments <code class="prettyprint">user</code> and <code class="prettyprint">sluggify</code>method which receives <code class="prettyprint">name</code>as an argument. You might be thinking, what’s the problem with this? I can understand the code perfectly. Yes, the code might be easy to read, but you have to make a little <strong><em>Mental Compilation</em></strong> which I like to avoid every time I can.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>A good way to avoid <strong><em>Mental Compilation</em></strong> when this happens is using variables with meaningful names.</p>
<pre><code class="prettyprint lang-ruby"># app/services/find_or_create_topic.rb
class FindOrCreateTopic
...
def self.perform(user, name)
slug = sluggify(name)
find(user, slug) || create(user, name)
end
...
end
</code></pre>
<p>This way you’ll avoid doing <strong><em>Mental Compilation</em></strong>. Our variable has an intention revealing name, and now when your call the <code class="prettyprint">find</code> method, you know that find is receiving a <code class="prettyprint">user</code> and a <code class="prettyprint">slug</code>.</p>
<h2 id="not-isolating-rake-tasks-using-classes_2">Not Isolating Rake Tasks Using Classes <a class="head_anchor" href="#not-isolating-rake-tasks-using-classes_2">#</a>
</h2><h3 id="bad_3">Bad <a class="head_anchor" href="#bad_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># lib/tasks/recalculate_badges_for_users.rake
namespace :users do
desc "Recalculates Badges for Users"
task recalculate_badges: :environment do
user_count = User.count
User.find_each do |user|
puts "#{index}/#{user_count} Recalculating Badges for: #{user.email}"
if user.questions_with_negative_votes >= 1 || user.answers_with_negative_votes >= 1
user.grant_badge('Critic')
end
user.answers.find_each do |answer|
question = answer.question
next unless answer && question
days = answer.created_at - question.created_at
days_count = (days / 1.day).round
if (days_count >= 60) && (question.vote_count >= 5)
grant_badge('Necromancer') && return
end
end
end
end
end
</code></pre>
<p>There are several problems with this rake task. The main problem is that this rake is very long and difficult to test. It’s not easy to read or understand at first sight. You have to trust that it recalculates the badges for your users because it say so.</p>
<h3 id="good_3">Good <a class="head_anchor" href="#good_3">#</a>
</h3>
<p>The best way to proceed with this is to move all your logic to an specific class. So, lets create a class specific for this job.</p>
<pre><code class="prettyprint lang-ruby"># app/services/recalculate_badge.rb
class RecalculateBadge
attr_reader :user
def initialize(user)
@user = user
end
def grant_citric
if grant_citric?
user.grant_badge('Critic')
end
end
def grant_necromancer
user.answers.find_each do |answer|
question = answer.question
next unless answer && question
if grant_necromancer?(answer, question)
grant_badge('Necromancer') && return
end
end
end
protected
def grant_citric?
(user.questions_with_negative_votes >= 1) ||
(user.answers_with_negative_votes >= 1)
end
def days_count(answer, question)
days = answer.created_at - question.created_at
(days / 1.day).round
end
def grant_necromancer?(answer, question)
(days_count(answer,question) >= 60) &&
(question.vote_count >= 5)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># lib/tasks/recalculate_badges_for_users.rake
namespace :users do
desc "Recalculates Badges for Users"
task recalculate_badges: :environment do
user_count = User.count
User.find_each do |user|
puts "#{index}/#{user_count} Recalculating Badges for: #{user.email}"
task = RecalculateBadge.new(user)
task.grant_citric
task.grant_necromancer
end
end
end
</code></pre>
<p>As you can see, now the rake task is easier to read and you can test every grant badge method on isolation. Also we could reuse this class if we need to. Of course this code could be written in a better way, but lets keep it simple.</p>
<p>Thanks @luislavena for the suggestion of refactoring this example.</p>
<h2 id="not-following-sandi-metz39-rules_2">Not Following Sandi Metz’ Rules <a class="head_anchor" href="#not-following-sandi-metz39-rules_2">#</a>
</h2>
<ol>
<li>Classes can be no longer than one hundred lines of code.</li>
<li>Methods can be no longer than five lines of code.</li>
<li>Pass no more than four parameters into a method. Hash options are parameters.</li>
<li>Controllers can instantiate only one object. Therefore, views can only know about one instance variable and views should only send messages to that object (@object.collaborator.value is not allowed).</li>
</ol>
<p>Check out this article from <a href="http://robots.thoughtbot.com/"><strong>thoughtbot</strong></a>, <a href="http://robots.thoughtbot.com/sandi-metz-rules-for-developers">Sandi Metz’ Rules For Developers</a> for more details about these rules.</p>
tag:edelpero.svbtle.com,2014:Post/github-workflow-contributing-with-open-source-projects2013-11-12T10:00:50-08:002013-11-12T10:00:50-08:00GitHub Workflow: Contributing with Open Source Projects<p>This week I made my first contribution to a ruby open source project, devise, the well known, flexible authentication solution for Rails with Warden.</p>
<p>When working on open source projects it’s very important to have a well defined git workflow. Having a well defined workflow will help you to indentify changes on your code easily, revert changes without losing your work, test your ideas without putting your main project at risk, be more organized and so.</p>
<p>You may find several guides talking about git workflow and different ways to accomplish what this post tries to explain. Bear in mind that given git’s flexibility you can achieve the same results in different ways.</p>
<h4 id="summary_4">Summary <a class="head_anchor" href="#summary_4">#</a>
</h4>
<ol>
<li>Fork the project you want to collaborate with</li>
<li>Clone your project’s fork to your local drive</li>
<li>Add the original project git url to your fork’s remote list</li>
<li>Create a new branch and commit your changes</li>
<li>Pull the changes from the original project’s repository</li>
<li>Rebase your master with your new branch and fix conflicts if necessary</li>
<li>Push your new branch</li>
<li>Go to the original project’s repository and create a new pull request</li>
</ol>
<h4 id="1-fork-the-project-you-want-to-collaborate-wi_4">1. Fork the project you want to collaborate with <a class="head_anchor" href="#1-fork-the-project-you-want-to-collaborate-wi_4">#</a>
</h4>
<p>Go to the project repository’s web page and! click on the <strong>Fork</strong> button.</p>
<p><img src="http://i.imgur.com/V4lQhA6.png" alt=""></p>
<h4 id="2-clone-your-project39s-fork-to-your-local-dr_4">2. Clone your project’s fork to your local drive <a class="head_anchor" href="#2-clone-your-project39s-fork-to-your-local-dr_4">#</a>
</h4>
<p>Go to your project’s fork and you’ll find the <strong>Clone Section</strong>, that looks like this:</p>
<p><img src="http://oi42.tinypic.com/2laznmb.jpg" alt=""></p>
<p>Copy the <strong>SSH</strong> url. GitHub suggest you to use the <strong>SSH</strong> over the others, but you could use GitHub Mac or Windows client or whatever solution fits your needs.</p>
<p>Now that you’ve copied the <strong>SSH</strong> url, go to the console and do:</p>
<pre><code class="prettyprint lang-bash">$ git clone git@github.com:<username>/<project>.git
# Clones your fork of the repository into the current directory in terminal
#
# <username> it's your github's username
# <project> it's the name of the github's project
</code></pre>
<h4 id="3-add-the-original-project-git-url-to-your-fo_4">3. Add the original project git url to your fork’s remote list <a class="head_anchor" href="#3-add-the-original-project-git-url-to-your-fo_4">#</a>
</h4>
<p>When a repository is cloned, it has a default remote called <code class="prettyprint">origin</code> that points to your fork on GitHub, not the original repository it was forked from.</p>
<p>To keep track of the original repository, you need to add another remote named <code class="prettyprint">upstream</code> (that’s the convention).</p>
<p>You need to do this in case you need to retrieve new changes from the original project’s repository.</p>
<pre><code class="prettyprint lang-bash">$ cd <project>
# Changes the active directory in the prompt to the newly cloned project directory
<project> $ git remote add upstream https://github.com/<username>/<project>.git
# Assigns the original repository to a remote called "upstream"
#
# <username> it's the github's username from the original project's owner
# <project> it's the name of the github's project
<project> $ git fetch upstream
# Pulls in changes not present in your local repository, without modifying your files
</code></pre>
<h4 id="4-create-a-new-branch-and-commit-your-changes_4">4. Create a new branch and commit your changes <a class="head_anchor" href="#4-create-a-new-branch-and-commit-your-changes_4">#</a>
</h4>
<p>Branching allows you to build new features or test out ideas without putting your main project at risk.</p>
<p>In git, branch is a sort of bookmark that references the last commit made in the branch. This makes branches very small and easy to work with.</p>
<pre><code class="prettyprint lang-bash"><project> $ git checkout -b <branch>
# Creates and positions you on that new branch
#
# <branch> it's the name of the branch that will store all the changes you make
<project> $ git add .
# Tracks your changes
<project> $ git commit -m 'Some changes'
# Commits your changes
</code></pre>
<p>Now we can start developing our new feature.</p>
<h4 id="5-pull-the-changes-from-the-original-project3_4">5. Pull the changes from the original project’s repository <a class="head_anchor" href="#5-pull-the-changes-from-the-original-project3_4">#</a>
</h4>
<p>After we finished developing our new feature, we need to check if they were any updates on the original project’s repository and get the latest version of the master branch.</p>
<pre><code class="prettyprint lang-bash"><project> $ git checkout master
# Make sure before pulling changes that you are on master branch
<project> $ git pull --rebase upstream master
# Updates our master branch with the latest version of the original project's master branch
</code></pre>
<h4 id="6-rebase-your-master-with-your-new-branch-and_4">6. Rebase your master with your new branch and fix conflicts if necessary <a class="head_anchor" href="#6-rebase-your-master-with-your-new-branch-and_4">#</a>
</h4>
<p>Now that we have our master branch up to date, we need to rebase it with our new branch where our new feature is.</p>
<pre><code class="prettyprint lang-bash"><project> $ git checkout <new branch>
# Make sure before rebasing changes that you are on new branch
<project> $ git rebase master
# This will rebase your new branch with your master branch
</code></pre>
<p>If they were any conflicts during the rebase process, solve the conflicts and commit the fix.</p>
<h4 id="7-push-your-new-branch_4">7. Push your new branch <a class="head_anchor" href="#7-push-your-new-branch_4">#</a>
</h4>
<p>So now that we have our new branch up to date, we are going to push it to GitHub.</p>
<pre><code class="prettyprint lang-bash"><project> $ git checkout <new branch>
# Make sure before pushing changes that you are on new branch
<project> $ git push -u origin <new branch>
# Pushes your local new branch to your fork's repository
#
# -u option tells git to link your local branch repository to the remote branch you
# created, you only need to do this the first time you push, for future pushes,
# just write 'git push' and git will know what to do
#
# <new branch> it's the name of the branch you were working on
</code></pre>
<h4 id="8-go-to-the-original-project39s-repository-an_4">8. Go to the original project’s repository and create a new pull request <a class="head_anchor" href="#8-go-to-the-original-project39s-repository-an_4">#</a>
</h4>
<p>After you pushed your new branch to GitHub. visit the repository you pushed to. Select your new branch and click on <strong>Compare & review</strong> button.</p>
<p><img src="http://oi40.tinypic.com/wqy4pu.jpg" alt="This is an example of a pull request of our 'alias_methods_' branch to devise"></p>
<p>You’ll land right onto the compare page. You can click Edit at the top to pick a new branch to merge in, using the <strong>Head Fork</strong> and <strong>Compare</strong> dropdown.</p>
<p><img src="http://oi41.tinypic.com/10zzgog.jpg" alt=""><br>
<img src="http://oi44.tinypic.com/whhffa.jpg" alt=""></p>
<p>Select the target repository and branch your branch should be merged to, using the <strong>Base Fork</strong> and <strong>Base</strong> dropdown.</p>
<p><img src="http://oi44.tinypic.com/whhffa.jpg" alt=""></p>
<p>Review your proposed changes and click on <strong>Click to create a pull request for this comparison</strong></p>
<p><img src="http://oi40.tinypic.com/1zx34vl.jpg" alt=""></p>
<p>Enter a title and description for your pull request and click <strong>Send pull request</strong>.</p>
<p><img src="http://oi40.tinypic.com/otjn7a.jpg" alt=""></p>
<p>That’s pretty much how it goes. Remember that you can do the same in different ways. Hope it helps you.</p>
<h4 id="references_4">References <a class="head_anchor" href="#references_4">#</a>
</h4>
<p><a href="https://help.github.com/articles/fork-a-repo">GitHub: Fork a Repo</a></p>
tag:edelpero.svbtle.com,2014:Post/homemade-decorators2013-11-03T11:41:14-08:002013-11-03T11:41:14-08:00Homemade Decorators<p>Ever since I started writing Rails applications, people always told me to use Decorators instead of Helpers.</p>
<h3 id="so-what39s-a-decorator_3">So what’s a Decorator? <a class="head_anchor" href="#so-what39s-a-decorator_3">#</a>
</h3>
<p>Decorator is a design pattern. Its intent to attach additional responsabilities to an object dynamically. One common use of Decorators on Rails is to group view logic of our Models. This way we’ll keep the business logic in our Models separated from our view logic, otherwise will be breaking the Single Reponsability Principle. You can think of it, as a view logic’s wrapper for our Model.</p>
<h3 id="how-does-it-work_3">How does it work? <a class="head_anchor" href="#how-does-it-work_3">#</a>
</h3>
<p>First thing we are going to do, is creating our Decorator class which should inherit from SimpleDelegator class which comes built-in with ruby:</p>
<pre><code class="prettyprint lang-ruby">#app/decorators/user_decorator.rb
class UserDecorator < SimpleDelegator
end
</code></pre>
<p>Inheriting from SimpleDelegator will make that all methods called from our UserDecorator instance will be delegated to the Object passed as argument when we created the decorator instance. Just like this:</p>
<pre><code class="prettyprint lang-ruby"> user = User.new(first_name: 'John', last_name: 'Smith', age: '30')
user_decorator = UserDecorator.new(user)
user.first_name # => 'John'
user_decorator.first_name # => 'John'
</code></pre>
<p>Now that we created our UserDecorator class, lets add a new method for displaying our user’s full name.</p>
<pre><code class="prettyprint lang-ruby">#app/decorators/user_decorator.rb
class UserDecorator < SimpleDelegator
def full_name
"#{first_name} #{last_name}"
end
end
</code></pre>
<p>So now, in the users controllers we’ll decorate the user model instance we found.</p>
<pre><code class="prettyprint lang-ruby">#app/decorators/user_decorator.rb
class UsersController < ApplicationController
def show
user = User.find(params[:id])
@user = UserDecorator.new(user)
end
end
</code></pre>
<p>And finally in our view file, we’ll display our user’s full_name:</p>
<pre><code class="prettyprint lang-html">#app/views/users/show.html.erb
<h1>User Info</h1>
User's Fullname: <%= @user.full_name %>
User's Age: <%= @user.age %>
</code></pre>
<h3 id="that39s-all-what-decorators-can-do_3">That’s all what decorators can do? <a class="head_anchor" href="#that39s-all-what-decorators-can-do_3">#</a>
</h3>
<p>Well, not really. Decorators are also useful when you want to change the behavior of certain method of an object. Lets say for example that we have two kind of calendar events, events and submitted events. The only difference between them is that the submitted events stores the user who submitted the event, so we are going to store events and submitted events on the same place.</p>
<p>First, lets define our event model:</p>
<pre><code class="prettyprint lang-ruby">#app/models/event.rb
class Event < ActiveRecord::Base
belongs_to :user # Returns the user who submitted the event if it's a submitted kind otherwise returns nil
end
</code></pre>
<p>Now lets create our SubmittedEvent class, only this time we’ll loose the Decorator from the name of the class and we’ll store this class on the models’ folder:</p>
<pre><code class="prettyprint lang-ruby">#app/models/submitted_event.rb
class SubmittedEvent < SimpleDelegator
attr_reader :user
def initialize(user)
@user = user
event = Event.new(title: 'submitted event')
super(event) # This will tell SimpleDelegator to delegate all methods to event
end
def save
self.user = user # Associates the submitted event with a user
super # Calls the parent's object (that would be Event model) save method
end
end
</code></pre>
<p>So now that we have our SubmittedEvent’s class, lets create a submitted event:</p>
<pre><code class="prettyprint lang-ruby"># User who sent the event
user = User.create(first_name: 'John', last_name: 'Smith', age: '30')
# Creates submitted event instance and passes the user who sent the event as an argument
submitted_event = SubmittedEvent.new(user)
# Tells the submitted event to associate this event with the user who sent the event
# and then calls the Event model save method
submitted_event.save
</code></pre>
<h3 id="conclusion_3">Conclusion <a class="head_anchor" href="#conclusion_3">#</a>
</h3>
<p>Decorators are very useful sometimes to extract logic from your models or controllers. Remember that you don’t want to end up having god classes, fat models or fat controllers.</p>
<h3 id="resources_3">Resources <a class="head_anchor" href="#resources_3">#</a>
</h3>
<ul>
<li>There is a pretty good gem to work with Decorators named <a href="https://github.com/drapergem/draper/">Draper</a>, it also has some cool features and works great with Rails. I suggest you to read the documentation and give it a try.</li>
<li>
<a href="http://www.ruby-doc.org/stdlib-1.9.3/libdoc/delegate/rdoc/SimpleDelegator.html">SimpleDelegator</a> Documentation</li>
<li><a href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator Pattern</a></li>
</ul>
tag:edelpero.svbtle.com,2014:Post/strong-parameters-the-right-way2013-10-19T11:52:43-07:002013-10-19T11:52:43-07:00Strong Parameters The Right Way<p>StrongParameters is a great gem and it comes with Rails 4 by default. Currently, there are two patterns to work with your attributes.</p>
<h3 id="1-creating-a-private-method-on-your-controlle_3">1. Creating a private method on your controller which returns the whitelisted attributes. <a class="head_anchor" href="#1-creating-a-private-method-on-your-controlle_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/controllers/people_controller.rb
class PeopleController < ActionController::Base
def update
person = current_account.people.find(params[:id])
person.update_attributes!(person_params)
redirect_to person
end
private
def person_params
params.require(:person).permit(:name, :age)
end
end
</code></pre>
<h5 id="pros_5">Pros <a class="head_anchor" href="#pros_5">#</a>
</h5>
<ol>
<li>If your person_params logic is simple as the example shows. That’s pretty much, just call the method and it will do the job.</li>
</ol>
<h5 id="cons_5">Cons <a class="head_anchor" href="#cons_5">#</a>
</h5>
<p>If your person_params logic grows because, let say you want to permit certain params attributes if your user is an admin and another params attributes if it’s just a regular user:</p>
<ol>
<li>You’ll be adding more complexity to your controller.</li>
<li>You wont be able to reuse these logic.</li>
<li>Your controller will be harder to test.</li>
</ol>
<h3 id="2-extracting-your-params-logic-into-a-class_3">2. Extracting your params logic into a class. <a class="head_anchor" href="#2-extracting-your-params-logic-into-a-class_3">#</a>
</h3>
<pre><code class="prettyprint lang-ruby"># app/models/permitted_params.rb
class PermittedParams < Struct.new(:params)
def person
valid_keys = [:name, :email, :message]
params.slice(*valid_keys).require(:person).permit(*valid_keys)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
private
def permitted_params
@permitted_params ||= PermittedParams.new(params)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/people_controller.rb
class PeopleController < ActionController::Base
def update
person = current_account.people.find(params[:id])
person.update_attributes!(permitted_params.person)
redirect_to person
end
end
</code></pre>
<p>These approach, in my opinion is better than the first one. You should checkout the <a href="http://railscasts.com/episodes/371-strong-parameters">StrongParameters’ Railscasts</a> for more deatils if you liked these approach.</p>
<h5 id="pros_5">Pros <a class="head_anchor" href="#pros_5">#</a>
</h5>
<ol>
<li>You’ll decouple your controller’s logic from your params logic, in which case, you’ll keep your controllers dry. </li>
<li>Your controllers will be easier to test.</li>
<li>You’ll avoid code duplication.</li>
</ol>
<h5 id="cons_5">Cons <a class="head_anchor" href="#cons_5">#</a>
</h5>
<p>If you have a lot a resources, because applications usually grows and not the other way:</p>
<ol>
<li>Your PermittedParams class will end up being a huge and will be hard to maintain.</li>
<li>You’ll be breaking the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsability Principle</a>.</li>
</ol>
<h3 id="so-which-is-exactly-the-best-way-to-handle-my_3">So, which is exactly the best way to handle my parameters? <a class="head_anchor" href="#so-which-is-exactly-the-best-way-to-handle-my_3">#</a>
</h3>
<p>The best way to handle your resource params would be to have a PermittedParams class type for each resource. Wouldn’t be better to have your resources params’ logic in separate classes like this?:</p>
<pre><code class="prettyprint lang-ruby"># app/parameters/user_parameters.rb
class UserParameters < Struct.new(:params)
def permit
params.require(:user).permit(:name, :age)
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby">class ApplicationController < ActionController::Base
protect_from_forgery
# Returns an instance of the params class related to the Controller from which was called
def permitted_params
@permitted_params ||= permitted_params_class.new(params)
end
# Returns the params class related to the Controller from which was called
def permitted_params_class
class_name = params[:controller].to_s.singularize
formatted_class_name = class_name.camelcase
@permitted_params_class ||= "#{formatted_class_name}Parameters".constantize
end
end
</code></pre>
<pre><code class="prettyprint lang-ruby"># app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
User.create(permitted_params.permit)
end
end
</code></pre>
<h5 id="pros_5">Pros <a class="head_anchor" href="#pros_5">#</a>
</h5>
<ol>
<li>You’ll decouple your controller’s logic from your params logic, in which case, you’ll keep your controllers dry.</li>
<li>Your controllers will be easier to test.</li>
<li>You’ll avoid code duplication.</li>
<li>Your params classes will be smaller, easier to test and maintain.</li>
<li>Your params classes will not violate the <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle">Single Responsability Principle</a>.</li>
</ol>
<h5 id="cons_5">Cons <a class="head_anchor" href="#cons_5">#</a>
</h5>
<p>Some people might think that this is an over-engineering work if your controllers are simple and you have to deal with params like the first approach I described.</p>
<h3 id="a-hrefhttpsgithubcomedelperoactionparameterac_3">
<a href="https://github.com/edelpero/action_parameter">ActionParameter</a> <a class="head_anchor" href="#a-hrefhttpsgithubcomedelperoactionparameterac_3">#</a>
</h3>
<p>It’s a gem I created to implement this last pattern with some other features. I encourage you to take a look at it and try it, I’m pretty sure it would be helpful.</p>
<h3 id="conclusion_3">Conclusion <a class="head_anchor" href="#conclusion_3">#</a>
</h3>
<p>All three patterns are good, you should choose the one that fits your needs. But bear in mind that applications and their logic always tends to grow and to get more complex.</p>