Super Spread Sheet S³

Or little computing tricks and hacks

Data Validation of boolean values in Rails

To validating the presence of a boolean value, the short answer is you don’t need to. Rails does an automatic check on boolean data types.

In theory validating the presence would be just a waste of time, but in practice it creates a bug. If you have in your model.rb a line similar to

validates :is_active, presence: true

and is_active is a boolean, when entering false as a value, Rails interprets it as empty and the action of creating or updating the record is refused.

Leaving the line out will allow the creation or updating of the record and if the value is not either true or false, the stored value will be nil.

You may want to ensure that the value is either true or false. In that case, the following line should be added:

validates_inclusion_of :active, :in => [true, false]

Inspired from:

Advertisements

Managing multiple ssh keys

I know. This post has been written many times. However, this one has my own flavor. This post assumes that the reader knows how to use the ssh protocol and to create ssh keys. If in doubt, visit the github instructions here.

The ssh protocol uses the ssh-agent program defined as follows:

ssh-agent is a program to hold private keys used for public key authentication (RSA, DSA, ECDSA, ED25519). The idea is that ssh-agent is started in the beginning of an X-session or a login session, and all other windows or programs are started as clients to the ssh-agent program. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using ssh.

When there is only one ssh-key, the ssh-agent loads it automatically it seems (I need to investigate further as I seem to be running polkit-gnome-authentication-agent instead of ssh-agent).

Start by identifying how many keys you need, depending on the sites you usually connect to. In my case that is gtihub, heroku, bitbucket, computers in my local network, and a remote computer. Remove the current keys located in the ~/.ssh directory, which names have patterns like id_{rsa,dsa}*. As I tend to be paranoiac, I put them in a directory called original in case I needed to do a rollback.

Github

The next step is to create the key, by using the command:

ssh-keygen  -f ~/.ssh/id_rsa.github -C "myemail@example.com"

I tend to omit the paraphrase by just typing enter when prompted.

This created two files: id_rsa.github, id_rsa.github.pub. The latter is the actual key to copy on the github account settings part.

The next to steps are new:
First add the key to ssh-agent:

ssh-add ~/.ssh/id_rsa.github

Second add the specification of the site to the ~/.ssh/config file:

Host github
Hostname github.com
User bluciam
IdentityFile ~/.ssh/id_rsa.github

You can check if the connection is working by issuing the command

ssh -T git@github.com

which, if successful, will respond with

Hi bluciam! You’ve successfully authenticated, but GitHub does not provide shell access.

bluciam is my github username. To get all the information on the handshake, add a -v:

ssh -Tv git@github.com

Adding the other ssh keys follows the same process, obviously replacing with the correct names and hosts.

Heroku

Heroku has also a page with full instructions here. There are two commands I would like to highligh:

1. To check if the connection is working issue the command

ssh -v git@heroku.com

2. To add the key without logging into the site:

heroku keys:add

Local machines

For my local machines, the added local instead of the name of the server. The adding to the ssh-agent is done once

ssh-add ~/.ssh/id_rsa.local

but there must be an entry for each machine in the config file.

And that is all!

Further reading: https://gist.github.com/jexchan/2351996/

Ckeditor in heroku

I was reaaaally happy to have found the ckeditor gem. As my grandmothers used to say: “Mató dos pájaros de un tiro” (killed two birds with one shot). The gem took charge of all the type setting of the articles INCLUDING adding pictures to the body of the text.

ckeditor-1

Everything worked like magic in my test environment, until I deployed to heroku. All charms gone, it did not work. Where the editing window was to go, it was just nothingness.

The solution taken from here:

Make sure to

bundle update ckeditor

and then, add these line to config/application.rb

config.assets.precompile += Ckeditor.assets
config.assets.precompile += %w( ckeditor/* )
config.autoload_paths += %W(#{config.root}/app/models/ckeditor)

and that worked for me.

Sorting out time zones in Rails

NOTE: Post edited 9 March, 2015.
Original post had incomplete information. The solution given was not enough.

Nothing more annoying that an app which cannot sort out or at least tell you in what time zone the date displayed is given in.

Standard for Rails apps are the fields created_at and updated_at. By default Rails uses UTC to store this, but when this command is issued

Time.now

the time is adjusted to show local time. This creates an odd situation when you use Time.now to set in the database a time field through an input form. The time is stored without transformation in UTC.

Furthermore, ruby only supports UTC. By typing

article.created_at.class

I discovered that these are in fact of Class

ActiveSupport::TimeWithZone

which is (taken from ActiveSupport TimeWithZone) a

Time-like class that can represent a time in any time zone.

To sort out any discrepancies or errors with respect to you application, the time zone should be set. To find the available zones type

rake -D time

for the commands available and

rake time:zones:all

to get a listing of all the time zones recognized. Or try

rake time:zones:local

There seems to be different places to set the time zone:

  • config/environment.rb was mentioned in this post.
  • config/application.rb is where the commented portion with the explanations, was.

I used the latter, with the following line:

    config.time_zone = 'Eastern Time (US & Canada)'

This magic line

… sets Time.zone default to the specified zone and makes Active Record auto-convert to this zone.

is misleading, since I discovered that in the database dates are indeed and still stored in UTC, after all the changes.

To fix this, once the current date is captured, it is converted into UTC before storing in the database.

A snippet of the new.html.rb:

      my_date_time = Time.now

      select_datetime(my_date_time,
        datetime_separator: " at ",
        prompt: {day: 'Day', month: 'Month', year: 'Year',
                 hour: 'Hour', minute: 'Minutes'})

      my_date_time.zone

and in the controller.rb:

def create
    time_in_localzone = Time.new(
      params[:date]['year'].to_i,
      params[:date]['month'].to_i,
      params[:date]['day'].to_i,
      params[:date]['hour'].to_i,
      params[:date]['minute'].to_i,
    )
    @article.published_on = time_in_localzone.utc

    if @article.save
      redirect_to articles_path
    else
      render 'new'
    end
end

Useful links:

Rails: Choosing and assigning in a HABTM association

Now that I have an HABTM association, I need to provide the user with an interface to choose different categories for an article. (To see how I created the association, see this post.)

Because we have in each of the model files the line stating the association:

# app/models/category.rb
class Category < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

and

# app/models/article.rb
class Article < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

this generates the method:

article_object.category_ids

which returns an array of the category ids which the article object belongs to. Reciprocally the method

category_object.article_ids

returns an array of the article ids in that category object.

To choose a category, in the new.html.erb and edit.html.erb files I included the following (I apologize for the lack of the closing %>, but when I include them, the pre environment just disappears the line):

<% Category.all.each do |cat|
  <% check_box_tag "category_ids[]", cat.id, @article.categories.include?(cat)
  <% cat.name
<% end 

the first argument to check_box_tag is the name of the check box and the [] are very important to indicate that it is an array being passed. The second argument is the value, and the third is a boolean indicating whether the box should be ticked or not.

When the article is updated, the method category_ids updates the categories of the article using the array that was passed in the params hash. The category_ids method was generated by the has_and_belongs_to_many in the Article model.

In the controller, I included the following line as well

    @article.category_ids = params[:category_ids] ||= [8]

where 8 is a default value if nothing is given. If this line was not included no changes are made. This is in disagreement with the code in Bates’ Railscast, which is where I took the inspiration from. (I seem to recall a change in the params hash structure but I am uncertain.) I opted for the change by looking Rails API dock.

Git: looking for old versions of files

In the past two days I have been doing massive changes to my app along with some clean up. In the clean up however, I have changed chunks of code which I needed to refer to while creating other features.

A quick way to check for the version of the file from, say, the beginning of the year using git is:

git show HEAD@{2015-01-01}:./paht/to/file/file.rb

This was taken from Stack overflow. There is another solution using gitk taken from the same link:

1) start gitk with:

gitk /path/to/file

2) Choose the revision in the top part of the window either by description or by date. By default, the lower part of the screen shows the diff for that revision, (corresponding to the “patch” radio button).

3) To see the file for the selected revision:

Click on the “tree” radio button. This will show the root of the file tree at that revision.
Navigate down to your file.

Rails: Create a HABTM association between categories and articles

While looking to migrate the legacy database from WordPress into my Rails app, I noticed that one of the specs for the database was wrong. An article IS allowed more than one category. Sigh! That part of the implementation was ready. After studying the different possibilities, I opted for having a join table. This is what I did:

rails g controller Categories create edit
rails g model Category name:string

and all what is needed in Rails for the new model.

Then I added the following to the newly created Category model:

class Category < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

and to the preexisting Article model:

class Article < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

Having this, I have to create the join table, whose migration is as follows:

class CreateCategoriesAndArticles < ActiveRecord::Migration
  def change
    create_table :categories_articles, id: false do |t|
      t.belongs_to :category, index: true
      t.belongs_to :article, index: true
    end
  end
end

Two things to note:

  1. The name of the table is crucial, otherwise the magic to access the categories of an article will not work.
  2. id: false tells the database manager to create a table without an indexable id.

If you create the table with the wrong name as I did, here is the migration to rename a table (taken from Stack overflow):

 class RenameOldTableToNewTable< ActiveRecord:Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end 

Once created, the output in

rails db

as described in as described here is:

development=# select column_name from information_schema.columns where table_name='categories_articles';
  column_name   
----------------
 article_id
 category_id
(2 rows)

To access the categories in an article, the magic I mentioned before, do:

article.category_ids

which will return an array of the category ids associated with that article.

By the way, this is a HABTM association, Has And Belongs to Many. This association is done in the table pairing the two ids.

In this post I wrote about providing the option of selecting one or more categories for an article.

Git: changes in the wrong branch

As I was happily following instructions to use the puma gem in heroku, I noticed I was on the wrong branch… &*$%= (or word of your choice).

Searches told me to simply go back to my branch (from refactor_home to master) and changes would follow:

git checkout master

but instead I got this mistake:

error: Your local changes to the following files would be overwritten by checkout:
file-1
file-2
Please, commit your changes or stash them before you can switch branches.
Aborting

Uhmm. Reading the error message, commit was out of the question. There was “stash” left. git stash saves the changes somewhere. I ran

git stash

and the output was

Saved working directory and index state WIP on refactor_home: 8158613 Refactor finished with fallback for articles only

Then I checked out to the master branch, and ran

git stash pop

and presto. Now pending changes are part of the master branch.

This only worked because both branches were clean. I do not want to adventure what would happen if there were a lot of other changes.

If you want to throw away changes (taken from here):

git reset --hard

or

git reset --hard HEAD

This post explains what to do if the changes are already committed.

Image manipulation commands in Carrierwave

In my Rails app, I am using the gems

gem 'mini_magick'
gem 'carrierwave'

for image manipulation of files entered by users. Even though the sample files are full of useful comments, I did not find a comprehensive list of the possible commands. I needed to create exact sizes respecting ratio. The internet searches failed me today! Perhaps I was in a rush…

I found this post, which is actually describing another gem for image manipulation, describing the following commands:

resize_to_limit(width, height)

resize an image down to fit the width and height, maintaining the image ratio.

resize_to_fit(width, height)

resize an image up or down to fit the width and height, maintaining the image ratio.

resize_to_fill(width, height)

crop and resize to fit the width and height.

Create admin user in Rails

For obvious reasons, any way to create an admin user through the web interface should be forbidden: exclude the admin field in whatever form you have decided to implement it, from the params hash.

One of the most secured ways to create admin users is to use the seed.rb file. The file could look something like this:

users = {
    admin: {
        username: 'admin',
        email: 'admin@gmail.com',
        password: 'adminpass',
        password_confirmation: 'adminpass',
        is_admin: true
    },
    administrator: {
        username: 'administrator',
        email: 'administrator@gmail.com',
        password: 'administrator',
        password_confirmation: 'administrator',
        is_admin: true
    }
}

users.each do |user, data|
  user = User.new(data)
  unless User.where(email: user.email).exists?
    user.save!
  end
end

Taken from verbatim here.

Once the file is created, all you have to run is

$ rake db:seed

This file will also be sourced when running

$ rake db:setup

Make sure that the password is changed as soon as the admin user is created. You can also force an admin password reset.

If using heroku for deployment this is the command to seed the database:

$ heroku run rake db:seed