Archive forRuby On Rails

Mac Leopard, ROR 2.2 and MySQL

Finally, I found a nice solution for the RoR 2.2 MySQL problem. The initial problem was that the MySQL library isn’t bundled with RoR anymore, and you need to install it as a gem. No big deal at first, but we Leopard users are “plagued” with the fact that Apple has somewhat of an exotic installation method of web programming.

The stock MySQL and Apache are both 64bit, but the Ruby interpreter is 32 bit. That’s why you can’t use the 32 or 64 bit MySQL library gem. I found a lot of “idea’s” on the net, but none of them helped out, or I didn’t think they where good enough.

One of them was to run a second MySQL instance on 32bit. A lot of users solved  that way but I found it just stupid running 2 MySQL instances. So then it struck me, why not recompiling the stock MySQL as a universal build that supports both 32 and 64 bit?

So I did. I downloaded the source from the MySQL website and compiled it like this:

MACOSX_DEPLOYMENT_TARGET=10.5 \
CFLAGS='-O3 -fno-common -arch i386 -arch x86_64' \
LDFLAGS='-O3 -arch i386 -arch x86_64' \
CXXFLAGS='-O3 -fno-common -arch i386 -arch x86_64' \
./configure \
'--disable-dependency-tracking' \
'--prefix=/usr/local/mysql' \
'--localstatedir=/usr/local/mysql/data' \
'--libexecdir=/usr/local/mysql/bin' \
'--with-comment=MySQL Community Server (GPL)' \
'--enable-thread-safe-client' \
'--enable-local-infile' \
'--enable-shared' \
'--with-zlib-dir=bundled' \
'--with-big-tables' \
--with-readline \
'--without-docs' \
'--with-plugins=myisam,innobase'

And my problem was solved. I had one MySQL instance running, and I finally could use RoR 2.2.

Now the only problem remaining is getting PHP to run properly.

Comments

Mac, though love

I recently made the switch to mac. I just love working with it. But I’m experiencing some downsides to it. This is probably due to lack of knowledge about Mac.

Like most of you know, I’m in the web development business. So I need PHP and Ruby on Rails.

I was happy to notice that PHP en RoR where installed by default on Leopard. But then I needed MySQL PDO. Hmm, the default PHP installation doesn’t support MySQL PDO. So I need to recompile. So I downloaded the PHP source and tried to recompile it with almost the same parameters I found of my previous installation. But still no go. I just gave up at the moment.

Then next thing happend. RoR 2.2 came out. So I wanted to upgrade. I upgrade an old experimental app and tried to run it. Oops, looks like RoR doesn’t ship anymore with mysql library. After a quick google, I noticed I had to install the mysql 2.7 gem.

Ok, that’s easy. Tried to install it, but ran into errors. So after some more googling I saw that other mac users ran into the same problem and various solutions where found. But, none of them worked for me. Well, I didn’t tried them all. Some of the solutions mentioned installing both 64 and 32 bit version of MySQL. Well, I just like to run a clean system and not messing with diffrent installations.

I googled a lot lately but still didn’t found a solution for both of my problems. So if any of you readers might have found a solution to help me out, please do share.

Comments

Create sub folders in your Rails application

I got some nice emails conserning my restful search and the Object-oriented approach to ActiveRecord posts.

But a few of those mails had another thing in common. Some users find all the finder classes in the helper folder overwhelming, and they don’t like having them in the same folder as their view helpers.

Well, the thing you can do, is put all the finder classes in a subfolder. Lets call the subfolder “finders”, just for the fun of it :p.

Now Rails won’t load those finders anymore, since it won’t recognize your newly created subfolder. So open your environment.rb file and paste in the following code:

  Dir.glob("#{RAILS_ROOT}/app/helpers/*[^(.rb|.ignore)]").each{|dir| config.load_paths << dir }

This will tell Rails to load all files and folders in the helpers folder, that don't contain .rb or .ignore in its name.

So all the view helpers won't get loaded again, and if you have a subfolder that you don't need to be loaded anymore in your helpers folder, but still want the code, you can just rename the folder.

So I hope this might help you guys keeping your application clean. Offcoure you can also use this on other subfolders you might want to create ;)

Comments

RESTful search

During the development of my new project, I read a lot on the REST subject. In my opinion, it is a nice way of keeping your application clean and maintainable. But I stumbled upon a small problem when I had to implement a search for my resources.

In all the examples you find on the net, you will see how to create your basic CRUD actions in REST. So create, update and delete isn’t a problem at all. But when it came to implement a search system, you find nothing. Well, nothing is a big word, you do find posts, but all of them work diffrent.

The first thing I needed to do was to deside how I would handle the search. The first possibility is to create a new controller so it would fit in the REST filosophy. Just see the search as a resource. I didn’t realy feel right to see a search as a separate resource. I just see the search as a filter on an existing resource, so why defining the search as a resource of its own??

The next logical step was just adding a new action in my resource controller called search. But again, a new action just to search? Not a real good idea I think. Like I said before, a search is just a filter on your list, so I should be part of the index action.

So there we go. We just send our search parameters to the index action and filter our list there where it should happen.

If it was just as simple as that. You can’t just use a normal POST method form, becouse Rails will see that as create. And if I would use the GET method, all the search parameters would apear in the address bar. I know thats not a big of a deal, but I personaly think that isn’t realy clean.

But then it came to me. We live in an age where you can’t find an application without Ajax. So why not implement our search with Ajax? This way, we can send a GET request with our search parameters to the controller and rebuild our list without having to reload the hole page.

Some readers might think, building your search in the index action will make your index action look ugly. Well, for those readers, check out my previous post on building your query string dynamically in an object-oriented way with ActiveRecord.

As far as I know, this is the cleanest way to implement a search the RESTful way. But ofcourse, this is just my vision on the subject, and other developers will say you HAVE to create a separate controller. But if you think like me, and can’t comprehend why a search is a separate resource, my filosophy will be a nice way to follow.

If you have some input or improvements, please do share them :)

Comments (1)

REST design with extra actions

Yesterday, I had to add some extra actions in my controllers, so I could view some charts. The problem was that Rails didn’t recognize the actions, becouse Rails sees you action name as an id.

But Rails wouldn’t be Rails if it didn’t had a clever solution. Lets say you have a a resource called “Resource” and a similar controller. You want to add a new action and view to the resource controller named “charts” .

Just open your routes.rb file and find the line where you map the resource and add the following:

1
  map.resources :resource, :collection => [:charts], :member => [:print_pdf]

For the sake of being complete, if have added a member. The diffrence between a collection and a member is that collections work on all items of that resource (no id needed, like index action),
so:

1
  charts_resources_path()

could be used and give you a page with covering the charts of all resources

while a member works on a single item of the resource, defined by it’s id

1
print_pdf_resource_path(1234)

would print the resource with id 1234 as pdf

of course like with all other REST actions (or CRUD actions, to be correct) you can use additional named params like:

1
2
chart_resources_path(:type => :monthly)
print_pdf_resource_path(1234, :font => "Arial")

Comments

Object-oriented approach to ActiveRecord

One of my colleges (the main programmer for the company I work for) has created a nice post on creating dynamic search criteria in an object-oriented way using Rails ActiveRecord. You can find his post here.

At first, I was a little out of balance, becouse I couldn’t realy see the advantage of it. But now after working on a few big rails projects, I realized quickly that this was a real neat way of generating a query in ActiveRecord.  Yet, I had to make a few changes.

First, create a class called record_finder.rb and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class RecordFinder
 
  attr_reader :parameters
  attr_accessor :order_by 
 
  def initialize (bool_mode = 'AND')
    @bool_mode = bool_mode
    @sqls = []
    @parameters = []
    @includes = []
    @order_by = ''
  end
 
  def add (sql, *params)
    @sqls << sql
    @parameters += params
  end
 
  def add_ref(field, int)
    add "#{field.to_s} = ?", int
  end
 
  def add_wildcard(field, value)
    add "#{field.to_s} LIKE ?", "%#{value}%"
  end
 
  def add_range(field, range)
    if field.instance_of?(Hash)
      add "#{field['from']} >= ?", range['from']
      add "#{field['until']} <= ?", range['until']      
    else
      add "#{field} >= ?", range['from']
      add "#{field} <= ?", range['until']
    end      
  end
 
  def has_conditions?
    @sqls.filled?
  end
 
  def add_finder(finder)
    if finder.has_conditions?
      @sqls << finder.sql_string
      @parameters += finder.parameters
    end
  end
 
  def sql_string
    @sqls.collect{|sql| "(#{sql})"}.join(" #{@bool_mode} ")
  end
 
  def get
    if @sqls.length > 0
      [ sql_string ] + @parameters
    else
      nil
    end
  end
 
  def get_all
    options = {
      :include => @includes,
      :conditions => get,
    }
 
    if @order_by.filled?
       options[:order] = @order_by
    end
 
    return options
  end
 
  def include(path)
    unless @includes.include? path
      @includes << path
    end
  end
 
  def is_empty(var)
    return var == nil || var == ""
  end
end

The only special diffrence is the add_range action. With the add_range, you can search for a field in a sertain range. If the parameter is a Hash, you can use it to filter a record that has a start and end date. Otherwise, you just filter a range on one field.

The next step is to create a finder class that inherets from the RecordFinder class for all the resources you wish to search through. It might look like something as this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class ResourceFinder < RecordFinder
  def by_user(user_id)
    add("user_id = ?", user_id)
  end
 
  def by_name(name)
    add_wildcard("name", name)
  end
 
  def read_search(search)
    if search
      self.by_name unless is_empty(search[:name])
    end
  end 
end

Now, you have 2 options on how to build your query. The first one is to call for all the actions needed in your controller like this:

1
2
3
4
5
  finder = ResourceFinder.new  
  finder.by_user(session[:user].id)
  finder.by_name(params[:search][:name])  
 
  @resource = Resource.find(:all, finder.get)

Now you build your search in your controller. But if you have a lot of search parameters, your index action could get ugly after a while. That’s why I have created the read_search action in my ResourceFinder.rb class. Just pass you search hash to it, and build your query in there. This way, you build-up is centered in the finder class and your controller stays neat and clean :)

Comments

Rails breadcrumbs

As I was working on my new project, I was in need of a some breadcrumbs to implement on my site. Since I hate doing the same task over and over again, I looked for a ready to deploy plugin. After some googling, I quicly realized that a standard way of creating breadcrumbs is virtualy impossible.

The way of creating your bread trail can depend on diffrent situations and can change from project to project. I just think that this way of generating your bread trail I realy neat, and would fit about 80% of most projects. The application controller code can even serve as a starting point for generating the trail dynamicaly.

Start and put the following in your application_controller.rb file:

 protected
   def add_breadcrumb name, url = ''
     @breadcrumbs ||= []
     url = eval(url) if url =~ /_path|_url/
     @breadcrumbs &lt;&lt; [name, url]
   end  
 
   def self.add_breadcrumb name, url, options = {}
     before_filter options do |controller|
       controller.send(:add_breadcrumb, name, url)
     end
   end

Theses methods will be used in other controllers to build up the trail. Offcourse, every trail starts with the Home page. So it would be stupid to repeat that in every controller. The author of the blog post suggested to put

add_breadcrumb 'Home', '/'

in the top of your application controller, but that gave some problems for me. So what I did is, since I use the initialize method in my application method, is just to put the code right there.

So how do you continue to build up the trail you might think now? Just open an arbitrary controller and add something similar to the top:

  add_breadcrumb 'Resource', '/resources'
  add_breadcrumb 'List', '', :only =&gt; [:index, :destroy]
  add_breadcrumb 'Create a new resource', '', :only =&gt; [:new, :create]
  add_breadcrumb 'Edit a resource', '', :only =&gt; [:edit, :update]

This way, all your crumb entries are grouped at the top of the controller. But if you need to customize, you can just add an entry in your action aswell.

Now, you would like to view your breadcrumbs. Go to the right view (most likely you default layout page) and add the following code:

<%= @breadcrumbs.map { |txt, path| "
  • #{link_to_unless(path.blank?, h(txt), path)}
  • " } %>

    Source: http://szeryf.wordpress.com/2008/06/13/easy-and-flexible-breadcrumbs-for-rails/

    Comments (2)

    Google Gears meets Ruby on Rails

    It has been a while since I posted something new. But I have a few articles in mind that I will post soon.

    The first one is something that I discovered a few days ago. The fantastic toolkit Google Gears that enables webapplications to work offline has met RoR.

    2 students, Michael Marcus and Rui Ma, have made it all possible. I haven’t had the time to play with it yet, but I’m working on a small project now that fits the need to experiment with.

    The things I can tell is that they wrote some sort of a wrapper that to work with all the javascript api’s that Gears has. Next to that wrapper, you still need some javascript to work within the browser, but the syntax looks very ruby-ish.

    Becouse crud-actions over http can be simulated, we can use the same views and controllers like we would use for a normal online application.

    The two students hope they can make it available as a plugin soon, so it can be used in existing projects.

    For more info, check out the Gears on Rails project page.

    Comments

    Rails new template file extensions

    For some of you that don’t know this yet (don’t be ashamed of yourself, I only heared about it a a few months back), Rails 2 recommends a new file extension for your template file.
    At this point, everyone was using template extensions like:

    • .rhtml
    • .rxml
    • .rjs

    To unify the template files, the Rails developers have come with a clever solution: chaning the template extensions so that they math up and tell you in what format they are.
    By doing this, your new template extensions should look like this:

    • .html.erb
    • .xml.erb
    • .js.rjs

    You are probably thinking: “everything looks alike now, except the rjs and haml templates. Why not using .js.erb?

    Well, the answer is quite simple.

    • .html.erb -> response format is in HTML,  parsed with ERB
    • .html.haml -> response format in HTML, parsed with HAML
    • .xml.erb -> response format in XML, parsed with ERB
    • .js.rjs -> response format in JavaScript, parsed with RJS

    If someone ever came up with a plugin that does the same Javascript actions for some templates. Those templates could be called .js.dudesplugin .

    You see now? It all makes sence. Rails is all about convention, so it wouldn’t make sense to make an exception from the naming scheme for RJS templates.

    Comments

    Rails and foreign keys

    There is one plugin that I use in all my projects, and that is the Foreign Key Migrations plugin from RedHill. Defining foreign keys can’t become easier then this. Since as far as I know, Rails migrations don’t set foreign keys in your database, so this is the best solution. It uses SQL-92 syntax and as such should be compatible with most databases that support foreign-key constraints.

    You can even use it for legacy column names that don’t end with “id”. There is even a generator for creating foreign keys on a database that currently has none, so you can easily start using it even at the end of a project.

    You can download the EDGE, 2.0 stable, 1.2 stable or 1.1.6 release, depending on your Rails version. Don’t forget the you need the RedHill on Rails Core .

    Comments

    « Previous entries