May 10 2009

I’m back

dastels @ 2:16 pm

As I’ve mentioned on Twitter & Facebook, I’m back to doing Ruby & Rails fulltime.

Joining Google took me out of the Rails community & largely out of the Ruby community. At least until very recently when I joined a Rails project (yes, at Google.. who’da thought).

As noted on my blog last spring, I had the rug pulled out from under me with a sudden onset of diabetes.

With all that I pretty much pulled an Austin Powers and went into cold storage for a year & a half.

Well, I’ve thawed out and am back at it… Ruby, Rails, and hanging with peeps at conferences. Look for me on speaker lists before too much longer.

After GoGaRuCo and RailsConf, I’m back, motivated, and enthused like never before.


Jan 09 2009

RSpec is a hit, who’d o’ thought?

dastels @ 7:14 pm

Well, RSpec is doing well. A couple things of note recently:


Sep 11 2007

Rails Rumble project reports

dastels @ 5:18 am

The stats for our project:

 

+----------------------+-------+-------+---------+---------+-----+-------+
| Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M |
+----------------------+-------+-------+---------+---------+-----+-------+
| Controllers          |    70 |    55 |       2 |       6 |   3 |     7 |
| Helpers              |     6 |     4 |       0 |       0 |   0 |     0 |
| Models               |   891 |   734 |      13 |     110 |   8 |     4 |
| Libraries            |     0 |     0 |       0 |       0 |   0 |     0 |
| Model specs          |  2283 |  1835 |       0 |       0 |   0 |     0 |
| View specs           |     0 |     0 |       0 |       0 |   0 |     0 |
| Controller specs     |     0 |     0 |       0 |       0 |   0 |     0 |
| Helper specs         |     0 |     0 |       0 |       0 |   0 |     0 |
+----------------------+-------+-------+---------+---------+-----+-------+
| Total                |  3250 |  2628 |      15 |     116 |   7 |    20 |
+----------------------+-------+-------+---------+---------+-----+-------+
  Code LOC: 793     Test LOC: 1835     Code to Test Ratio: 1:2.3

 

A few things to notice:

  • very “rails” light… small controller… very literally a controller.. all the action happens in the models,
  • all the specs are for model classes, the controller & view do very little.. although the controller could probably do with a few specs, and
  • there’s over twice as much code in the specs than in the working classes.

The spec run:

 

$rake spec
(in /Users/dastels/Projects/Ruby-Projects/merlin/trunk)
..........................................................................
..........................................................................
..........................................................................
........................................................
Finished in 62.891545 seconds
278 examples, 0 failures

 

and the coverage report:

SafariScreenSnapz001.png
Note that echo was under development and actually didn’t get finished in time. Also we ran out of time before getting to mindbender.

Sep 11 2007

A hell of a way to spend a weekend

dastels @ 3:11 am

Rails Rumble ‘07 is over.

It was a total good time.We didn’t get as much done on our app as we had hoped, but what we got done turned out as well as we could have hoped.I was on the IRC channel the whole time pretty much, which provided a nice sideline. The whole thing had a strong co-opatition feel. There was a great group of people involved.

A big THANK YOU to the sponsors, the organisers, the other teams, and mostly to my teammate, Nancy.

We ran into some interesting technical issues in the course of the 48 hours, which I’ll be writing about over the next few days.For those interested, or just with voyeristic tendancies (ain’t the web great), there’s a flickr pool, and I’ve posted some pics in my .mac gallery.


Sep 09 2007

Rumbling away

dastels @ 4:37 am

We’re nearing the half way point of the Rails Rumble.. 1 day, 2 hours, 24 minutes remaining as I write this. We’ve been taking some photos that I’ve been posting at my .Mac web gallery.


Sep 07 2007

Rails Rumble is this weekend

dastels @ 8:36 pm

We’re getting prepped for the Rails Rumble. Nancy & I have entered as a team. The kids have been told they’re on their own for the weekend. This is going to be a great bit of fun.


Aug 15 2007

Rails Rumble

dastels @ 7:05 am
railsrumble_black_160.png The 2007 48 hour Rails coding competition has been announced. Check it out. Now we just need a good application idea.

Mar 30 2007

RSpec Autotest now a Rails Plugin

dastels @ 3:30 am

RSpec Autotest now a Rails Plugin:

“Posted by Nick Sieger Wed, 15 Nov 2006 15:46:00 GMT

Inspired by a posting on the RSpec list and recent comments stating that my Auto RSpec hack wasn’t working, I’ve bitten the bullet and upgraded to RSpec 0.7.2, and made rspec_autotest a plugin in the process. So, here are the necessary incantations to auto-rspec your project.”

OK, so I’m a bit behind on RSpec developments. But this plugin makes a world of difference when using rspec.

While Nick mentions rspec 0.7.2 in the post, I’m using it with the latest (pre-trunk) 0.9.0 without any issues.

If you use rspec (with rails or not.. see rspec-autotest-for-standalone-projects) you should be using this plugin!


Oct 29 2006

Using TinyMCE with Rails/AJAX

dastels @ 3:56 pm

Our current project is basically a very structured (i.e. niche/focused/custom) content management system. There are a few places where we want to give the client the ability to edit some HTML page content. The client is tech-savvy, but not in the “I enjoy slinging HTML” way. Ergo, we needed WYSIWYG HTML editing capability. After some research we decided that TinyMCE was the way to go. We just had to make it work the way we wanted it to.

Here are my notes on getting TinyMCE working nicely in a Rails/AJAX environment.

Start by grabbing the rails plugin (and read the material) from here and install it as per the instructions.

Allowable options to uses_tiny_mce are documented here… there are lots of them

I figured that having followed the directions in the above, my work was over. In fact it was just beginning. The above will work fine if you have a page, with a textarea that you want to be WYSIWYG. Our requirements were a bit more involved. The textarea in question was in a partial that was rendered via a remote updater call (via a link_to_remote in a list on the page). The main issue here is that the textarea didn’t exist when the page was rendered… so TinyMCE had to be hooked up to it later… when it was injected into the DOM tree. Some digging through support forums and I found what I needed. This required a bit of java script in the partial… after the textarea:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>
  <b>Page Content:</b><br />
  <%= text_area :page, :content, :rows => 15, :cols => 150 %>
  <br /><br />
  <%= submit_tag "Update" %>
  <script type="text/javascript">
  //<![CDATA[
    tinyMCE.execCommand('mceAddControl', true, 'page_content');
  //]]>
  </script>
<%= end_form_tag %>

The next issue was getting the contents out of TinyMCE and accessible to the parameter construction for the remote call. After a bit of research I ended up with the following:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>

Normally the save is trigger by a page unload, I needed to force it to happen before the remote call happened. Putting the call to force (aka trigger) the save in the :before script of the form submission remote call worked great. So now I had a bigger problem. TinyMCE was getting hooked up to the textarea. If the user picked another page item from the list, the div would be refilled with a different rendering of the partial… with a different textarea node. The old textarea would be gone… out from under TinyMCE. I needed a way to reconnect to the new textarea. More digging turned up this example. It gave me the final bit of the puzzle. My final solution includes the following in application.js:

bTextareaWasTinyfied = false; //this should be global, could be stored in a cookie...

function setTextareaToTinyMCE(sEditorID) {
	var oEditor = document.getElementById(sEditorID);
	if(oEditor && !bTextareaWasTinyfied) {
		tinyMCE.execCommand('mceAddControl', true, sEditorID);
		bTextareaWasTinyfied = true;
	}
	return;
}

function unsetTextareaToTinyMCE(sEditorID) {
	var oEditor = document.getElementById(sEditorID);
	if(oEditor && bTextareaWasTinyfied) {
		tinyMCE.execCommand('mceRemoveControl', true, sEditorID);
		bTextareaWasTinyfied = false;
	}
	return;
}

These two functions are used to disconnect from an existing textarea and reconnect to the newly rendered one. In the list item that causes the rendering:

<%= link_to_remote "<span class=\"listTitle\">#{page.title}</span>",
                   {:update => "editPage",
                    :url => {:action => :get_page, :id => page},
                    :before => "Effect.Fade('editPage',
                                            {duration: 0.25,
                                             queue: 'end',
                                             afterFinish: function(effect) {
                                               unsetTextareaToTinyMCE('page_content')}})",
                    :complete => "Effect.Appear('editPage', {duration: 0.5, queue: 'end'})"},
                    :title => "Edit #{page.title}"  %>

To avoid visual weirdness the disconnect is delayed until the fade has completed. Once the new version of the partial has been loaded, it’s faded back in. The relavant bit of the partial is here:

<%= form_remote_tag :url => {:action => 'edit_page', :id => @page},
                    :before => "tinyMCE.triggerSave(true,true)" %>
  <b>Page Content:</b><br />
  <%= text_area :page, :content, :rows => 15, :cols => 150 %>
  <br /><br />
  <%= submit_tag "Update" %>
  <script type="text/javascript">
  //<![CDATA[
    setTextareaToTinyMCE('page_content');
  //]]>
  </script>
<%= end_form_tag %>

The last thing was to add a Done/Cancel button to the form:

<input type="button"
       value="Done"
       onclick="Effect.Fade('editPage',
                            {duration: 0.25,
                             queue: 'end',
                             afterFinish: function(effect) {
                               unsetTextareaToTinyMCE('page_content')
                             }})" />

Now I have a WYSIWYG textarea in a partial that’s rendered via a remote call.. and it all works smoothly and exactly as required.


Aug 30 2006

Role Based Authentication from Rails Recipes. Part 2

dastels @ 2:19 am

Once I had the user roles code in place, working, and cleaned up, I decided to extend it by allowing regular expressions in the rights instead of literal strings (for controller & action names). Whether I stick with this going forward, who knows… but it’s convenient for development. Instead of separate rights for each action on a controller I can specify .* as the action to have the right apply to all actions for a controller.

Recall that I ended up with the core of the rights checking code actually in the Right class:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    action == action_name && controller == controller_name
  end
end

 

My first step was to wrap Rights attributes in a Regexp and do a match with the requested controller/action names:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    get_action_regex.match(action_name) && get_controller_regex.match(controller_name)
  end

  def get_action_regex
    Regexp.new(action)
  end

  def get_controller_regex
    Regexp.new(controller)
  end
end

 

It might be a case of premature optimization, but the Regexps can easily be cached since they are nicely encapsulated:

class Right < ActiveRecord::Base
  has_and_belongs_to_many :roles

  def has_right_for?(action_name, controller_name)
    get_action_regex.match(action_name) && get_controller_regex.match(controller_name)
  end

  def get_action_regex
    @action_regex || (@action_regex = Regexp.new(action))
  end

  def get_controller_regex
    @controller_regex || (@controller_regex = Regexp.new(controller))
  end

end

 

Part of the reason I blogged this was as an example of how much easier and obvious an enhancement can be when the code is cleanly (and extremely) refactored. More importantly, the details of rights can be changed without anything outside of the Right class being aware of it. If this ability is not one of the core benefits of OO, what is?


Next Page »