Grammy is a very small recursive descent parser generator framework written in ruby. It has several similarities with boost::spirit.

Short example:

You can use the defined grammar to parse strings:

An example image (not for this grammar):

error: image not loaded

Grammy supports:

  • Most EBNF features: Sequences, Repetition, Alternatives, Optional rules
  • Shortcut for lists: list and list?
  • Skipping of characters: comments, whitespaces between words
  • Generation of an AST. Most unused tokens can be removed automatically.
  • AST can be written to an image file with help of graphviz.

You can get grammy at github: Grammy on github

There is also a more detailed description there.

Problem Graphs

| No Comments | No TrackBacks

This is an idea i came up with during analyzing problems while designing software.

A specific software-design has/causes several problems. Those problems have zero or more (alternative) solutions. These solutions are basically changes to the previous software design that caused the problem. The new software design that solves one or more problems of the initial design can again cause problems, but the problem that was solved with the solution wont be caused (otherwise the solution was not a real solution for the problem).

An example for a problem-graph:

So, a problem has several *alternative* solutions and a solution causes several problems (at once - they are not alternatives).

Dilemma

A cyclic problem-solution situation i call "dilemma", because it cant be solved by a specific solution:

Problem A can be solved with Solution A, which causes problem B, which in turn can be solved by the solution B, which causes problem A. You either solve A with solution A or B with solution B, but you cant solve both.

This does not imply that those problems cant be solved. There might be an alternative solution A2 (which has not been discovered yet) to solution A which does not cause problem B. But for this problem graph you can say: "Solving problem A with solution A leads into a dilemma".

Extensions

Weights

The problem graph idea can be extended: You can assign weights to the arrows. Without weights the causalities can be interpreted as:

  • "The problem P is completely solved by the solution S"
  • "The solution S causes exactly the problems P1 .. Pn"

With weights added it can be interpreted like this:

  • "The problem P is weakly solved by solution S"
  • "The solution S strongly causes problem P1 and weakly causes problem P2"

With these weights you can model non-exact problem relations like:

  • "Spamming can be strongly reduced by introducing captchas"
  • ..
Colors

The problems can be weighted (colored) too, so that you can say "problem X is much more costly than problem Y".

This can easily be extended (eg design algorithms that find optimal solutions for a problem graph etc) but at the moment im too busy.

Just recently i switched from windows XP to ubuntu 9.04. I had some problems (Ubuntu freezes when connecting to WLAN) with my wlan drivers (DLink DWA 547) but after installing the compat-wireless package it worked. But its slower and more unstable than on windows. (After upgrading ubuntu and recompiling the package WLAN works as good as on windows). I tried to install ruby 1.9.1 on ubuntu. After several hours of reading articles and googling i put together these install instructions: Test if the installation worked: Compile readline to get arrow keys support in IRB: Now ruby 1.9.1 without valgrind is installed. Next install valgrind: Now setup another ruby installation with valgrind support. Then add some handy shortcuts: For more information see: UPDATE: Added --enable-shared to RUBY_OPTIONS

Rails Safe

| No Comments | No TrackBacks
Because i am a bit paranoid i sometimes think about protecting my ROR-sourcecode. I came up with this idea:

* Encrypt all files (models,controllers,helpers,views,css,...) with a secret key.
* Upload the encrypted files on your server
* Put the key in a file and upload the file to config/
* When the rails app starts, load the key into memory and delete(!) the key file
* Decrypt files (in memory) of your app when they are loaded

An attacker that got access to the filesystem can't just copy the source since it is encrypted. One problem might be this:
The attacker got write access to the FS and creates a .rb somewhere in a loaded gem or in the rails app. Then he might be able to read out the key and decrypt the source files.

The best way i know to protect the source is to use JRuby and compile the rails app to a jar.
Mysql has a special 'INSERT ... ON DUPLICATE KEY UPDATE' statement which can be used for some models like e.g. ratings. Instead of something similar to this:

You can just do this:

when the row already exists in the database (detected by a unique-constraint violation) the values of that row are updated and saved, otherwise the new row is created.

My current solution is this:

You use it like this:
Warning: You need mysql 5.1 so that LAST_INSERT_ID(id) works. (Mysql bug)

ActionExtension for rails

| No Comments | No TrackBacks
In my rails application i often have this kind of code in my erb/haml files:
There is some repetition in it. Why not infer the i18n-key from the action? My approach:
The parameters should also be passed to the i18n key. So for the first button_to call the translation method is invoked with: _('CommentRating.actions.create',:rating => :good, :comment => @comment)
Some of these ideas are relatively easy to implement:
Requirements:
  • Each model needs an class-method called 'actions'
  • Each model needs an instance-method called 'actions'
  • The actions-methods return an proxy (ActionProxy) that records the method name that is invoked on it (method name = action name)
  • the proxy returns an information object (ActionInformation) that contains:
    1. the instance or the class of the model
    2. the action name
    3. the parameters
  • the ActionInformation has methods that infer the i18n key as well as the url

Now this can be used like this:
Improvements to work on:
  • infer method (:delete etc)
  • dont merge the parameters into the url. make them accessible seperately so they can be extracted and posted via hidden fields inside a form.
  • maybe redefine actions in the models to preprocess the parameters: define_action :rate => lambda{|*params| {:rating => params[1]} }

Haml modification for i18n

| No Comments | No TrackBacks

I'm using the haml plugin in my rails application. In haml you can output plaintext like this:

Since i never output plaintext in my view because i use i18n i decided to modify haml:

So instead of outputting plaintext, you supply a i18n-key and haml outputs the translated text that belongs to that key.

The modification is quick & dirty and just a few lines long:
Go to the haml precompiler.rb and find the render_tag method. There should be a 'switch action' switch. Add the following lines to the switch:
This assumes that '_' is the method that is used for i18n. You can even append parameters:
This invokes _('my.i18n.key.here',:param1 => 'value')

Ruby DataFormat

| No Comments | No TrackBacks
For one project i am currently working on i had to load and parse some binary files with ruby. The parser code was not very nice, so i came up with an idea: The cool thing about this is: The DataFormat is a description of the data format and the code to load and save a file in this data format is generated automatically. So you dont have to worry about the loading and saving code, you just have to specify the format. Some more examples: This one reads an array of values. The data that is returned is an instance of the class AttributeHash. The AttributeHash just wraps an hash and overwrites method_missing to delegate all attribute accesses to the wrapped hash (so it behaves like a javascript object). But you can specify that an instance of some custom class should be created instead of an AttributeHash. Example: The requirement for the class that will be instantiated is just that is must have methods for "attrname=" calls with "attrname" specified in the data format.
The different types that are currently available to describe a data format:

Supported types
NumberSerializer: short, int, long (+unsigned: ushort etc.), float, double
uint :attribute_name, :min => 1145, :max => 67546 
StringSerializer: nullterminated(default) or fixed-length
string :attr_name, :length => 32
MagicSerializer: throws exception when the magic value (in this case 1337) is not found at the pecific position
magic :magic_number, :value => 1337
ArraySerializer: reads an array from the file. The data format of each entry can be specified.
array(:things,:length => :arr_length) do
	int :thing_id
	float :value
end


Status
Experimental version.
Todo:
  • Option to specify if format is big- or little-endian
  • Store errors (eg: integer out of range) in an error hash like in active record
  • Optional elements (if :someattr == 0, then :otherattr is not present)
  • Skip sections (if :someattr == 0, then skip x bytes)
Test syntax highlighting:
See: Max Horvath - Syntax Highlighting for your Movable Type blog

Blog created

Blog created.