Thursday, May 29, 2008

The blog is moving...

I'm moving the blog to rubyblocks.se. Please update your bookmarks and subscriptions.

Thursday, May 22, 2008

make_resourceful and odd controller names

I've been debugging make_resourceful to try to figure out why it fails to generate an index action for a controller named NewsController. After a couple of hours I found the now slightly obvious reason in lib/resourceful/default/accessors.rb...

The singular? method returns true for "News".

A simple solution would be to define singular? in your controller and let it return false.

Example:

class NewsController < ApplicationController
def singular?; false end

make_resourceful do
actions :all
end
end


See also: More on odd controller names

Tuesday, May 20, 2008

response.should have_tag problems

I use "integrate_views" to combine controller and view specs. The thing I discovered just now is that if you have nested describes, you have to place "integrate_views" inside the inner describe or "have_tag" won't work.

The error you typically get otherwise (even when the element exists) is:
Expected at least 1 element matching "div#content", found 0.

For this particular project I'm using RSpec 1.1.3.

Monday, March 31, 2008

In Place Editor using Scriptaculous and Prototype in Rails 2.0

I've been using the scriptaculous InPlaceEditor and thought I would share some useful snippets.

The code is setup to save on blur and being able to handle empty fields.

The creation script:

var inplace_editor_edit_hint = 'Click to edit...';

function createInplaceEditor(field, update_path, highlightcolor,
highlightendcolor, width)
{
fillIfEmpty($(field));

new Ajax.InPlaceEditor(field, update_path, {
highlightcolor: highlightcolor,
highlightendcolor: highlightendcolor,
okButton: false,
cancelLink: false,
submitOnBlur: true,
cols: width,
callback: function(form) {
input_field = form.elements[0];

// This is to ensure we don't save the edit hint if
// the user accidentally clicked an empty field
if(input_field.value == inplace_editor_edit_hint)
input_field.value = '';

return Form.serialize(form);
},
onComplete: function(transport, element)
{
fillIfEmpty(element);

if(transport.statusText != "Internal Server Error")
onEditorSuccess(); // cb

new Effect.Highlight(element, {
startcolor: this.options.highlightcolor,
endcolor: this.options.highlightendcolor
});
},
onFailure: function(element, transport) {
onEditorFailure(transport.responseText); // cb
}
});
}

function fillIfEmpty(element)
{
if(element.innerHTML == '')
element.innerHTML = inplace_editor_edit_hint;
}


In the view I have a bit of script that binds the callbacks for success and failure.

The validation errors is displayed in the error notice, this isn't exactly ideal, but works as an example of how to handle validation.


function onEditorSuccess()
{
$('error').innerHTML = '';
$('notice').innerHTML = 'Model was successfully updated.';
}

function onEditorFailure(response)
{
response = response.evalJSON();

var lines = new Array();

for(var i = 0; i < response.length; i++)
lines.push(response[i][0] + ' ' + response[i][1]);

$('notice').innerHTML = '';
$('error').innerHTML = 'Error: ' + lines.join('. ')
}


The controller code looks something like this:

def update_field
model = Model.find(params[:id])
if model.update_attributes(field_to_update => params[:value])
render :text => params[:value]
else
render :text => model.errors.to_json, :status => 500
end
end

private

def field_to_update
params[:editorId].split('_')[1]
end


And finally I create them using something like this:


<p id="prefix_title"><%= model.title %></p>
<script type="text/javascript">
createInplaceEditor("prefix_title", '/path/to/action',
"#FFFFFF", "#AAAAAA", 10);
</script>


Though I recommend wrapping it in a helper to keep it nice and DRY...

Tuesday, February 5, 2008

HABTM issue with Rails 2.0.2 and SQLite3

When using SQLite3 with rails you must make sure not to add an id column to your join tables (probably a good idea in any case).

The error I got when I did have an id column where something like this:

SQL logic error or missing database: INSERT INTO
podcasts_tags("podcast_id", "id", "tag_id") VALUES (3, 3, 1)


To avoid this, make sure you include :id => false when creating the join table:

create_table :podcast_tags, :id => false do |t|
t.integer :podcast_id, :null => false
t.integer :tag_id, :null => false
end

Monday, January 28, 2008

NCover in a relative path

Just a small note for anyone trying to get NCover to run in a relative path.

Make sure you include CoverLib.dll and register it (run Regsvr32 CoverLib.dll).

I had errors where it would run on one computer but not on another and that when it couldn't find the dll it's simply froze after the unit tests had run. I'm using v1.5.8.