Git: how to fix your own stupidity?

I guess everybody have experience in deleting files that were not supposed to be deleted and this time git cannot help us, there is no returning to specific commit because we just did… something stupid. What am I talking about?

This:

git add . 
git reset --hard

So we were doing something, we added some new files that we plan to use in the future, but the code we changed does not work and we just want to start from the last commit. So we simply do a reset. Wait! What? What about committing those files? …ups, they are gone!

No they are not, git is awesome! Why?

git fsck --lost-found

fsck verifies the connectivity and validity of the objects in the database and by sending the flag –lost-found we write the dangling objects into .git/lost-found/other/. If the object is a blob, the contents are written into the file, rather than its object name.

Our files are now “back”, we can find them:

ls .git/lost-found/other

Well, file names are lost but you have the content, what else can you wish for? :)

Problem resolved thanks to Stack Overflow thread.

Happy coding! :)

A beauty treatment for your views – HAML

There is a very interesting markup language used to describe the HTML of any web document, without the use of inline code and its name is HAML! In this post I ll go through its usage describing the advantages and disadvantages. So let’s start!

To start using it as a part of your Ruby on Rails application, it is enough to install HAML gem:

gem 'haml'

bundle install


Set the initializer for haml in config/initializers/haml.rb

Haml::Template.options[:format] = :html5

Have in mind that only files with haml extension will be compiled as valid files.

For example, let’s take a part of the code and translate it. I used the action show for a product and this is how it looked like:

<p id="notice"><%= notice %></p>
<p>
  <b>Name:</b>
  <%= @product.name %>
</p>
<p>
  <b>Description:</b>
  <%= @product.description %>
</p>
<p>
  <b>Price:</b>
  <%= @product.price %>
</p>
<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>

With haml:

%p#notice= notice
%p
  %b Name:
  = @product.name
%p
  %b Description:
  = @product.description
%p
  %b Price:
  = @product.price
= link_to 'Edit', edit_product_path(@product)
|
= link_to 'Back', products_path

Or index page:

%table.datatable
  %thead
    %tr>
      %th> Name
      %th> Description
      %th> Price
      %th>
        &nbsp;
        &nbsp;
  %tbody
    -@products.each do |product|
      %tr{class: [product.special_product?, 'product'], id: ['product', product.id]}>
        %td>= product.name
        %td>= product.description
        %td>= product.price
        %td>
          = link_to 'Show', product
          = link_to 'Edit', edit_product_path(product)
          = link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' }

= link_to 'New Product', new_product_path

%script{defer: true, src: 'assets/product.js'}

Or use Haml for building forms:

= form_for @product do |f|
  - if @product.errors.any?
    #error_explanation
      %h2= "#{pluralize(@product.errors.count, "error")} prohibited this product from being saved:"
      %ul
        - @product.errors.full_messages.each do |msg|
          %li= msg
  = f.label :name
  = f.text_field :name
  = f.label :description
  = f.text_field :description
  = f.label :price
  = f.text_field :price
  = f.submit 'Save'

How to use Haml inside helpers? Here is an example:

Helper will use haml_tag and haml_concat in this case, for more complicated helpers check the module documentation: Haml::Helpers

  def name_for_product(product)
  	haml_tag :h2, class: 'name', id: ['product', product.id] do
  	  haml_concat product.name
  	end
  end

And to use the helper method inside the haml file use:

%p
  - name_for_product(@product)

In short, rules of HAML:

  • %something is compiled as and everything that follows “.” will become a class, “#” an id and the rest will be the content of the object, be careful with indentation
  • Use \ to escape characters like “=”, “%”, “-” … if you want to use them in your views
  • Everything that is defined in Ruby hash (“{ , }”) after the identifying an object will become an attribute for the html object, the same effect will take the regular “()” – no need for separation with “,”
  • For multiple classes or id names use Ruby array; class: [@product.type, @product.code] will be separated with ” ” (class=”special dragon_ball”), the same rule is there for ids but they will be joined with “_” id: ['product', @product.id] (id=”product_23″)
  • Boolean types (selected, checked) are identified with true or false so {:selected => true} will generate selected=’selected’
  • Using {data: {product_id: product.id}} will properly generate custom non-visible data attributes (data-product_id=”32″)
  • Don’t bother yourself specifying divs: #content is the same as %div#content
  • “>” removes all whitespace surrounding a tag,” removes all whitespace immediately within a tag content
  • Use “[]“ when you have to build tags with Ruby object class and id
  • Use “/” for html comments,“/[if IE]“ for conditional html comments and “-#” for haml comments
  • For running Ruby use “-” and for inserting “=”. Ruby interpolation can also be used.
  • For the rest that is missing consult Documentation
  • Spaces are important, indentation has to be correct- always
  • Haml does not like Javascript, do not even try to defer a piece of js code.

 

Overall, Pros and Cons

Haml is a really cool markup but be aware of the following facts before including it into your project:

  • It takes some time to learn, luckily it is nothing complicated but your front end developers could have difficulties
  • There is no defering JS code inside haml file; well, you have to respect best practices anyway
  • Indentation will become your obsession
  • No need for “end” for Ruby code- just the proper indentation
  • No need for div tags!
  • Code reaches even grater level of value in its artistic point of view, working on someone’s legacy code written in haml can be painful; solution – just practice!
  • There is another markup that works even better (according to klaustopher)- its name is Slim
  • It is your decision!

 

For more examples and detail integraton check the DemoApp project, available on Github, commit: fee84b78d3dc2061795604d86c031f2c94dd82f4

Happy coding! ;)

Client side validations in Ruby on Rails

In order to protect your application from the invalid input on server side we can easily use validations. Imagine you have a model

Product where the attributes name, description and price should not be empty, and price should have a specific format and range.

Most probably, in our model we will set something like:

class Product < ActiveRecord::Base
  attr_accessible :description, :name, :price

  validates_presence_of :name, :description, :price
  validates :price, :format => { :with => /^\d{0,8}\.\d{0,2}$/ }, :numericality => {:greater_than_or_equal_to => 0.01, :less_than_or_equal_to => 100.00}
end

Whenever user tries to add a new product, the form will be sent to the server and the returned response will contain object errors. What if we want to save server’s time and do the validations on the client side? Well, wether we can write some javascript ourselves or we can use client_side_validations gem.

The installation of the gem is very simple. Just follow the steps from their documentation.

Now when we installed and add the “//= require rails.validations” to our application.js, it is pretty easy to use- we just add “validation: true” to our form and we have it done!
Still, let’s see some more specific cases.

 

Use symbols to build form- not strings!

Very simple, our form will be built “the same” way wether we use:
    <%= f.label :description %><br />
    <%= f.text_field :description %>
or:
    <%= f.label 'description' %><br />
    <%= f.text_field 'description' %>

This is not the same for form builder, why?

Remember what is the main difference between symbol and a string, string is mutable and symbol is not. What does it mean? String changes its object_id during time while symbol remains always with the same object_id. That is why. Have this in mind because you might waste some precious time debugging it! You can find more details about it on stack overflow.

Custom validations errors preview

Imagine you don’t want that after error another label is rendered. You want a paragraph. In initializers/client_side_validations.rb uncomment the following part and replace <label> with <p>

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  unless html_tag =~ /^<p/
    %{<div class="field_with_errors">#{html_tag}<p for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</p></div>}.html_safe
  else
    %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
  end
end

And override the default behavior by creating new javascript file  ../javascripts/rails.validations.actionView.js (do not forget to add it in your application.js):

$(document).ready(function (){
  window.ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'] = {
    add: function(element, settings, message) {
		var form, inputErrorField, label, labelErrorField;
		form = $(element[0].form);
		if (element.data('valid') !== false && !(form.find("p.message[for='" + (element.attr('id')) + "']")[0] != null)) {
			inputErrorField = jQuery(settings.input_tag);
			labelErrorField = jQuery(settings.label_tag);
			label = form.find("p[for='" + (element.attr('id')) + "']:not(.message)");
			element.before(inputErrorField);
			inputErrorField.find('span#input_tag').replaceWith(element);
      		inputErrorField.find('p.message').attr('for', element.attr('id'));
      		labelErrorField.find('p.message').attr('for', element.attr('id'));
       		labelErrorField.insertAfter(label);
      		labelErrorField.find('p#label_tag').replaceWith(label);
		}
		return form.find("p.message[for='" + (element.attr('id')) + "']").text(message);
    },

    remove: function(element, settings) {
		var errorFieldClass, form, inputErrorField, label, labelErrorField;
		form = $(element[0].form);
		errorFieldClass = jQuery(settings.input_tag).attr('class');
        inputErrorField = element.closest("." + (errorFieldClass.replace(" ", ".")));
        label = form.find("p[for='" + (element.attr('id')) + "']:not(.message)");
        labelErrorField = label.closest("." + errorFieldClass);
        if (inputErrorField[0]) {
          inputErrorField.find("#" + (element.attr('id'))).detach();
          inputErrorField.replaceWith(element);
          label.detach();
          return labelErrorField.replaceWith(label);
        }
    }
  }
});

And this is it, now instead of label we will have a paragraph element.

Custom validations methods

Imagine we want a special format for the product name, and we will need the same format for other fields in application, the best is tu create our own custom validator. How to do that? Create app/validators/name_validator.rb and use something like:

class NameValidator < ActiveModel::EachValidator
  def validate_each(record, attr_name, value)
    unless value =~ /(CODE|TEST)-\w/
      record.errors.add(attr_name, :name, options.merge(:value => value))
    end
  end
end

module ActiveModel::Validations::HelperMethods
  def validates_name(*attr_names)
    validates_with NameValidator, _merge_attributes(attr_names)
  end
end

Customize the error message in yml file:

en:
  errors:
    messages:
      name: "This is not exactly what I want, try harder! It has to start with CODE- or TEST- and it contains only letters"

And bind the validation on ClientSideValidations.validator. In ../javascripts/rails.validations.customValidators.js

$(document).ready(function (){
	window.ClientSideValidations.validators.local['name'] = function(element, options) {
  	if (!/(CODE|TEST)-\w/.test(element.val())) {
    	return options.message;
  	}
	}
});

And final step, use it:

class Product < ActiveRecord::Base
  NameValidator
  ActiveModel::Validations::HelperMethods

  attr_accessible :description, :name, :price

  validates_presence_of :name, :description, :price
  validates :price, :format => { :with => /^\d{0,8}\.\d{0,2}$/ }, :numericality => {:greater_than_or_equal_to => 0.01, :less_than_or_equal_to => 100.00}
  validates_name :name
end

Here you go! Custom name validation is done!

For more ways of using this handsome plugin check their documentation.

This project is also available on my Github account, check here, commit: 3b9fcaacbe87755293648719e19c9b71202e0072.

Happy coding! :)