debuggable

 
Contact Us
 
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27

Jac: Comment box name auto completer (jQuery plugin)

Posted on 15/9/08 by Felix Geisendörfer

Hey folks,

this is post #26 of my 30 day challenge.

For those not familiar with it: A while ago Tim had the wonderful idea of adding an IRC-like auto completion feature to the comment box of our blog. Whenever you start to type in the name of a previous commenter on our blog and then hit tab, his full name will magically appear.

Download & Docs: You can download & read about the jac plugin at the Debuggable Scraps repository as usual.

Usage is as simple as it gets. The code for powering the input box on our blog looks as simple as this:

$('#comment-box').jac({items: 'strong.author-name'});

This will auto-magically scrap all author name's from the DOM and offer them as auto completions when the tab key is hit.

Comments and ideas for improvement are welcome as always!

-- Felix Geisendörfer aka the_undefined

 

Relative urls in JavaScript

Posted on 14/9/08 by Felix Geisendörfer

Hey folks,

this is post #25 of my 30 day challenge.

One of the issues I always face when writing JavaScript is the relative path problem. Unless you specify an absolute path for lets say an ajax request, your urls will resolve relative to the current url.

This is a really annoying issue, especially since we are all used to CakePHP fixing it for us when using Router::url. So how could we create our own url() function in JavaSccript that will solve this problem for us?

Well the solution is simple. All we need to do is to store the information on the base url somewhere in the html. Since we are lucky, the html specification already knows an element for this called <base>.

So when we open up our app/views/layouts.ctp file, all we need to put into the <head> section is the following:

<base href="<?php echo Router::url('/'); ?>" />

Now we need a little JavaScript function we can use with this:

$.url = function(url) {
  return $('base').attr('href')+url.substr(1);
}

Now whenever we want to make an ajax call, we can simply do:

$('#foo').get($.url('/posts/index));

Of course another way of achieving the same result is to require your site to run within its own domain (virtual host). However, I like building apps that can also run from within a sub folder as it makes them more portable and its easier for other people to set the site up and get involved in the project.

Alright, looking forward to alternative approaches & feedback.

-- Felix Geisendörfer aka the_undefined

 

Recommended Reading

Posted on 13/9/08 by Felix Geisendörfer

Hey folks,

today I'd like to recommend some blogs and articles to you that I'm enjoying right now.

As heavily promoted by Nate Abele at the CakePHP workshop, everybody should be familiar with the Five Rules published by Paul M. Jones. You also should read up on the history of the user agent string but it might cause you nightmares.

Merlin Mann is also changing the theme of his blog, an inspiring sample is his making time to make series. Other then that I currently also enjoy reading Coding Horror, Nuts and Bolts of CakePHP and the github blog.

Happy Reading and stay tuned for my next posts - I'm working on something ; ).

-- Felix Geisendörfer aka the_undefined

 

XPath on PHP Arrays (Set::extract)

Posted on 12/9/08 by Felix Geisendörfer

Hey folks,

this has been something I wanted to write about for quite a while. Back when I was writing the post on the original Set::extract method by nate the idea of doing one supporting XPath came up.

One of the requirements was that the new method would need to be faster or at least as fast as the old implementation. My first attempts were big failures. Not only did the solutions I came up with contain tons of bugs. No, they were are also a lot slower the old extract function.

A few benchmarks later and I discovered the biggest bottleneck in my implementation: Recursiveness.

If you need a function to have the highest performance, try to express it non-recursively. It can make a 500% difference. So that is what I did. After lots of trial and error I was able to find an algorithm that would resolve XPath expressions without the use of recursion. The only exception is traversal via the '..' token which has memory / simplicity reasons.

If you are curious feel free to check out the XPath implementation in the CakePHP core.

Anyway, if you wonder what this whole thing can do for you, I recommend checking out the doc block:

Currently implemented selectors:

/User/id (similar to the classic {n}.User.id)
/User[2]/name (selects the name of the second User)
/User[id>2] (selects all Users with an id > 2)
/User[id>2][<5] (selects all Users with an id > 2 but < 5)
/Post/Comment[author_name=john]/../name (Selects the name of all Posts that have at least one Comment written by john)
/Posts[name] (Selects all Posts that have a 'name' key)
/Comment/.[1] (Selects the contents of the first comment)
/Comment/.[:last] (Selects the last comment)
/Comment/.[:first] (Selects the first comment)
/Comment[text=/cakephp/i] (Selects the all comments that have a text matching the regex /cakephp/i)
/Comment/@* (Selects the all key names of all comments)

Usage is as simple as:

$users = $this->User->find('all', array('contain' => 'Comment'));
$bakers = Set::extract('/User/Comment[text=/cakephp/i]/..', $users);

While the implementation does not support full XPath (and probably won't in future), feel free to make suggestions on additional selectors or the idea in general.

-- Felix Geisendörfer aka the_undefined

 

Why UUIDs?

Posted on 11/9/08 by Felix Geisendörfer

Why UUIDs?

what are UUIDs? Well according to the Wikipedia:

A Universally Unique Identifier (UUID) is an identifier standard used in software construction, standardized by the Open Software Foundation (OSF) as part of the Distributed Computing Environment (DCE).

In English that would roughly translate to really long random strings. So random in fact that Wikipedia thinks:

After generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%

So why should you care and maybe even use those UUIDs? I mean there are certainly reasons against using them. Ever tried to memorize a bunch of UUIDs? Give it a shot:

48c907b0-b8ac-4161-84c9-4fbf1030b5da
48c907b0-dc38-475c-a9c4-4a2e1030b5da
48c907b0-f088-44ae-8be5-4e811030b5da

When it comes to primary keys you might miss the ease with which one can remember auto incrementing values. But hang on, with a bit of copy & paste one can get over this inconvenience and carry those values around.

But why should you go through that trouble? The answer can largely be found in their uniqueness. With UUIDs, you can give an identifier to any object in the real world. This id you give it is guaranteed to not have been used for labeling any other object in the universe so far. Guaranteed in this context means you are more likely to win the lottery without buying lottery tickets than generating a duplicate UUID.

This is an amazing property for several reasons. Imagine a fairly real world task of having to join the blog posts of two previously separate sites into a single new one. Back when Tim and I did that for this blog we had to re-index all our blog post ids as well as all foreign keys pointing to them. Why? Because we both had given out the same auto incrementing ids to different blog posts. If we (wordpress) had used UUIDs, merging our two blogs (or any other sets of data) would have been magnitudes easier.

And there is more. If you want to create polymorphic associates than UUIDs are going to make that a lot easier for you in CakePHP. Just create a table called 'comments' and give it a belongsTo of [Photo, Post, User]. But instead of creating a foreign key field for each model, you get away with just creating a single foreign_id field and setting that up as the foreign key for all the belongsTo associations. Since the UUID the foreign_id points to is unique across tables, you don't even have to track what model / table it actually belongs to. This avoids a more complex query and leads to improved performance for the setup. (You might still want to populate Comment.model just so you know where the link goes to without doing the actual lookup).

Last but not least there is another advantage hidden in the randomness of those ids. By not having your ids follow any pattern, an attacker won't be able to iterate through your databases records without you giving him a map of primary ids for it. This in itself doesn't automatically make your application secure, but it lessens the damage that is likely to be done if a permission bug is exploited.

Anyway, I'm sure I forgot a bunch of reasons and I am also looking forward to people sharing their concerns on performance and the concept itself. In the meantime just know that CakePHP will automatically generate UUID keys if your primary key is a char(36) field.

HTH,
-- Felix Geisendörfer aka the_undefined

 
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27