Updating Rails when vendor/rails is under local svn

In some of my projects I have Rails checked out in vendor/rails and I keep it under local subversion repository (not as an external nor ignored). Why? It is sometimes to handy to have just whole application in one repository.

The only problem I encountered is when I need to upgrade Rails version. Normal rake rails:unfreeze && rake rails:freeze:edge TAG=rel_x-y-z is not solution, since unfreeze just deletes vendor/rails along with svn metadata and importing Rails source every upgrade makes Your repository grow. Sure upgrades are not so often, but when lifespan of project is over a year…

Besides, deleting makes svn client refuse to work ;) maybe someone with high svn-fu knowledge would make it, but I use just this simple procedure. Let’s assume I’m upgrading from 1.2.3 to 1.2.5:

cd vendor/rails
rm -f TAG_rel_1-2-3
for i in *; do
  svn export  --force http://svn.rubyonrails.org/rails/tags/rel_1-2-5/$i
done
touch TAG_rel_1-2-5
rake svn COMMIT_MSG='new rails version'

The last command is using this simple rake task to import all changes to SVN. Code from above is bash command line and was tested on FreeBSD. And in case new version of Rails adds new directories, this way You won’t fetch them.

Rails in production and code reloading

When I have discovered Rails through 4 Days on Rails over a year and half ago, I decided to buy Agile Web Development with Rails, which is great book for learning Rails. And there I found following statement (page 52):

It turns out that the WEBrick-based Rails dispatcher is pretty clever. In development mode (as opposed to testing or production), it automatically reloads application source files when a new request comes along. That way, when we edit our application, the dispatcher makes sure itís running the most recent changes. This is great for development.

This is true, but You have to remember what application source files mean in this context. As I wrote earlier reloaded are files from app directory (and at least part from config since changes in routing are in effect without restart). Code in lib is not reloaded.

Well this I have knew from long time, but yesterday I have learned something new (for me) about Rails in production mode. From quote above I was thinking production server does not re-read code from app directory at all. Boy, I was wrong.

First, I discovered very stupid error in Run-N-Share. I used embedded map to present info how to get to Bootstrap meeting (polish web site). Bootstrap is our monthly local meetup, where we discuss new trends, technologies and people share with own experiences running business in web 2.0 world.

I draw a route used code presented on page to embed it on Bootstrap blog and… I saw this route. What the heck?!? Quick look in RNS code and I found my stupid mistake – I did not create link to copy and paste with real route ID, I have just hard coded link to widget with ID 1. Grrrr… I made quick fix, deployed code to production site. Reloaded webpage without app restart. And saw that production server have noticed change in RHTML template without restart.

Production server does cache only real Ruby code and RHTML templates are just plain data files in this context. So any change made in RHTML template is in effect without application restart…

Ruby Tk

Recently I wrote a lot code with Ruby and Tk. I just need to write some old fashioned GUI application. And being somewhere in 1/3 way with this work, what I can say?

This is my first time I’m using Tk so I’m newcomer to this land, and my first impressions are quite positive (YMMV). Maybe Tk powered GUI looks & feels a bit old-school, but its use is quite straightforward. Nevertheless, I had few struggles with some simple things, so I decided to start here new category Ruby/Tk and put here few examples. I do this since I had troubles with finding good examples to Ruby/Tk.

Maybe a book for a start?

First if You don’t have any prior experience with Tcl/Tk think about purchasing some good book about it. For it have worked very well. I went for Tcl/Tk: A Developer’s Guide by Clif Flynt, and was happy with this. I don’t need Tcl part, and Tk is described in big detail. Of course – this is Tcl/Tk description, not it’s Ruby bindings.

Ruby and Tk – real example

So let’s start with something simple. Window which will allow run ruby code. I needed this to inspect my application status, it was much simpler than using debugger or implementing DRb client.

Code goes here:

require 'tk'

$root = TkRoot.new( :title => "Tk Example", 
	:width => 300, :height => 100)

Tk.root.bind( TkVirtualEvent.new('Control-c', 'Control-q'), 
	proc{Tk.exit})

label = TkLabel.new{ text "Command:" }
label.place(:x => 10, :y => 10)
label.font= TkFont.new(:size => 6)

entry = TkEntry.new
var = TkVariable.new("puts 'test'")

entry.textvariable(var)
entry.place(:x => 10, :y => 30)
entry.bind("FocusOut") { eval var.value }

button = TkButton.new { text "Run" }
button.place(:x => 10, :y => 52)
button.bind("ButtonPress") { eval var.value }

Tk.mainloop

In lines 3-4 we create root window. Code is self explanatory ;) In line 6 and 7 we create virtual event and associating it with lambda calling Tk.exit, or in other words destroys Tk application. TkVirtualEvent allows DRY, since it binds to Control-c or Control-q sequences.

Lines 9-11 create label with word Command on it. Most of objects can be initialized like $root in line 3 or like label in line 9 – code block or function call with hash of args. Line 9 in hash version would be:

label = TkLabel.new( :text => "Command:" )

In line 11 we set non-default font size. It is possible (I mean no error warning, because duck still quacks) to try label.font.size = 6, but it wont give expected result. You need to create new font object with size property.

I use place method to put object on window, most examples uses pack. The latter arranges objects with some built-in magic/logic, but in my application I needed strict control over layout and overlapping objects. This can provide only place method.

In lines 13-14 we create two objects – entry for type in command and variable which will hold it contents. Of course You could create just entry object and have possibility to write something in it, but I don’t know any way to get contents from this entry without TkVariable associated with entry.

This association is made in line 16. Then we place it on window (17) and assign code when entry loses focus. It just evals code typed in this entry. Simple. But can be tricky. Run example, write some code in entry, or just leave default, place cursor in entry field and switch activie window to other application. Surprised? Well… Technically, when You have switched windows entry filed lost focus so code was evaluated…

So maybe we need other way of evaluation – after pressing button with Run. This button is created, placed and code evaluation is assigned in lines 20-22. Nothing new here. Almost. ButtonPress needs more attention. bind can take as argument:

  • alphanumeric – single character (or punctuation, digit, other) which defines what key need to be pressed to fire code binded with this statement
  • virtual event – defined with TkVirtualEvent (we have done it on begging when we wanted provide alternate exit)
  • mod-type-detail or just strict definition what combination events need to happen to fire code. mod – could be B1-5 (mouse buttons), Alt, Control, Shift, Double, Triple. Type could be ButtonPress, ButtonRelease, Motion, FocusIn/Out, KeyPress, KreyRelease. Detail depends on type field. Not all combination are valid. For example change ButtonPress in line 22 for Double-Shift-ButtonPress and You will need to double-click Run button with shift pressed to activate code from entry. ButtonPress itself fires with any mouse button pressed. When we want double-right-click with shift we need to use code>Double-Shift-ButtonPress-3 (button 2 is middle button)

More about arguments for bind You can read in documentation for Active State Tcl/Tk implementation (which is free BTW, so You know where to go for Tk implementation if You want to give it a try).

And last but not least in line 24 we start Tk main loop, from now our GUI is alive and kicking. This example is quite simple but demonstrates few issues I had problem with. Maybe it will be useful for other.

Stay tuned, in future posts – drag&drop layout changes, schedule command execution in future and more ;)