When writing new Cucumber scenarios, developers will usually start with a failing scenario, incrementally making it pass, step by step. If this is a common workflow for you, you’ll probably have noticed a trend of having to re-run it each time a new step is failing, adding something like Then show me the page after the last passing step to see why the story is currently failing.
Chendo and I came up with a nifty little solution in just a few lines that really helps this process of seeing what webrat sees when a scenario fails. Throw this snippet of code in a file in your features/support/ directory:
The other day we got some HTML from the designer of one of our clients to implement as the new UI for an app we are building at Mocra. Overall the HTML was good but implementing it started to feel a little moist (i.e. not DRY).
For example, around all the apps form the client’s design had a rounded white box, the HTML of which went something like this:
It’s a lot of div tags to have to repeat around every form that has this style. Luckily a nice feature of Rails partials can help out. Create a shared partial file that will act as a layout like this:
Then in your views that need to have this white box, simply wrap your content in that layout like so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%render:layout=>'shared/fieldset'do %><divclass="frow"><label>Currency:</label><selectclass="fs"><option>EUR</option></select></div><divclass="frow frlast"><label>File:</label><inputtype="file"name="" /></div><%end%><!-- Or, if the inner content is already in a partial --><%=render,:partial=>'form',:layout=>'shared/fieldset'%>
http://ftp2.au.postgresql.org/pub/postgresql/source/v8.4.1/postgresql-8.4.1.tar.bz2 | tar xjf -
cd postgresql-8.4.1
./configure
make && sudo make install
The files are now all installed in the right places, onwards to making them usable!
Create a postgres User and Group
This is adjusted from the instructions in the comments here).
That’s the clean way of making a user (so it doesn’t show up in your Accounts preference pane, etc.
Clean up
1
2
3
4
5
6
7
sudo touch /var/log/psql.log
sudo mkdir /usr/local/pgsql/data
sudo chown -R postgres:postgres /usr/local/pgsql/data /var/log/psql.log
# Put Postgres in your pathexport$PATH="/usr/local/pgsql/bin:$PATH"
sudo sh -c 'echo /usr/local/pgsql/bin > /etc/paths.d/pgsql'
Thanks to Apple we have a nice way of setting the PATH across the entire system so every app should now know how to find the Postgres binaries and the data directory is now set up to store the database files — now, we just need to create them.
# Become the postgres user
sudo su - postgres
# If this throws next commant throws an error about shared memory, # try putting "these lines":http://gist.github.com/224815 into # /etc/sysctl.conf, rebooting, and trying again:
initdb -D /usr/local/pgsql/data -E UTF8
# Start the database
postgres -D /usr/local/pgsql/data >/var/log/psql.log 2>&1&# Create a test database and check you can connect to it
createdb test
psql test# Just create a superuser for general dev tasks
createuser postgres
# we don't want to be the postgres user anymoreexit
Your done with the Postgres setup now!
PostGIS
1
2
3
4
curl http://postgis.refractions.net/download/postgis-1.3.7SVN.tar.gz | tar xzf -
cd postgis-1.3.7SVN
./configure --with-geosconfig=/Library/Frameworks/GEOS.framework/unix/bin/geos-config --with-projdir=/Library/Frameworks/PROJ.framework/unix
make && sudo make install
Phew! That one was easy.
Postgres Ruby Gem
This is the part that everyone cares about the most. If this works your Rails apps should start working like a charm.
A few weeks ago, I was modifying my clone of Enki (my blogging platform) to use Ultraviolet instead of CodeRay, as it supports using both TextMate themes and syntaxes. This means I can extend it fairly limitlessly and use TextMate itself to modify the themes an syntaxes.
However, Ultraviolet doesn’t come with the best tools to turn the TextMate syntax and theme files into files Ultraviolet can use, and the ones that it does provide puts those translated files INTO the gem on your system. This means that you can’t easily deploy or share them.
So, to remedy this I made a small gem Ultraviolet Tools that provides two command line tools: uv-create-syntax and uv-create-theme.
They aren’t very complicated, nor very documented, but they are straight-forward to use:
Install
Install Ultraviolet Tools with sudo gem install bjeanes-ultraviolet-tools -s http://gems.github.com.
Usage
Themes
Run uv-create-theme path/to/theme.tmTheme
Syntaxes
Run uv-create_syntax path/to/syntax.plist or uv-create_syntax path/to/bundle/with/syntaxes.tmBundle
Using the resulting files
Use my fork of ultraviolet as it has an option to change the load path for themes and syntaxes so that you can load them out of your application files.
Just a quick post so show you how fields_for form helper can cause invalid HTML when used in combination with accepts_nested_attributes_for in your views.
If you are for any reason editing/creating your child objects in a tabular form, your view might look something like this:
<%form_for(@todo_list)do |f|%><%= f.label:name%><%= f.text_field:name%><h3>To Do Items:</h3><table><thead><tr><th>To Do Item</th><th>Due Date</th><th>Done?</th></tr></thead><tbody><% f.fields_for:itemsdo |item|%><tr><td><%= item.text_field:content%></td><td><%= item.text_field:due_date%></td><td><%= item.check_box:done%></td></tr><%end%></tbody></table><%= f.submit'Save'%><%end%>
At first glance this looks fine. However, when the ToDoList model has accepts_nested_attributes_for:items, the fields_for helper also outputs a hidden field for each existing Item instance with it’s ID.
I had an “Organization” creation form which allowed an administrator to create an Organization and an initial user for it. However, even though I had filled in all the required fields to pass the validations I was constantly getting the following error: Organization can not be blank.
Digging deeper I found that when an object is added to an association via the association.build method, the parent object isn’t actually set:
1
2
3
4
5
6
>> o =Organization.new(:name=>"Test")=>#<Organization id: nil, name: "Test">>> u = o.users.build(:name=>"Test User")=>#<User id: nil, organization_id: nil, name: "Test User">>> u.organization
=>nil
Apparently this flaw also applies to accepts_nested_attributes_for. When I send through the User params through from my form normally with the Organization params, it creates the User object in the users association as you’d expect, but raises a validation error because the User instance doesn’t recognise that it is has a parent Organization
My quick 5 minute fix was to modify the Organization model thusly:
Related Rails bugs seem to be here and here. This patch will also solve the problem and is currently in edge, but didn’t make it in time for Rails 2.3.
There has been quite an annoying problem that has been bugging @chendo and I today.
In short, fields_for when used with accepts_nested_attributes_for does not reset it’s index when it’s called multiple times for the same attribute.
Our scenario was the following:
We had a 3 levels of hierarchical data that we had to display in a <table>. Because of the nature of the data we were displaying one level as columns and the other level as rows. Unfortunately, HTML mandates that we group everything by rows—each column is really just a single cell. This means that we have to iterate over the “column” values not just once, but once for every row.
Now, fields_for takes care of naming your <input> tags magically with the correct indexes so that your models can accept the params directly and magic happens. However, evidently calling fields_for multiple times was not part of the original intention, and it seems resetting the index after each call was neglected.
@chendo couldn’t see a cleaner way of doing this so we added our own option to reset the index. We didn’t just override the behaviour in case there is a good reason to leave it, but here is our code:
Today after finding the gem AlterEgo and falling in love with the API, @chendo and I came to a sad realisation that its beauty was skin-deep. It seems it is not ActiveRecord-aware and overrides #state and #state= on your models. This means that your state column goes untouched and your models are always in the default state.
To get around this, @chendo and I hacked together this little monkey patch which does two things:
It adds question methods for each of your defined states. So if you have states: active, inactive, and banned on your User model, your instances will have #active?, #inactive?, and #banned? defined.
It properly sets and gets the state of the row and loads it into AlterEgo.
moduleAlterEgodefself.included(base)
base.instance_eval do# This will allow us to define a question method for each state in a class# For instance if user has states :active and :inactive, methods active? and inactive?# will be defined when first calleddefmethod_missing_with_states(method,*args,&block)begin
method_missing_without_states(method,*args,&block)rescueNoMethodError=> e
state_found =false
result =nil
base.states.keys.each do |state|if method.to_s =="#{state}?"&&!state_found
self.class.send :define_method,"#{state}?"doself.state == state
end
state_found =true
result =self.__send__(method)endendraise(e)unless state_found
result
endend
alias_method_chain :method_missing,:states# state setter to write to database
define_method :state=do |value|
write_attribute(:state, value.to_s)end# state getter to read from database
define_method :state_with_active_recorddo(read_attribute(:state)||(self.state = state_without_active_record)).to_sym
end
alias_method_chain :state,:active_recordendendend
After the 2009 WWDC release, I decided to give Snow Leopard a try on my production machine. Crossing my fingers, expecting a plethora of broken gems and databases, I wiped my hard drive clean and installed the latest build.
Much to my surprise, most things worked flawlessly and exactly as it did on Leopard.
Quite possibly these default gems and versions will change between now and the final release of Snow Leopard. For instance, this seed comes with Rails 2.2.2, even though we are already at 2.3.2. Snow Leopard doesn’t come out till September and by then we could have an even newer version of Rails that might be bundled.
What doesn’t work, and how to fix it.
Textmate – Everything works fine except for the following shortcuts: ⌘←, ⌘→, ⌘⇧←, and ⌘⇧→. These shortcuts are for moving the text insertion point to beginning and end of line, and selecting to beginning and end of line, respectively. The fix is easy, simply download and double click the TextMate macros attached to this ticket
Nokogiri – Nokogiri installs fine but gives error “native.bundle: mach-o, but wrong architecture” when used. Getting around this is as easy as running sudo gem install nokogiri -s http://tenderlovemaking.com/ to get the latest development release which includes a fix for this.
do_sqlite3 – I haven’t personally used this or tried to fix it but I saw report of it not working by @benlovell
Passenger PrefPane – Preference pane does not load. No known fix (it’s probably an easy fix but I haven’t looked enough into it to try).