Categories
Git

Git – rename branch locally and remote

Sometimes I need to rename a git branch because I had to break down the feature in smaller bits or other circumstances that somehow require a revision name change.

Local rename

So how to rename the branch locally? It’s a 2 step process:

# Checkout the branch you want to rename
git co <old branch name>

# Now rename the branch
git branch -m <new branch name>

# There is also a shortcut
git branch -m <old branch name> <new branch name>

You can verify the rename is succesful with this

git branch --list

Remote rename

Once the local rename is successful, the rename of the remote branch needs to be done. It isn’t possible to rename a remote branch, but removing it and pushing the local branch in the new name is.

# Remove the old branch
git push origin --delete <old branch name>
git push origin :old_branch_name new_branch_name

# I learned if I just push the new branch it will push to # the old name. Therefore if I use tracking I must unset # the upstream branch
git branch --unset-upstream

# Then I can push the new branch
git push origin -u <new branch name>
Categories
Virtualization

Vagrant synced directories

I’ve often been wanting to mount a dir on the host system, when spinning up a vagrant server.

Here is how I did it. First I had to install the vagrant-vbguest plugin. With this one liner

vagrant plugin install vagrant-vbguest

Then I added this to my Vagrantfile

Vagrant.configure("2") do |config|
 config.vm.synced_folder "tmp/", "/opt/tmp", owner: "root", group: "root"
end

and did a vagrant reload and presto – vagrant mounted the tmp folder inside /opt/tmp

Categories
elasticsearch ruby search

Elastic Search, Hacking the Y-combinator

I’ve wanted to dive into Elastic search and see what it does for sometime. Mostly to see how it was working with it.

Search Basics

When you first dive into search, there’s a couple of concepts you need to know about.

Documents

We denormalize our data into documents. Typical use cases for applying a search engine is on heavily normalized data, that needs to be combined into arbitrary queries, that would make ordinary sql statements too slow or complex, thus joining multiple tables, to only return a few columns.

Other usecases could be fulltext search or geospatial data. Documents are represented by JSON, which makes it a delight to work with.

The index

Documents are stored in an index. The index is what we search in. As the name state, it is fast to lookup documents in it. In Eleastic Search, the index is a lucene based index. The greater part of the index is typically loaded into memory, but persisted to disc at index time. So it can be reloaded in case of a server failure.

The schema

The document structure of the index is defined by a schema. In Elastic Search the schema is dynamic, so it’s possible to virtually throw anything at it.

In other lucene based search engines i.e. Solr, the schema is static and singular to the server instance. This means the server will have to be reloaded in order for a schema change to take place, and only one index is served. This clearly has its disadvantages.

Te have some structure to the index, we provide a mappings. Which basically define the data types our document should consist of.

Here I’ve listed an entry for one of the documents.

{
  "_index":"ycombinator",
  "_type":"items",
  "_id":"s6T7pwLNS8y1r4aUQXsoEA",
  "_score":1.0, "_source" : {
    "identifier":"7375376",
    "author":"summerdown2",
    "content":"Very addictive and lots of fun :)",
    "link":"item?id=7375376",
    "points":null,
    "parent":7373566
  }
}

Indexes, Shards, Replica, Nodes, Clusters

Elastic Search operates with multiple indexes. A single index is made of shards, which can be scattered over multiple nodes in a cluster. Each shard can have a replica, which is an exact copy of a shard. This is used to enhance search performance, and as duplication in case of failure.

Indexes support basic create and delete operations on the fly.

Indexing

So getting data into the search engine is actually a project on its own. Basically there are two ways of populating an index.

  • Push data to elastic search, when it is modified
  • Query the database for delta changes

The first strategy works nicely if you have a monolithic system of one. If you have multiple sub systems that interact with your data, it would make sense to query the database for deltas.

The indexing task for this project is querying the database, because faults might appear when parsing the ycombinator for data.

Looking at the Item the record boils down to

require 'elastic'

class Item < ActiveRecord::Base
  def re_index
    elastic = Elastic.instance
    body = ItemSerializer.new(self).to_json
    elastic.add_item(body)
  end
end

The serializer is a simple ActiveModel::Serializer which removes the root element and adds the attributes I want in the index.

class ItemSerializer < ActiveModel::Serializer
  self.root = false
  attributes :identifier, :author, :content, :link, :points, :parent
end

The interaction with ElasticSearch is wrapped in the Elastic class.

require 'elasticsearch'

class Elastic
  include Singleton

  # This creates the index and types at
  # '/name/type/'
  # making the documents available
  def create_index(name, type, body)
    client.index index: name, type: type, body: body
  end

  # Adds documents of type items to the index ycombinator
  def add_item(body)
    create_index('ycombinator', 'items', body)
  end

  # Creates the ElasticSearch client
  def client
    Elasticsearch::Client.new log: true
  end
end

Queries

Finding things again in the index is nicely done using the lucene syntax.

Basic syntax
http://localhost:9200/ycombinator/items/_search?q=<query>

Giving query the following:
author:gebe        # Will return documents with author gebe
+author:gebe       # Will make author=gebe mandatory for results
-author:gebe       # Will make exclude author gebe from results

Querying throug the gem would add this to the Elastic class

def search(options = {})
  client.search(index: 'ycombinator', type: 'items', body: options)
end

A search for the string nice in the content would look like this

result = es.search( query: { match: { content: 'nice' } } )

Facets

Facets are a way of summerizing on the data in the index. Lets assume I want to find how many items an author have created, I could as the index to facet over authors.

This would change our query to this

result = es.search( query: { match: { content: 'nice'}},
            facets: { tags: { terms: { field: 'author' } }} )

This actually combines the search result with the facets.

More

This is far from an exhaustive example of ElasticSearch. More a sort of scratching the surface.

If you want to check out the code I used, you can find it on Github

Categories
rails ruby

simple_form lessons

So I’ve messed with simple_form, another great project from José Valim.

I’ve gathered some of my lessons learned in this post. First of all I’m skipping the basics, since that’s covered just fine in the README.

Notes On Configuration

Remember to flip your rails server, when you do configuration changes. They will not be loaded on the fly in development.

Wrappers

Wrappers was one of the things I had to dig in to, before figuring out how they work. The documentation explains how to set them up, but not really how they work.

So a wrapper is a configuration set that tells simple_form, how to render the components your form use. But what does that mean?

Let’s look at a simple wrapper, looking something like this:

config.wrappers :simple, tag: :div, error_class: :field_error, class: :form_field do |b|
  b.use :html5
  b.use :label
  b.use :input
  b.use :hint,  wrap_with: { tag: :span, class: :hint }
  b.use :error, wrap_with: { tag: :span, class: :error }
end

When you use this wrapper in a form, like this

# Here the wrapper is applied to all of the elements of the form
<%= simple_form_for @profile, wrapper: :simple do |f| %>
  <%= f.input :first_name %>
<% end %>

# Here it is only applied to the single field
<%= simple_form_for @profile do |f| %>
  <%= f.input :first_name, wrapper: :simple %>
<% end %>

Yes yes, but what does it do? Well … It wraps. Our first_name input field friend from above, will be wrapped, like this

<div class="form_field string required profile_first_name">
  <label class="string required control-label" for="profile_first_name">
    First name<abbr title="required">*</abbr>
  </label>
  <input class="string required" id="profile_first_name" name="profile[first_name]" size="50" type="text">
</div>

So there’s a lot going on, and simple_form is indeed a powerful ally in maintaning forms across an application.

You can even nest the wrappers.

Custom input

Custom input types goes into the app/inputs folder. They will be loaded by simple_form.

Let’s take a look at a simple example. I want to add a weight type, thus appending the text kg to the input field.

It is as simple as this

class WeightInput < SimpleForm::Inputs::NumericInput
  def input
    out = ''
    out << super # Render what the super class has to offer
    out << template.content_tag(:span, I18n.t('simple_form.units.defaults.kg'))
    out.html_safe
  end
end

You can build your output, prepending, appending and pretty much do what you like with the fields.

The above turns into this

<input class="numeric weight optional" type="number" name="..."><span>Kg</span>

More to come…

Categories
gem ruby

ctags_ruby gem

I created a gem for doing ctags on my ruby project files and gem dependencies. Basically it will find all ruby files in your project, and run ctags on them. Then it will dive into your Gemfile and trawl through the source files of each gem.

It will store tags in .tags and .gemtags respectively.

Installing it

Just do agem install ctags_ruby

gem install ctags_ruby

Making that play nice in vim

Simply add the following to your .vimrc

set tags=.tags,.gemtags

And you’re good to go.