Páginas

Sunday, November 20, 2011

Creating emails with Rails

By default, rails sends emails with the MIME type text/plain, but sometimes you might wish to make your emails look better, by adding links or images and for that you need your mail to have the MIME type of text/html.

The easier way to do this, would be by change the content type variable in the notifier.rb file, but if you do that, email reader that don't support html will not show your email correctly.

So how have the best of both worlds with as little effort as possible? Fear not my friends, for RoR convention over configuration policy has come to the rescue yet again!

All that you need to do is to create two files in your notifier views, one with the name whatever_you_want.text.html.erb and another with the name whatever_you_want.text.plain.erb and rails ActiveMailer will take care of the rest for you. Sweet!

PS: This is for rails 2.x, in rails 3.x the names would be whatever_you_want.text.erb and whatever_you_want.html.erb

Saturday, October 1, 2011

Properly show errors with Paperclip and Formtastic

Paperclip has for while now decided that each of its files should have 5 arrays of errors, one for each field it stores in the database (file_name, file_size, content_type and updated_at) and one for the actual file object.

If you are using it alongside with formtastic (or even if you are not), this can be the cause of some problems when trying to show those errors to the client. Therefore, I created a little method to concatenate all these arrays into one.

def properly_show_errors(record)
  @record=record
  if @record.errors.any?
    flash[:error] = []

    @record.errors.each do |attribute,msg|
      if attribute =~ /.+_content_type/ || attribute =~ /.+_content_file_size/
        proper_attribute = attribute.split('_')[0]
        @record.errors.delete_all_at proper_attribute
        @record.errors.add proper_attribute,msg
      end
    end
  end
end  


This takes a record and merges the content_type and content_file_size errors into its own error array. The message can be internationalized in the model to whom the file concerns, as such:

validates_attachment_size :image, :less_than => 1.megabytes, :message => I18n::t('flash.image_size_1mb')

The record is passed on as an instance variable of the caller class. In my use case this caller class is an action in the controller, for instance when creating a page:

@template.properly_show_errors(page)
flash.now[:error] = t("flash.page_not_updated", :name => page.title) 

This will render the page creation form with the error on the flash div, and the record instance variable with page and its errors. The two things of note in this piece of code are the way of using helpers in a controller with the @template variable, and the flash.now that will make the flash message last only one redirect.

Note: This 'bug' has been fixed in formtastic version 1.2.0 and above, but this is still pertinent for those using a prior version


Sunday, September 18, 2011

Dynamic HTML container size with CSS + JS

Have you ever tried to make a container (let's say a span) have the size of the text dynamically, without you having to har code it? Here's how I've done it using JavaScript (actually JQuery) and some CSS.

First let's define the markup:

<span id="ruler"></span>
<div class="wrapper">
    <span class="name">Hello World</span>
    <span class="name">I am a very very very very very big string.......................</span>
    <span class="name">I am a normal string</span>
</div>  


The only thing of notice here is the span with the id ruler, this span is empty and is what is going to help us measure the string size in pixels.

Now for the javascript:


String.prototype.visualLength = function() {
    $("#ruler").html(this.toString());
    var width = $("#ruler").width();
    $("#ruler").text("");
    return width;
};

$("span.name").each(function() {
    $(this).css("width", $(this).text().visualLength());
});

This defines a new function for Strings called visualLength that puts the string in the ruler span, gets the width in pixels and cleans it. Then there is an iterator that sets the width for each of the spans we've defined to the one returned by the function.

And that is it. Now we just need some CSS, to make use of this:

span.name{
    display: block;
    border: 3px solid #FF0000; 
    margin-right:auto;
    margin-left:auto;
}    


div.wrapper{
    width: 500px;
    border: 3px solid #000;  



span#ruler{
    visibility: hidden;
    white-space:nowrap;
}  


This code makes the ruler invisible and impedes the text from wrapping. The rest is just an example of how to use this feature to center your text in an outer container. Here is a demo.

Note: The javascript code was based on a blog somewhere, but I cannot seem to find it. If someone knows the link, I'll be happy to refer it.

Saturday, August 27, 2011

Integrating git and rvm with prompt

Here's a quick hack to your prompt, that I find helpful when using git and rvm.

Add this to you .bash_profile, .bashrc, or whatever file you use to configure your shell:

export PROMPT_COMMAND='PS1="\[\033[0;33m\][\!] \h\`
if [[ \$? = "0" ]]; then echo "\\[\\033[32m\\]";
else echo "\\[\\033[31m\\]"; fi
\` \`
if [[ `pwd|wc -c|tr -d " "` > 60 ]]; then echo ":..$(expr "$PWD" : ".*\(/.*.\{40\}\)")";
else echo ${PWD/\/Users\/$(whoami)/\~}; fi
\`\[\] $(parse_git_branch)\[\]\[\033[0m\]$(rvm_version.sh)\[\033[0m\]: ";
echo -ne "\033]0;`hostname -s`:`pwd`\007"'


Now you need the parse_git_branch and rvm_version.sh.

Parse Git Branch

parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/[\1]/'
}


RVM Version

ruby_version=$(/usr/local/rvm/bin/rvm current)
if [ -f "Gemfile" ] # If it is a rails project
then
  if [ -e "app/assets" ] # If rails version >= 3.1
  then
    if [[ $ruby_version != *1.9* ]] # If not using correct rvm version
    then
      echo -n "\\[\\033[31m\\]"
    else
      echo -n "\\[\\033[32m\\]"
    fi
  else # If rails version >= 3.1
    if [[ $ruby_version != *1.8* ]]
    then
      echo -n "\\[\\033[31m\\]"
    else
      echo -n "\\[\\033[32m\\]"
    fi
  fi
  echo -n [$(/usr/local/rvm/bin/rvm current)]
else
  echo -n "\\[\\033[32m\\]"
fi


Put them somewhere in some directory that's in your PATH, and it should work. What it does, as far as git and rvm go, is tell what branch your on, and if your using the correct rvm for your rails project (turns red if your not).

I'll probably work a little more on the rvm_version, that is the only thing that I can actually get credit for, but for now it works.

Monday, July 18, 2011

Project Euler

Project Euler is a website that proposes various problems, related to programming and/or math. You can solve the problem anyway you like, as it only asks for the result. If you get it right, you can then check out how others have done it or, in some cases, have an explanation from the guys at project euler.

It is very addictive and fun, I highly recommend it!

I've been solving the problems entirely in Ruby, and committing my code to github. Check out my solutions, and don't hesitate to let me know if you find a better one, or even a bug. ;)

Tuesday, May 31, 2011

Bridging the gap between SQL ao NoSQL: A state of the art

Here is a state of the art report I wrote on SQL and NoSQL, and a way to bring them closer. This is actually the theme of my master thesis, so you should probably get some more posts on this topic in the future.

Hasta. ;)

Artigo-MI-STAR

Monday, May 9, 2011

Running a Cassandra cluster with only one machine

I've noticed that if you want to run a cassandra cluster on your own pc, for the purpose of small tests, there is no guide in the wiki to do just that.

Therefore, here is how I've done it.

First of you'll need to create an alias for you network interface:

Mac OS
ifconfig en0 alias 192.168.0.2

Linux
ifconfig eth0:0 192.168.0.2

Here I've chosen the en0 (or eth0) interface, but you can choose the one you like, and also the IP address you like.

The first file you'll have to edit is the conf/cassandra.yaml:

- Change the commit_log, data and saved_caches directories, so it doesn't conflict with the ones from the previous "node";
- Change the rpc_port (used for Thrift or Avro) to one that is free;
- Change the listen_address to the IP of your "fake" interface.

Next open the conf/cassandra-env.sh file and change the JMX_PORT.

The last file to edit is the bin/cassandra.in.sh where you'll need to change all the occurences of $CASSANDRA_HOME to the path of the "node". For example, if you're bin directory is in /XXX/YYY/node2/bin, the path is /XXX/YYY/node2.

You can do this to create as many nodes as you want, and then just run them as usual, with bin/cassandra -f

Sunday, May 1, 2011

Inserting data with Thrift and Cassandra 0.7

A lot has changed from Cassandra 0.6 to 0.7, and sometimes it is hard to find examples of how things work. I'll be posting how to's on some of the most usual operations you might want to perform when using Cassandra, written in Java.

First of you have to establish a connection to the server:

TFramedTransport transport = new TFramedTransport(new TSocket("localhost", 9160));
Cassandra.Client client = new Cassandra.Client(new TBinaryProtocol(transport));
transport.open();

Here I'm using localhost and the default port for Cassandra, but this can be configured.

One difference to the previous versions of Cassandra is that the connection can be bound to a keyspace, and can be set as so:

client.set_keyspace("Keyspace");

With the connection established you need only the data to insert, now. This data is passed to the server in the form of mutations (org.apache.cassandra.thrift.Mutation).

In this example, I'll be adding a column to a row in a column family in the predefined keyspace.


List<Mutation> insertion_list = new ArrayList<Mutation>();

Column col_to_add = new Column(ByteBuffer.wrap(("name").getBytes("UTF8")), ByteBuffer.wrap(("value").getBytes("UTF8")),System.currentTimeMillis());

Mutation mut = new Mutation();
mut.setColumn_or_supercolumn(new ColumnOrSuperColumn().setColumn(col_to_add));
insertion_list.add(mut);

Map<String,List<Mutation>> columnFamilyValues = new HashMap<String,List<Mutation>>();
columnFamilyValues.put("columnFamily",insertion_list);

Map<ByteBuffer,<String,List<Mutation>>> rowDefinition = new HashMap<ByteBuffer,<String,List<Mutation>>>();
rowDefinition.put(ByteBuffer.wrap(("key").getBytes("UTF8")),columnFamilyValues);

client.batch_mutate(rowDefinition,ConsistencyLevel.ONE);


The code is pretty much self explaining, apart from some values that can be reconfigured at will, as the encoding of the strings (I've used UTF8), and the consistency level of the insertion (I've used ONE).

In the case of the consistency levels you should check out Cassandra's wiki, to better understand it's usage.

To close the connection to the server it as easy as,

transport.close();

Hope you find this useful. Next I'll give an example of how to get data from the server, as soon as I have some time. ;)

Friday, February 18, 2011

Opening a new tab in the same directory and then some in Mac OS

For all of you that use the Mac OS Terminal, you've probably felt the frustation of opening a new tab and it opening on the $HOME path, unlike the Linux one's, that open in the path you were in.

Well, I've written a script that kind of solves this problem, and adds some extra functionality that I find really helpfull.


#!/bin/bash

COMMAND=$1

if [ -z "$1" ]
then
  COMMAND="cd $(pwd)"
fi

/usr/bin/osascript 2>/dev/null <<EOF
activate application "Terminal"
tell application "System Events"
  keystroke "t" using {command down}
end tell
tell application "Terminal"
  activate
  do script "$COMMAND" in window 1
end tell
return
EOF


First let's take a look at the applescript part (that's the part between EOF). Applescript code is very readable, but what it does is to open a new tab in the terminal, and then run the code in the COMMAND variable in that newly open window.

Then, there is that little bit of bash code, that assigns the string passed as an argument to be run or, if none is provided, it changes the directory to the one you were in.

So, you can open a new tab, by calling the script or, and this is the very handy thing for writing other scripts, open a new tab and run code in that tab, by calling the script with the string as an argument.

Saturday, February 5, 2011

Parsing strings from the datepicker

In my previous post I explained how to create a datepicker with dynamic internationalization. There is one catch though, in different languages the representation of the date can be different, for example, February 5th can be 2/5/2011 in the USA and 5/2/2011 in Portugal. The rails default is the first.

This means that you'll have to take this into account when using the string that you get from the form where you are using the datepicker. You have two options, change the way the dates are displayed, by altering all the languages javascripts, or parse the string as it gets to the controller.

The latter can be achieved with this piece of code:


todo.due_date = DateTime.strptime(params[:date],"%d/%m/%Y").to_time


Note that I've chosen that format for the string, but it can be any format according to the ruby's Time class.

There is one other problem though, the user can, maliciously or by distraction, insert an invalid date. We can strengthen our code to prevent this, by catching the exception thrown.


begin
  todo.due_date = DateTime.strptime(params[:date],"%d/%m/%Y").to_time
rescue ArgumentError
  flash[:error] = t("flash.invalid_date")
  redirect_to somewhere_in_the_app_path
  return
end


So, if the exception occurs, we set the flash error message (using the translation helper), redirect to the appropriate path, and then return, so that it does not complain of having multiple render or redirect calls.

Thursday, February 3, 2011

jQuery-UI datepicker dynamic internationalization in Rails

The jQuery UI datepicker is internationalizable, by chosing from one of the languages in the regional array, as such:

$(selector).datepicker($.datepicker.regional['en-GB']);

As is easy to see, this changes the datepicker language to english. In order for any other language, apart from english (which is the default), to work, we need to include a javascript file that defines the strings to be shown.

We can either include all the languages (http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.8/i18n/jquery-ui-i18n.min.js), or just the ones we need, that can be found here.

So far so good. But what if we want to include only the file we need, according to the system's locale?

It's pretty simple, and it prevents a user from having to download files he is not going to use, but just the one for the language he is viewing the site.

First, you'll have to create a helper that checks the current locale and includes the file accordingly, so it can be called from the views that use the datepicker.


def include_i18n_calendar_javascript
  content_for :head do
    javascript_include_tag case I18n.locale
      when :en then "jquery.ui.datepicker-en-GB.js"
      when :pt then "jquery.ui.datepicker-pt-BR.js"
      else raise ArgumentError, "Locale error"
    end
  end
end


As you can see, this has a case that chooses the file according to the locale, an returns it to the javascript_include_tag helper that generates the HTML for the inclusion of a javascript file and places it in the header with the content_for helper.

Now you only have to call the helper in the view and add some javascript.

var counter = 0;
var locale = "
for(i in $.datepicker.regional){
  if(counter == 1)
  { locale=i; break; }
  counter++;
}


Because the regional array is not exactly an array, but an hash (or an associative array, in javascript terms), we will have to iterate through each of it's objects. The one we want is the second, that the reason for the break. This object is the string the key in that associative array for the definitions of the locale we want. In the case of the first example, it would be "en-GB".

Now, we just initialize the datepicker with this variable:


$.datepicker.setDefaults( $.datepicker.regional[ '' ] );
$( ".datepicker" ).datepicker($.datepicker.regional[locale]);


And that's it. Now your datepickers are internationalized in a dynamic way.

PS: Of course you'll need a textfield that has the HTML class datepicker (or any other you choose).

Wednesday, January 5, 2011

Manipulating nested hashes in Ruby

Lately I needed to work with some nested hashes in ruby. By nested hashes I mean hashes with hashes (or any other type, actually) in them, something like this:

nested_hash = {"first_key"=>{"second_key"=>"value"},"third_key"=>12}

That was when I found out that there are no actual methods to do this, and therefore I had to come up with my own.

If you want to get all the values in a nested hash, you can do this:

def get_all_values_nested(nested_hash={})
  nested_hash.each_pair do |k,v|
    case v
      when String, Fixnum then @all_values << v
      when Hash then get_all_values_nested(v)
      else raise ArgumentError, "Unhandled type #{v.class}"
    end
  end

  return @all_values
end

Obviously, you could just run trough all the pairs of key/value, but this would only work if there were no nested hashes. If there are, you need to recursively call the method each time you find a hash.

That's why we need the case statement, in order to differenciate between values and other hashes (or Arrays...). If it is a hash, you just give the value to the function and do a recursive search, that stops when it hits a value, adding this value to the final array. In this example I've considered to be values, String and Fixnum, if any other type happens to be present, an exception will be raised.

Note that the all_values variable is an instance variable. It cannot be a local variable, because it's values are going to be used in all the recursive calls. Another way of doing it would be by passing the variable to the method each time and update it at each return. I find it simpler and prettier like this.

In the previous example you'll get an array with all of the values, and that's it. You may, however, want to now what was the path travelled to get to the value. It is actually not that hard to implement, by changing the code just a little bit.

def get_all_values_nested(nested_hash={})
  nested_hash.each_pair do |k,v|
    @path << k
    case v
      when String, Fixnum then
        @all_values.merge!({"#{@path.join(".")}" => "#{v}"})
        @path.pop
      when Hash then get_all_values_nested(v)
      else raise ArgumentError, "Unhandled type #{v.class}"
    end
  end
  @path.pop

  return @all_values
end

There are two main differences in this code, the first is that there is a new instance variable, called path, that's an array, with all the keys that had to be "visited", to get to the value. The last key to be visited is the last key in the array, and is poped each time a value is found, or when all the keys of a certain hash are exhausted.

Imagine you have the hash first presented as an example, the evolution of the path array would be:

["first_key"] , ["first_key","second_key"] - Here, the value is found, and therefore a pop occurs, leaving the array with the previous state, after saving the path in the all_values hash:

["first_key"] - first_key does not have any more keys, so another pop happens, and so on:

[] , ["third_key"] , []

The other difference is that an hash is returned instead of an array. The hash has the following format (using the previous example):

{"first_key.second_key"=>"value" , "third_key"=>12}

So, now you can get the values, and know where they came from, the next thing you probably will want to do is change them and update the nested hash.

def set_value_from_path(nested_hash,path_to_value,newValue)
  path_array = path_to_value.split "."
  last_key = path_array.pop
  hash = create_hash_with_path(path_array,{last_key=>newValue})
  self.merge!(nested_hash,hash)
end

This method receives the path to the value in the format used in the get, and the new value to be inserted. It first transforms the string of the path into an array as the ones we've used before, then it makes the array and the value into a hash, using an auxiliary method, create_hash_with_path. It is a very simple method that gets a path array and a simple hash with the last key before the value, and the value.

def create_hash_with_path(path_array,hash)
  newHash = Hash.new
  tempHash = Hash.new
  flag = 1
  path_array.reverse.each do |value|
    if flag == 1
      tempHash = hash
      flag = 0
    else
      tempHash = newHash
    end
    newHash = {value => tempHash}
  end

  return newHash
end

Afterwards it merges the nested hash (that is the one from the first example), and the newly created hash. The only problem is that you cannot use the merge methods from the Hash class, because it does not work for nested hashes. You can write a simple method that does just that.

def merge!(merge1,merge2)
  case merge1
    when String,Fixnum then merge2
    else merge1.merge!(merge2) {|key,old_value,new_value| self.merge!(old_value,new_value)} if merge1 && merge2
  end
end

It just redefines the Hash's class merge! to be recursive, and to stop when it reaches a value (String, Fixnum), and to using the value in merge2, that is the new value.

So, there you go. Now you have a whole new arsenal of methods to deal with nested hashes. Have in mind that you can chage this code to be compatible with other kinds of values, like Symbols and/or to accept other containers as an Array.

Saturday, November 6, 2010

Passing data from a jQuery script to a controller method in Rails using Ajax

First of all you have to write your script to get the data and store it in variables. This code should be written either in public/javascripts/application.js or in a new file in the same directory and then included in the HTML, like so:

<%= javascript_include_tag 'name_of_file' %>
or

<%= javascript_include_tag :defaults %>

to include the application.js file.

Have in mind though that this includes must be done after including the jquery.js, and that jQuery can affect other scripts that use prototype. Therefore, if you are using any code that needs prototype or just as a good practice, the first line of your jQuery script should be jQuery.noConflict();.

This being said, the way you pass your data to the controller is through an Ajax post, which is something like this:

$.post(path,{ "string1": variable1,"string2": array1},null,"script");

Check the jQuery documentation for more details.

The path variable should be in the form controller/action, so that the message is sent to the desired action.

The next thing to do is to create the action in the controller that will receive the message. This action can respond to different kind of requests in different ways, what I mean is that if it is an HTTP request it behaves one way, and if it is our Ajax request it behaves another.

This separation of behaviours is achieved with respond_to like this:

respond_to do |format|
format.html { redirect_to :action=>"list" }
format.js
end


As it is easily perceivable, for an HTTP request it redirects to the action named list of the same controller and renders it. What it does in the case it receives an Ajax request might not be that obvious, because the code that will be run can be written in a file called action_name.js.erb that has to be in the views/controller directory.

This file can be something as simple as this:

$("#justForTest").html('
params[:actions]
');


One last thing for this to work is that the post request in our client side script must be an Ajax request. This can be done by adding .js to each path or by adding this setup code to the top of your scripts file:


jQuery.ajaxSetup({
'beforeSend':function(xhr) {xhr.setRequestHeader('Accept','text/javascript')}
})


This should make your request work as intended. Have fun with jQuery and Ruby on Rails, which are very powerful tools for any web developer.

Saturday, October 16, 2010

Cassandra, the Data Model

UPDATE: Sorry for the images being down for so long. I've finally had the time to re-upload them, and while I was at it, I re wrote the whole post.

For my master's thesis I'm going to be working with Cassandra, an open source distributed database management system, and therefore I'll probably write a lot about it throughout the next year. To get started let's take a look at one of the biggest differences from this kind of DBMS to the classical relational systems, the data model.

Cassandra that was created on Facebook, first started as an incubation project at Apache in January of 2009 and is based on Dynamo and BigTable. This system can be defined as an open source, distributed, decentralized, elastically scalable, highly available, fault-tolerant, tuneably consistent, column-oriented database.

Cassandra is distributed, which means that it is capable of running on multiple machines while the users see it as if it was running in only one. More than that, Cassandra is built and optimized to run in more than one machine. So much that you cannot take full advantage of all of its features without doing so. In Cassandra, all of the nodes are identical, there is no such thing as a node that is responsible for certain organizing operations, as in BigTable or HBase. Instead, Cassandra features a peer-to-peer protocol and uses gossip to maintain and keep in sync a list of nodes that are alive or dead.

Being decentralized means that there is no single point of failure, because all the servers are symmetrical. The main advantages of decentralization are that it is easier to use than master/slave and it helps to avoid suspension in service, thus supporting high availability.

Scalability is the ability to have little degradation in performance when facing a greater number of requests. It can be of two types:

  • Vertical - Adding hardware capacity and/or memory
  • Horizontal - Adding more machines with all or some of the data so that all of it is replicated at least in two machines. The software must keep all the machines in sync. 

Elastic scalability refers to the capability of a cluster to seamlessly accept new nodes or removing them without any need to change the queries, rebalance data manually or restart the system.

Cassandra is highly available in the sense that if a node fails it can be replaced with no downtime and the data can be replicated through data centers to prevent that same downtime in the case of one of them experiencing a catastrophe, such as an earthquake or flood. 

Eric Brewer's CAP theorem states that it is impossible for a distributed computer system to simultaneously provide all three of the following guarantees:
  • Consistency
  • Availability
  • Partition Tolerance
The next figure provides a visual explanation of the theorem, with a focus on the two guarantees given by Cassandra.



Consistency essentially means that a read always return the most recently written value, which is guaranteed to happen when the state of a write is consistent among all nodes that have that data (the updates have a global order). Most NoSQL implementations, including Cassandra, focus on availability and partition tolerance, relaxing the consistency guarantee, providing eventual consistency.

Eventual consistency is seen by many as impracticable for sensitive data, data that cannot be lost. The reality is not so black and white, and the binary opposition between consistent and not-consistent is not truly reflected in practice, there are instead degrees of consistency such as serializability and causal consistency. In the particular case of Cassandra the consistency can be considered tuneable in the sense that the number of replicas that will block on an update can be configured on an operation basis by setting the consistency level combined with the replication factor.


 The NoSQL movement members (which includes Cassandra) focus on the last two, relaxing the consistency bit. They provide what is know as eventual consistency. Having said that, let's take a closer look at Cassandra's data model.

Usually, NoSQL implementations are key-value stores that have nearly no structure in their data model apart from what can be perceived as an associative array. On the other hand, Cassandra is a row oriented database system, with a rather complex data model. It is frequently referred to as column oriented, and this is not wrong in the sense that it is not relational. But data in Cassandra is actually stored in rows indexed by a unique key, but each row does not need to have the same columns (number or type) as the ones in the same column family.

The basic building block of Cassandra are the Columns. They are nothing but a tuple with three elements, a name, a value and a timestamp. The name of column can be a string but, unlike its relational counterpart, can also be long integers, UUIDs or any kind of byte array.



Sets of columns are organized in rows that are referenced by a unique key, the row key, as demonstrated in the following figure. A row can have any number of columns that are relevant, there is no schema binding it to a predefined structure. Rows have a very important feature, that is that every operation under a single row key is atomic per replica, despite the number of columns affected. This is the only concurrency control mechanism provided by Cassandra.




The maximum level of complexity is achieved with the column families, which "glue" this whole system together, it is a structure that can keep an infinite (limited by physical storage space) number of rows, has a name and a map of keys to rows as shown here:



Cassandra also provides another dimension to columns, the SuperColumns, these are also tuples, but only have two elements, the name and the value. The value has the particularity of being a map of keys to columns (the key has to be the same as the column's name).




There is a variation of ColumnFamilies that are SuperColumnFamilies. The only difference is that where a ColumnFamily has a collection of name/value pairs, a SuperColumnFamily has subcolumns (named groups of columns).

Multiple column families can coexist in an outer container called keyspace. The system allows for multiple keyspaces, but most of deployments have only one.

This is pretty much it. Now, it all depends on the way you use these constructs.

Be aware of one thing when using Cassandra, the values on the timestamps can be anything, but they must be consistent throughout the cluster, since this value is what allows Cassandra to define which updates are new and which are outdated (an update can be an insert, a delete or an actual update of a record).

Sunday, October 3, 2010

Bash 101: Variables and Conditions

First off I would like to make a little note on the use of quotes. In the shell, variables are separated by whitespaces, if you want those characters to belong to the variable you'll have to quote them.

There are 3 types of quotes, double, single and the backslash, that have the following results:
  • Double - Accepts whitespaces and expands other variables
  • Single -   Accepts whitespaces and doesn't expand other variables
  • Backslash - Escapes the value of $
In my previous post I've talked about normal variables, here I'll talk about the other two types of variables, environment and parameter.

Environment Variables


At the start of any shell script some variables are initialized with values defined in the environment (you can change them with export or in the .bash_profile file). For convenience these variables are all uppercase, as opposed to the user defined that should be lowercase. Here's a list of the main ones and a brief description.
  • $HOME - Home directory of the current user
  • $PATH - The list of directories to search commands
  • $PS1 - The definition of the command prompt (eg: \h:\W \u\$)
  • $PS2 - The secondary prompt, usually >
  • $IFS - Input Field Separator. List of characters used to separate words when reading input
  • $0 - The name of the shell script
  • $# - The number of parameters passed
  • $$ - The PID of the shell script (normally used to create temporary files)
If you want to check all your environment variables just type printenv in the shell.

IBM has a pretty good hands on post to understand the setting and unsetting of environment variables, here, and refer to this other post for a more extensive overview of variables.

Parameter Variables


If your scripts is invoked with parameters it has some more variables which are defined (you can check if there are any parameters if the $# variable has a value greater than 0). These are the parameter variables:
  • $1, $2, ... - The parameters given to the script in order
  • $* - A list of all parameters in a single variables, separated by the first character in IFS
  • $@ - A variation of $*, that always uses a space to separate the parameters
I've written a small script that should make the difference between $* and $@ clear:

#!/bin/bash

export IFS=*
echo "IFS = $IFS"
echo "With IFS - $*"
echo "Without IFS - $@"

exit 0

Run it as ./script param1 param2 param3 ...

Note: The export command sets the variable for the script and all its subordinates.

Conditions


One the fundamental things of any programming language is the ability to test conditions. A shell script can test the exit code of any command it invokes, even of scripts written by you. That is why it is very important to include an exit command with a value (0 if it is ok), at the end of all your scripts.

The commands used to test conditions are two synonyms, test and [. Obviously, if you use [ it must have a matching ], and because it makes your code much easier to read, this is the most used construct.

In a shell script, a test should look something like

if [ -f file ]
then
    echo "File exists"
else
    echo "File does not exist"
fi

The exit code of either these commands is what determines the veracity or not of the statement (again, 0 for true and 1 for false). A little thing to remember is that [ is a command, therefore you must put spaces between it and the condition, or else it won't work.

There are 3 types of conditions that can be used with these commands:

String Comparison

  • string1 = string2 - True if strings are equal
  • string1 != string2 - True if strings are not equal
  • -n string - True if string is not null
  • -z string - True if string is null (empty)

Arithmetic Comparison

  • exp1 -eq exp2 - True if the expressions are equal
  • exp1 -ne exp2 - True if the expressions are not equal
  • exp1 -gt exp2 - True if exp1 is greater than exp2
  • exp1 -ge exp2 - True if exp1 is greater than or equal to exp2
  • exp1 -lt exp2 - True if exp1 is less than exp2
  • exp1 -le exp2 - True if exp1 is less than or equal to exp2
  • ! exp - True if the expression is false and vice versa

File Conditional

  • -d file - True if the file is a directory
  • -e file - True if the file exists (-f is usually used instead)
  • -f file - True if the file is a regular file
  • -g file - True if set-group-id is set on file
  • -u file - True if the set-user-id is set on file
  • -s file - True if the file has nonzero size
  • -r file - True if the file is readable
  • -w file - True if the file is writable
  • -x file - True is the file is executable
These are the more commonly used options, for a complete list type help test in your bash.

Tuesday, September 14, 2010

Bash 101: The Shell as a Programming Language

There are two different ways of writing shell programs, interactively (type a sequence of commands on the shell and let it execute them), or store the commands in a file that can be invoked as a program. We'll focus on the later, but having in mind that they are pretty much alike.

The first little "trick" you should be aware of are the wildcard expansions (or globbing), here are some of the most used:
  • * - Matches any string of characters
  • ? - Matches any character
  • [...] - Matches the defined characters
  • [^...] - Negates the previous one (everything but what matches)
  • {...} -  Matches the specified strings
Here's an example of the last one:
ls my_{file,doc}s

Which will list the files my_files and my_docs.

There is another thing you should know before starting to write bash scripts and that's the $(...) operation. What it does is represent the output of the program you invoke inside the brackets. Let's see it with an example:

Note:
  1. If the string contains spaces it must be delimited by quote marks;
  2. There can't be any spaces before or after the equal sign.
You can also assign user input to a variable, using read. It waits for the user to write something and press Enter. At that moment the variable has been assigned what the user wrote:

$read variable
abcde (Enter)
$echo $variable
abcde


At this time you're ready for your first program. In order to do that just open your favorite text editor and write the commands.

Comments in bash are represented by the character #, and continue to the end of the line. The only exception is the first line that should start with #! and the path to the program used to run the file (usually /bin/bash). Also by convention the last line of the file should be exit 0 (for now just know that 0 represents successful in shell programming).

The actual script could be something like this:

#!/bin/bash

echo "Name of file to cat:"
read file
cat $file

greeting="\nHello World"
echo -e $greeting

exit 0


This script waits for the name of a file, "cats" it and then writes Hello World to the output (not worrying with errors such as the file not existing).

The final step is to make the file executable, with chmod:
$chmod +x file
and run it!
$./filename

Monday, August 30, 2010

Accessor Methods

Following my last post, I'm going to talk a little bit about the accessor methods in Objective-C.

Accessor methods, as you may know, are those methods used to get or set the value of an object's variable, without actually "seeing" it. As you might imagine these methods are used many times in most, if not all, object-oriented programming languages. Objective-C 2.0 provides a very elegant way to declare these methods and saving a lot of lines of code.

It uses the key words @property and @synthesize. In general, a declaration of a property looks like this:

@property (attributes) type name;

The attributes can include readwrite (default) or readonly (doesn't get a setter method). To describe how the setter works it can also include assign, retain or copy.
  • assign (default) - simple assignment, does not retain the new value. If it's an object type and you're not using the GC, don't use this.
  • retain - releases the old value and retains the new. With GC is the same as assign.
  • copy - makes a copy of the new value and assigns the variable to the copy. (often used for strings).
So, a property declaration in the header file should look something like this:


@interface ClassName : NSObject {
    int foo;
}
@property (readwrite,assign) int foo;
@end


And then, in the implementation file you just need to write @synthesize foo; and your accessor methods are defined.

NOTE: There are two ways of using these methods, the normal one is by sending a
message to the object:

[object setValue:newValue];

and there is the other way, that's called the dot syntax and is a lot like what you do in Java:

object.value = newValue;

Although you can use the dot syntax, I do not recommend it. Read this post for the reasons why.

Sunday, August 29, 2010

An Objective-C/Cocoa character counter program

I've been learning Objective-C and Cocoa since yesterday (yes, I'm a newbie, so don't judge... :P), but I'm really loving it.

For those who have no idea of what this is, Objective-C is a C object oriented extension and Cocoa is, according to the Wikipedia, one of Apple Inc.'s native object-oriented API's for the Mac OS X operating system. Both of them together provide a great way to create programs to Mac OS X.

I'm not going to try to explain Objective-C or Cocoa in detail, there are really good books for that (the idea for this example was taken from Cocoa® Programming for Mac® OS X (3rd Edition)), nor will I explain how to use Xcode as an IDE. I'll just write the code and a little explanation of what it does.

So, let's get to what really matters, the code! :D

Every class in Obj-C is composed by two files a header file (.h) and a source file (.m). The first one has the instance variables and methods declarations and the second one the actual code (remember that Objective-C is an extension of C).

Our header file will be something like this:

#import <Cocoa/Cocoa.h>

@interface Counter : NSObject {
    IBOutlet NSTextField *line;
    IBOutlet NSTextField *output;
}

-(IBAction)count:(id)sender;
@end


The first line imports the declaration of NSObject which Counter inherits from, similar to Java's Object. All the Objective-C keywords start with @, to minimize conflicts with C code, as @interface.

Both instance variables are of type pointer to NSTextField, that can be either a text field or a label. IBOutlet is a macro that evaluates to nothing, it's a hint to the Interface Builder.

Finally, there's the method declaration. The method has the name count, returns IBAction (the same as void, also a hint for the IB) and has one argument named sender and of type id (a pointer to any type of object).

The .m file will have to implement the declared method (Java's public methods), but other methods can be declared as well, new methods (Java's private methods) or override inherited methods. Ours will be like this:


#import "Counter.h"

@implementation Counter

-(void)awakeFromNib
{
    [output setStringValue:@"???"];
}
   
-(IBAction)count:(id)sender
{
    NSString *theLine = [line stringValue];
    int noChars = [theLine length];
    NSLog(@"Counted %d chars",noChars);
    [output setStringValue:[NSString stringWithFormat:@"'%@' has %d characters", theLine, noChars]];
}   

@end


The nib file is a collection of objects that have been archived. When the program is launched, the objects are brought back to life before the application handles any events from the user. After being brought to life but before any events are handled, all objects are automatically sent the message awakeFromNib. This means that the label will have the string value "???" when the program starts, it should look like the following picture:


In the Interface Builder you should connect the text field and label to the corresponding outlets and the action of the button to the count method. For this you will have to add an object of the class Counter to the Doc Window.


Now, you've made sure the count method will be called when the button is pressed. So, what does the count method do?

It's actually a pretty simple method, it gets the string the user has typed, by sending the stringValue message to the text field (this method is an accessor, the correspondent to Java's get). It then sends the length message to the string, to get the number of characters. We now have all the information we need.

After that it writes the character number to the console, and finally it sets the label's string.

The final result should be something like this:



In this code I assume that you have a version of Mac OS above 10.4 and that you have the garbage collector on. I'll cover the usage of retain counts, the alternative solution to the GC in the future.

Saturday, August 28, 2010

How to create a man page

OA very useful thing, as everyone that has ever used a shell knows, are the man pages. In this post I'll explain how to create a man page for your programs, from scratch.

First you have to create a file and write the actual text for the man page, using some special tags, the most important can be found here. This is the main step of the creation of the man page, and where you should spend most of the time.

So that you can check how your man page will look while you're writing it and/or after you've written it, there is a very useful program, nroff, that is used the following way:

nroff -e -mandoc yourFile | less -s

Once you feel your page is as you want it, you'll have to rename your file to XXX.1 (or any other number from 1 to 8, according to this standard) and then compress it using gzip or bzip2. Your man page is now ready!

If you try the command man yourFile, you'll notice it doesn't work. That's because you're man page isn't in the MANPATH yet. To do this you'll first have to move your file to a directory with the name manX, being X the number you chose from the 8 possible (it is normal to have a directory called man and all the manX directories to be it's children). So, let's do that:

mkdir path/to/program/man
mkdir path/to/program/man/man1
mv yourFile.1.gz path/to/program/man/man1


The last thing to be done is actually adding your man folder to the MANPATH, if it isn't already added. The first thing to do is check if you have to add it or not:

echo $MANPATH (Just to check if the folder is in the current MANPATH)
export MANPATH=path/to/program/man:$MANPATH


Instead of doing this, if you have root privileges, you can create a directory in one of the directories already pointed by the MANPATH, like /usr/share/man.

And that's it! Go try it out!

Thursday, August 26, 2010

Writing to NTFS with Mac OS

I recently had the need to write to an NTFS formatted disk and found out that I only had read permissions. I could not have this, therefore, and after some Internet searching,  I found out how to do this. This "hack" is a really easy one, but really useful as well, nonetheless.

Native file handling capabilities of the Mac Os can be extended using Google's MacFUSE, as can be read at the project's home page. At the same page you can download the .dmg and install it.

You're halfway through. Now you just need the NTFS part, that can be downloaded here, install it, restart and you're good to go!

The Tuxera product needs a license after 15 days, if you find one that works just the same and is free, please tell me something.

*UPDATE*: See the comments for a free product.