The latest Application Compatibility Toolkit (ACT) release, ACT 5.0.5428.1080 is publicly available and can be downloaded here.
To give you some background, ACT helps customers understand their application compatibility situation by helping identify which applications are compatible with Vista, IE7, and IE8 and which require further testing. ACT allows compatibility data to be uploaded from individual machines to a central location for analysis, grouping and reporting. Once an issue has been identified, help will be available on how to resolve a particular issue or create a workaround. Furthermore, partners and customers using ACT are able to post comments to the Online Application Community, where they can share data and information about application compatibility testing.
The IE components of ACT are:
Overall, these tools help customers lower their costs for application compatibility testing, prioritize their applications, and deploy Internet Explorer more quickly.
The work flow for identifying application compatibility issues before rolling out a new version of IE8 is shown below:

New Application Compatibility Events added in IE8
We added logging for twelve new Application Compatibility Events in IE8, as shown in the table below. Including the IE7 events, we now currently log 31 compatibility events. The Internet Explorer Compatibility article contains more information on these events.
| New IE8 Event Name | Event ID |
| Cross-Site Scripting Filter | 1046 |
| Intranet at Medium Integrity Level | 1047 |
| DEP/NX Crash Recovery | 1048 |
| Standards Mode | 1049 |
| File Name Restriction | 1056 |
| Codepage Sniffing | 1058 |
| AJAX Navigation | 1059 |
| Application Protocol | 1061 |
| Windows Reuse Navigation Restriction | 1062 |
| MIME Sniffing Restrictions - no IMAGE elevation to HTML | 1064 |
| Web Proxy Error Handling Changes | 1065 |
| Certificate Filtering | 1073 |
Internet Explorer Application Compatibility article
In the past, we noticed that the ACT tool helped identify the compatibility issues that occur in a line of business application or website, however, the tool itself did not provide any guidance for remediation. In IE8, we are providing a resource that gives exactly that information. The article is linked directly in the IECTT logged message or is directly available here. The article covers the following topics for all IE7 and IE8 compatibility events:
We will be adding additional examples and remediation to this article before the final IE8 release.
As you can see, we refined our Application Compatibility logging in IE8 and have provided a useful resource in the IE Application Compatibility article. We look forward to you trying it out and giving us feedback in the IE newsgroups.
Jatinder Mann
Program Manager
Rails?? routing mechanism is pretty slick. In a very intuitive way you??re able to describe the resources you want exposed at the URL level with this routing-DSL:
| 1 2 3 4 5 | map.resources :users do |user| user.resources :articles do |article| article.resources :comments end end |
However, while this configuration makes an article available at /users/1/articles/1 and comments at /users/1/articles/1/comments/1 there are often times when you want to bypass the full nested hierarchy and directly access the resource in question. Now, with the shallow route option, you can.
| 1 2 3 4 5 | map.resources :users, :shallow => true do |user| user.resources :articles do |article| article.resources :comments end end |
This configuration removes all nested member paths (like /articles/1/comments/1) and makes them directly accessible (as /comments/1). Basically, routes are built only with the minimal amount of information that??s needed to uniquely identify the resource.
| 1 2 3 4 | user_articles_path(1) #=> '/users/1/articles' article_path(2) #=> '/articles/2' article_comments_path(3) #=> '/articles/3/comments' comment_path(4) #=> '/comments/4' |
No longer do you need to wrestle with infinitely nested routes, the :shallow option automatically makes all routes as concise as possible.
tags: ruby, rubyonrails
Rails?? routing mechanism is pretty slick. In a very intuitive way you??re able to describe the resources you want exposed at the URL level with this routing-DSL:
| 1 2 3 4 5 | map.resources :users do |user| user.resources :articles do |article| article.resources :comments end end |
However, while this configuration makes an article available at /users/1/articles/1 and comments at /users/1/articles/1/comments/1 there are often times when you want to bypass the full nested hierarchy and directly access the resource in question. Now, with the shallow route option, you can.
| 1 2 3 4 5 | map.resources :users, :shallow => true do |user| user.resources :articles do |article| article.resources :comments end end |
This configuration removes all nested member paths (like /articles/1/comments/1) and makes them directly accessible (as /comments/1). Basically, routes are built only with the minimal amount of information that??s needed to uniquely identify the resource.
| 1 2 3 4 | user_articles_path(1) #=> '/users/1/articles' article_path(2) #=> '/articles/2' article_comments_path(3) #=> '/articles/3/comments' comment_path(4) #=> '/comments/4' |
No longer do you need to wrestle with infinitely nested routes, the :shallow option automatically makes all routes as concise as possible.
tags: ruby, rubyonrails
There are some fantastic gems and plugins out there for handling images in Rails apps, such as Paperclip, Attachment-fu, etc., that on the whole are well-written and do a pretty good job.
However, something has always narked me when using them.
In general, to add a preview_image to, say, your Album model, you do something like this:
class Album some_macro_method :preview_image, :thumbnails => { :listing => "300x200", :thumb => "100x100!", :small => "50x50#" } endThen in the view that shows the image, you can use something like this:
<%= album.preview_image.url(:listing) %> ... <%= album.preview_image.url(:thumb) %> ...etc.This is all very well, provided you know the exact sizes of the thumbnails that you will need at the very beginning.
Unfortunately, more often than not, this is not the case, and we find ourselves running some 'reprocess' task every time a new thumbnail size is added, or one is changed.
Furthermore, we might not always want to use all of those thumbnails. If we use these models in a script which makes no use of the images, or in our tests, then having to process thumbnails every time we create a model is expensive and unnecessary!
Taking these things into account, it seems clear to me that the fundamental problem is that the thumbnail specifications are in the wrong place!
Images, and what size they should be, are visual concerns, so surely the correct place for specifying thumbnails is in the view.
The SolutionWhat we really want is to have our model looking like this:
class Album some_macro_method :preview_image endand our view looking like this:
<%= album.preview_image.url("300x200") %> ... <%= album.preview_image.url("100x100!") %> ...etc.The way to achieve this will be to generate thumbnails on-the-fly - this will both remove the need to reprocess thumbnails when there are changes, and minimize the creation of unused thumbnails.
NB If you're concerned about performance at this point, this is easy to optimise using HTTP caching - we'll mention that later - what's important for now is that the thumbnails are specified in the correct place.
DragonflyAlthough I'd been thinking about this problem for a long time, it's taken a while to get round to actually creating a ruby gem for doing it!
So at last, I'm very pleased to introduce Dragonfly, a Rack-based ruby gem for processing/encoding on the fly.
There are already one or two gems which deal with on-the-fly processing (see below), and while these are good for their specific tasks, I wanted one which was generic enough as to allow the use of different processing libraries, different data stores, etc.
From the start it has been designed to be as modular and extendable as possible, making it highly configurable, but falling back to sensible defaults for those who just want to do easy thumbnailing without delving into configuration details.
In particular, it was designed with the following in mind:
Given the above points regarding not being tied to Rails/ActiveRecord, it's been designed primarily as a Rack application, but with an optional extension module for using with ActiveRecord.
Using with Rails is simply a matter of using it as a Rails Middleware, and configuring appropriately (which is done for you if you use the supplied generator or helper Rails configuration file).
Basic usage as a Rack applicationBasic usage of a dragonfly app involves storing data (e.g. images), then serving that data, either in its original form, processed, encoded or both.
We set up the dragonfly app and run it (e.g. in our rackup file config.ru):
require 'rubygems' require 'dragonfly' app = Dragonfly::App[:my_app_name] app.configure_with(Dragonfly::RMagickConfiguration) app.configure do |c| # any other configuration here end run app(If you are unfamiliar with how to run Rack apps with config.ru, then see e.g. this tutorial).
Elsewhere in our code, we store some content:
# Store uid = app.store(File.new('path/to/image.png')) # ===> returns a unique uid for that image, "2009/11/29/145804_file"We can get the url for a processed and encoded version of this content:
url = app.url_for(uid, '30x30', :gif) # ===> "/2009/11/29/145804_file.gif?m=resize&o[geometry]=30x30&s=aa78e877113f6bc9"Now when we visit the url /2009/11/29/145804_file.gif?m=resize&o[geometry]=30x30&s=aa78e877113f6bc9 in the browser (given the app is running of course), we get the resized image!
NOTE: the GET parameter s=aa78e877113f6bc9 is for protecting from DOS attacks. You can turn this off if you wish - see the documentation.
Using in RailsAs mentioned earlier, the ActiveRecord/Rails part of the code is a layer which sits on top of the main app.
In fact, the main task of the ActiveRecord extension is storing the content uid mentioned above.
Let's say we want to add a 'cover image' attribute to our Album model.
Then in environment.rb:
config.gem 'rmagick', :lib => 'RMagick' config.gem 'rack-cache', :lib => 'rack/cache' config.gem 'dragonfly', :lib => 'dragonfly/rails/images', :source => 'http://gemcutter.org'The file 'dragonfly/rails/images' creates a Dragonfly App and configures it for use with Rails, then inserts it into the Rails middleware stack (see the docs for more info). Note that we're using RMagick for image processing/encoding, and Rack::Cache to cache requests.
Migration:
add_column :albums, :cover_image_uid, :stringModel:
class Album < ActiveRecord::Base image_accessor :cover_image # Defines reader/writer for cover_image endView (for uploading via a file field):
<% form_for @album, :html => {:multipart => true} do |f| %> ... <%= f.file_field :cover_image %> ... <% end %>View (to display):
<%= image_tag @album.cover_image.url(:gif) %> <%= image_tag @album.cover_image.url('400x200') %> <%= image_tag @album.cover_image.url('100x100!', :png) %> <%= image_tag @album.cover_image.url('100x100#') %> <%= image_tag @album.cover_image.url('50x50+30+30sw', :tiff) %> <%= image_tag @album.cover_image.url(:rotate, 15) %> ...etc.As you can see from the migration, the model's main concern is storing the uid for the content. The method album.cover_image.url(...) is a wrapper around the Dragonfly app's url_for(uid, ...) method mentioned earlier, using the stored cover image uid.
Extra nicetiesThe ActiveRecord extension module actually has a number of useful helper methods, which should make it extremely easy and intuitive to use, as if the image is like any other model attribute.
See the docs for using with ActiveRecord for more details, but for now, here are some examples of some of the things you can do.
Assignment:
album = Album.new album.cover_image = "\377???JFIF\000\..." # can assign as a string... album.cover_image = File.new('path/to/my_image.png') # ... or as a file... album.cover_image = some_tempfile # ... or as a tempfile album.cover_image # => #<Dragonfly::ActiveRecordExtensions::Attachment:0x103ef6128... album.cover_image = nil album.cover_image # => nilInspection and processing:
album.cover_image.width # => 280 album.cover_image.mime_type # => 'image/png' album.cover_image.transform!('30x30#nw', :gif) # (operates on self) album.cover_image.width # => 30 album.cover_image.mime_type # => 'image/gif'Write to a file:
album.cover_image.to_file('out.png')URLs:
album.cover_image.url(:png) # => '/media/2009/12/05/170406_file.png' album.cover_image.url('300x200#nw', :gif) # => '/media/2009/12/05/170406_file.gif?m=resize_and_crop&o[height]=...'Generating (for tests/populate tasks):
album.cover_image = Dragonfly::App[:images].generate(300, 200)(the above line of code assumes the Dragonfly app is called :images).
There are a number of validations you can use too:
class Album validates_presence_of :cover_image validates_size_of :cover_image, :maximum => 500.kilobytes validates_mime_type_of :cover_image, :in => %w(image/jpeg image/png image/gif) validates_property :width, :of => :cover_image, :in => (0..400) image_accessor :cover_image end Per-blog-post thumbnailsNow that we're generating thumbnails on the fly, we can wave 'bye-bye' to reprocess tasks every time we change the sizes of our thumbnails, and smugly shout 'so long suckers' to tests bogged down by unnecessary image resizing.
However, it becomes apparent that now that our thumbnail definitions are in the correct place, other things become easier.
One example is this blog!!
We have a number of users who want to create blog posts with images sized on a per-blog-post basis.
Previously this would have been difficult, because we'd have had to specify the sizes up front, e.g.
class BlogPost some_macro_method :image, :thumbnails => { :small => "100x100!", # ...etc. } endAlternatively the user could resize the image themselves before uploading, and then use the original, but this is tedious.
Now we are generating thumbnails on the fly, this is trivial. There are a number of ways we could achieve this, but this blog uses something along the lines of the following (actually it has multiple images, but for simplicity, let's assume there is one image per blog post):
First, we add an image attribute to the blog post model
Migration:
add_column :blog_posts, :image_uid, :stringModel:
class BlogPost < ActiveRecord::Base image_accessor :image endThen we allow the user to add tags like img[300x200!] to the blog post.
Before rendering, substitute all instances of e.g. img[300x200!] with <img src="#{blog_post.image.url('300x200!')}" />
Here are some examples for this post!!
| 150x150 | ![]() |
| 150x150! | ![]() |
| 150x150# | ![]() |
| 100x100+250+150nw | ![]() |
(image taken from here)
Flexible ConfigurationDragonfly can be configured in various ways to suit various use cases.
To see some examples, such as using with Heroku and S3, and text image replacement, see the docs.
Other approachesOther on-the-fly processing libraries of note include Fleximage and Rack::Thumb (sorry if I've overlooked any other obvious ones!).
These are very good at what they do, but don't quite encompass all the aspects I listed above (among other things, Fleximage is tied to Rails and ActiveRecord, while Rack::Thumb is a lightweight Rack middleware that deals only with image resizing/cropping), which is why I felt the need to build Dragonfly.
Getting itThe gem is hosted on gemcutter, installed in the usual way
sudo gem install dragonflyThe code is here on github.
Documentation is here.
Feel free to fork away, contribute, suggest improvements etc.
Enjoy!
The Silverlight Toolkit is innovative in many ways, not least of which is that controls are released in one of four quality bands:
The control I??ll be considering today was developed (and described here) by Ruurd Boeke and is currently in the Experimental band. You can expect that the API will change quite a bit, but that said, it is an enormously useful control right now; and thus I??ve submitted a video and this write-up.
What??s It For?The goal of the Transitioning Content control is to make it easy to add animation when you are changing content within a control as demonstrated here. [You??ll need to click on DomainUpDown on the left (and surprisingly, not on TransitioningContent!) and Animations on top. The following cropped image illustrates where to click, but provides only a shadow of the impact
To make this crystal clear, and to show how easy it really is to use this control, we??ll build the example three times: first with a Content Control, then with a Transitioning Content Control, and finally, adding data binding and the ability to transition more complex objects.
Starting SimpleVersion 0 begins with a grid with two columns. The left column contains a ContentControl and the right a button. Here is the complete Xaml:
<UserControl x:Class="tccDemo.MainPage"The job of the ContentControl is to hold a single piece of content: in this case a string. The button??s job is to cause that content to change, which we do programmatically in the button??s click event handler in MasterPage.xaml.cs, shown in full:
using System;Each time the button is clicked, a new value is displayed.
[ Demo here ?? visible only if you are running Silverlight 3 ]
Changing from Content to TransitioningContentThe TransitioningContent control is, essentially, a skinnable custom control that derives from content control.
For more on Skinnable Custom Controls, see the blog series that starts here, or consider these videos (click on the image to go to the video):
![]() |
![]() |
![]() |
![]() |
Before we dive into the TransitioiningContent control and how it does its work, let??s look at how to use it. We start by replacing the ContentControl with a TransitioningContentControl, but to do this we need to add a reference to System.Windows.Controls.Layout.Toolkit in the references and a namespace to the top of the Xaml file
xmlns:layout="clr-namespace:System.Windows.Controls;With that in place we can modify MainPage.xaml to replace the ContentControl with the TransitioningContentControl and replace the Change button with two buttons: one for Up and one for down. Here is the complete Xaml:
<UserControl x:Class="tccDemo.MainPage"The code is modified only to set the Transition property of the TransitioningContentControl. Here is the complete code behind file:
using System;Here is the effect:
Adding DataBinding and ObjectsIn both of the examples so far, the content has been a simple string. It is possible, however, to provide a more complex object, by modifying the TransitioningContentControl and using an explicit ContentTemplate.
<layout:TransitioningContentControlThis follows all the normal conventions of using a ContentTemplate. We fill it with a DataTemplate which holds a StackPanel, allowing us to place two TextBlocks, both of which use binding syntax to indicate that they are going to bind to the Title and Author properties of whatever object they are given, respectively.
The rest of the Xaml file is unchanged.
We need a data object, and so we create as simple a data object as possible to illustrate this idea; noting that of course you can get your data from a database, from an XML file, etc. Here is the complete contents of Book.cs including the static property we??ll use to obtain some pre-created data,
using System.Collections.Generic;
MainPage.xaml.cs is modified somewhat more significantly, to hold a membervariable of type List<Book> (thus avoiding having to ??get? the data repeatedly) and a counter as a convenience so that we can cycle through our somewhat meager collection. Here is the complete MainPage.xaml.cs
using System.Collections.Generic;The constructor sets the initial visual state to Normal and sets the content of the TransitioningContentControl to the first book in the collection. It then sets up the two event handlers. The job of each is to set the Transition state and then call the helper method that gets the next book in the collection. Here it is in action:
Visual State AmbivalenceThe TransitioningContent is a bit ambivalent about its visual states. There are four states that are hardwired into the control as it is currently written:
However, if you examine the attributes at the top of the class (used to signal, for example, both the Visual State Manager and tools like Blend what visual states the class supports) you??ll find this:
[TemplateVisualState(GroupName = PresentationGroup,There are precisely two visual states made visible to Blend and the VSM. The net effect is that you can certainly use the UpTransition and DownTransition, but they were added as examples of how you can freely extend this class with any transitions you like.
Here??s how it works. The TransitioningContentControl consists of two parts both of type ContentControl: PreviousContentPresentationSitePartName and CurrentContentPresentationSitePartName.
To add an animated transition from content A to content B you need only hand the two to this control and tell it, by passing in a string, what storyboard to invoke. If you pass in the string TransitionUp or TransitionDown then it already knows what storyboard to invoke, as Ruurd Boeke wrote those and put them in the Resources section of TransitioningContentControl.xaml. Here, for example, is his UpTransition:
<vsm:VisualState x:Name="UpTransition">The effect of this is to target first the opacity of the current content, which will go from 0 to 1 over 3/10 of a second. During that same time period it will move up the Y axis from 30 to 0 (remember that the Y axis counts up as it moves down the screen). In the second half of the animation the targetproperty is the opacity of the previous content which fades away from 1 to 0 over that same 3/10 of a second, while the content itself moves up from 0 to ??30.
Notice that the storyboard is within the VisualState whose name is UpTransition.
The class itself has a public property named Transition:
/// <summary>This acts as a front for the Dependency Property which is registered immediately below
public static readonly DependencyProperty TransitionProperty =A quick review of the Silverlight documentation reveals the meaning of each of the four parameters:
Notice that the type of the TransitionProperty is string, and parenthetically, notice that the final parameter, typeMetadata, is explicitly noted for usage with a PropertyChangedCallback, which is what is done here.
OnTransitionPropertyChanged is overloaded in the implementation, but the net effect is to set the source of the content control and to set the string representing the new transition and then to call ChangeTransition whose job is to make sure it is safe to set a new transition, and then to obtain the PresentationState Visual State group and then to look to see if there is a state for the string passed in. If so, that transition is set as the new value for the transition.
Thus, with this somewhat unusual control, you can modify the visual states within the PresentationGroup) without subclassing, and by doing so (and providing a storyboard) you can add any transition you like, which you can then invoke by passing in its name!
Caveat! As noted earlier, this control is in the experimental band, and this API is very likely to change.
I hope you found this bit of control spelunking as interesting as I did sorting it out; and it is just fine to set all of the details aside and just use the control in conjunction with other controls to create animated transitions without over-worrying about how it is doing its magic.
Cucumber is a great tool that lets you create something akin to a personalized programming language for testing. If you haven’t heard of it yet, refer to previous posts on basic and advanced cucumber. While I love what Cucumber lets you do, up until now a lack of modularity within step definitions has been the elephant in the room. Dave Astels and I were lucky enough to stumble upon a neat solution to this while pairing recently, so let’s take a more specific look at the problem and solution. Note that at the time of writing the feature is only available in the trunk Git version of Cucumber, but expect a release soon.
Problem: Step Definition Arguments Captured as StringsAs you write step definitions that capture variable data in the provided regex, you’ll remain happy if the target data is naturally represented as a string. The following example uses DataMapper as its ORM and dm-sweatshop (found in dm-more) for fixture factories:
# step definition file Given /^a new user with username (.+)$/ do |username| @user = User.make(:username => username) end Then /^the user is valid$/ do @user.should be_valid end # feature file Scenario: valid username Given a new user with username larrytheliquid Then the user is validHowever, there are many occasions where the natural data-type for a captured argument may be something other than a string:
# step definition file Given /^a new user with age (\d+)$/ do |age_string| @user = User.make(:age => age_string.to_i) end Then /^the user is valid$/ do @user.should be_valid end # feature file Scenario: valid age Given a new user with age 22 Then the user is validThe key thing to notice is that it was necessary to convert age_string to an integer because the concept of age is naturally represented here as an integer. While the conversion does not look like much work now, the actual problem lies in modularity. If we would like to refer to age in any subsequent step definitions, we must duplicate the code to coerce the string everywhere… certainly not DRY.
The code we’ve seen so far is able to get away with going from captured argument string, to the argument with its natural data-type, to an ORM instance representation, without too much pain. This is possible because the structure of the scenarios being written is fairly simple and setup can be performed in a Given that creates an instance variable to be used in a Then. However, there are more complex scenarios where this pattern is not possible.
# step definition file Given /^a customer user named (\w+)$/ do |username| User.gen(:customer, :username => username) end Given /^a support user named (\w+)$/ do |username| User.gen(:support, :username => username) end When /^user (\w+) is assigned user (\w+)$/ do |support_username, customer_username| support_user = User.first(:username => support_username) customer_user = User.first(:username => customer_username) support_user.assign(customer_user) end Then /^user (\w+) should be in user (\w+)'s work queue$/ do |customer_username, support_username| support_user = User.first(:username => support_username) customer_user = User.first(:username => customer_username) support_user.work_queue.should include(customer_user) end # feature file Scenario: support assigned a customer Given a support user named stoltini And a customer user named larrytheliquid When user stoltini is assigned user larrytheliquid Then user larrytheliquid should be in user stoltini's work queueThe example above needs to reference specific users in both a When and a Then, and cannot rely upon a single instance variable that sets up state in a Given. The unfortunate result is some pretty nasty duplication of the ORM finder code to lookup each user by their respective usernames in the database.
Solution: Step Argument TransformsThe historical problem with Cucumber has always been that it was restricted to yielding strings as step definition arguments, but this is no longer the case. With a new Transform method, we are able to register regular expressions with Cucumber that it will check against arguments before they are yielded to step definitions. In addition to a regex, Transform expects a block that will be passed the raw argument, and whose return value will be used in place of it.
First, lets revisit our original modularity problem in the age example:
# support file Transform /^age \d+$/ do |step_arg| /(\d+)$/.match(step_arg)[0].to_i end # step definition file Given /^a new user with (age \d+)$/ do |age| @user = User.make(:age => age) end Then /^the user is valid$/ do @user.should be_valid endIf you look at the Given, you’ll see that we expanded the capture group to include “age” as valuable contextual information. With step argument transforms, such contextual information is important to avoid overly general transforms that affect every argument.
The first argument to Transform uses a regex that anchors the beginning and end. This means that we will only match that specific entire string, rather than accidentally matching other step arguments that happen to contain a partial piece of our regex (of course, you could have more general versions if you wanted to, just tread carefully).
If a registered transform matches an argument of a step definition, that argument will be passed to the block supplied with the transform definition. In the Transform example above, we anchor at the end and just capture the digit, because we already know the structure of our input based on the initial match.
After pulling the information we want out of the match group, we apply our transform, to_i, which is yielded to the Given as the variable age. Note that we chose the name age in our new Given instead of age_string because we are expecting the transform to be applied. Most importantly, any other step definition that captures a group of the form (age \d+) will happily transform age into its natural type, keeping our code nice and DRY. Let’s see how step argument transforms change our previous more complex scenario.
# support file Transform /^user \w+$/ do |step_arg| User.first :username => /(\w+)$/.match(step_arg)[0] end # step definition file Given /^a customer user named (\w+)$/ do |username| User.gen(:customer, :username => username) end Given /^a support user named (\w+)$/ do |username| User.gen(:support, :username => username) end When /^(user \w+) is assigned (user \w+)$/ do |support_user, customer_user| support_user.assign(customer_user) end Then /^(user \w+) should be in (user \w+)'s work queue$/ do |customer_user, support_user| support_user.work_queue.should include(customer_user) endHere we use a similar strategy to capture groups of the form (user \w+). The transform applied looks up the user by their username and returns a DataMapper instance. The neat thing is that we can reuse our capture group across multiple different step definitions (the When and the Then), and the more involved duplicated boilerplate code gets packed away in the call to Transform.
Tips and TricksScenario outlines and example tables are really cool features of Cucumber that let you specify a lot of different permutations of data in a compact way. However, the feature is also somewhat limited, because it can only yield string data. With step argument transforms, you’ll find yourself using the awesome tables more because duplicated transform code is removed so there is less friction to write additional step definitions.
# feature file Scenario Outline: username validity Given a new user with age <age> Then the user is <validity> Scenarios: valid | age | validity | | 18 | valid | | 21 | valid | | 49 | valid | | 120 | valid | Scenarios: invalid | age | validity| | 0 | invalid | | 1 | invalid | | 12 | invalid | | 17 | invalid | #... plus different steps using ageSometimes it may be more convenient to pass a string version of a regex to Transform, so this is supported. Below is an example where the goal is to test properties of a Unix system. Any capture groups that contain path followed by a Unix path are desired to be expanded into their absolute system filepath. The UNIX_PATH_CAPTURE pattern is designed to be regex-interpolated into other regex capture groups, so it is defined as a string to prevent unintentional use as a standalone regex.
# support file UNIX_PATH_CAPTURE = 'path (?:\w+|\/|\.|-|~)+' Transform UNIX_PATH_CAPTURE do |step_arg| File.expand_path /^path (.*)/.match(step_arg)[0] endTo avoid overly confusing dependencies, a step argument may only be transformed once. The Transform defined last gets matching order precedence over previously defined transforms, giving you the ability to “override” previous transforms. As a rule of thumb, define general transforms first and get more specific last. More importantly, appropriately including contextual data in capture groups prevents potentially unexpected transforms.
ConclusionCucumber has been a fantastic and innovative tool thus far. With step argument transforms, another bit of frustration is removed and your step definitions stay DRY.
As a final note, I’d like to point out how awesome it was to hack out the first version of this with Dave Astels while pairing, test-driven, and in less than an hour… given his BDD/RSpec/Cucumber background =) As mentioned before, we were pairing and ran into a problem that unearthed this feature. Before we knew it the console flashed from red to green.
Happy hacking!
Note: Due to browser security limitations related to cross-site scripting. This solution works only for iframe page content called from the same domain.
iFrame: Example | Download (56 KB)
First off, let me say that frames are bad and should be avoided. That being said, if you must use frames then I suppose the iframe would be the least of all the evils. Occasionally, project requirements arise such that you simply cannot get around having to use these pesky elements.
One thing I have always detested about iframes is they are not aware of the dimensions of their content. Setting the width of an iframe is trivial, because you generally know how wide its contents will be. The pain point often comes when specifying height, because pages always vary in length.
With a fixed height, the iframe is either too tall or short. This causes one of two undesirable outcomes: cutoff content, or a scrollbar. One of the cardinal sins of design is to have multiple scrollbars per page, and cutoff content just looks awkward. These two factors make iframes nearly unusable.
This past week, I thought to myself: “Wouldn’t it be nice if iframes just auto-magically knew what height they needed to be?” After a few days of toiling, with the help of jQuery, auto-sizing iframes are a reality. The underlying JavaScript code is actually quite simple.
// For other good browsers. $('iframe').load(function() { this.style.height = this.contentWindow.document.body.offsetHeight + 'px'; } );This attaches an onload event listener to each iframe tag within the page. As the content for each one loads, it reports its overall body height, and the iframes then size themselves accordingly. Likewise, any link clicked that cause the iframe to reload, also triggers a height recalculation.
In web development, there is always one browser that does things incorrectly. In this case, the culprit is Safari. It prematurely reports the onload event as being completed, once the DOM is in place, but before the CSS has had a chance to render. This gets the height calculated with browser default styles (16px font, etc) rather than the true on-screen representation.
Roll up your sleeves folks, because things are about to get messy. In order to wrangle Safari under control, we put the height calculations in a separate chunk. True to the Apple spirit, I’ve named my function iResize.
I then watch for onload, but instead of calling the resizing code directly, I force it to take a breather via setTimeout. This forces Safari to pause for an infinitely small amount of time, enough to realize that it has rendered the CSS for all the iframes. After this, the correct height is retrieved.
// Start timer when loaded. $('iframe').load(function() { setTimeout(iResize, 0); } );You’d think this would be enough, but oh how Safari loves to play coy! It does not actually execute the code associated with onload when the entire parent page is loaded. Instead, it takes reloading the content of each iframe individually for anything to happen. Until then, browser defaults win out.
Undeterred, we need to smack some sense into this dysfunctional browser. We grab the src attributes of all the iframes, and save that array into a variable iSource. We take Safari’s lunch money by setting the src attributes to blank, after which we immediately reassign the values stored in iSource. After this slight of hand, Safari renders the iframes correctly.
// For Safari to realize iframes loaded. for (var i = 0; i < iFrames.length; i++) { var iSource = iFrames[i].src; iFrames[i].src = ''; iFrames[i].src = iSource; }It’s worth mentioning there is some old-school HTML in play, for Internet Explorer and Opera. Unless otherwise specified, IE will produce a nasty border, necessitating frameborder. Like Safari, Opera tends to calculate height prematurely, but scrolling negates the issue.
<iframe src="?" scrolling="no" frameborder="0"></iframe>There you have it folks, a reliable cross-browser solution to the iframe predicament. Just include the iframe.js file, following jquery.js, in the head of your document and it will automatically parse all iframe tags and resize them accordingly. Hopefully this will save some developer headaches.
I’ve been asked by a few customers about the location of the VMware ESX\ESXi LUN masking feature and how the LUN masking is done at the VMware ESX\ESXi level in version 4.
In VMware ESX 3.0/3.5 the settings for LUN masking were available in the UI via the Advance Software settings under Disk -> Disk.MaskLUNs as shown in screenshot below.
VMware ESX\ESXi 3.x Disk.MaxLUNs Settings

Well, here is the reason why you can’t find the Disk.MaskLUNs in the UI of ESX\ESXi 4. The component is no longer accessible under the ESX\ESXi’s 4 UI. The chance is implemented as a result of the re-architecture of the storage stack. The VMware Pluggable Storage Architecture (PSA) is completely new. Old code and features were left behind in order to provide better, faster, and more reliable options and features. The Disk.MaskLUNs access via the UI was one of those left behind.
I agree with the point of taking the LUN masking feature out of the UI. Most vSphere administrators shouldn’t be manipulating those settings, unless they also happen to be in charge of the SAN environment, which hopefully means that there is a good amount of experience with storage technologies. The masking of LUN’s is something that should should be handled by the SAN team and executed on the hardware side. For configurations such as the presentation and removal of LUN’s and Volumes, it’s best to simply contact the SAN team and ask for a certain LUN or certain range of LUN’s not to be presented to the servers. LUN masking is less error-prone at the storage array than at the hosts.
One reason as to why someone would want to configure software LUN masking (ESX\ESXi) is to protect against screw-up’s by SAN administrators. In boot from SAN scenarios this would be beneficial in order to keep the ESX Servers from seeing each others booting LUN and corrupting them. With that said, as you can’t configure LUN masking from the UI in ESX\ESXi 4, you’ll have to do it from the Service Console, vCLI or vMA appliance. The new procedures on how to achieve LUN masking in ESX\ESXi 4 are listed below.
vCLI LUN Masking Procedure:
You can prevent the ESX/ESXi host from accessing storage devices or LUNs or from using individual paths to a LUN. Use the vSphere CLI commands to mask the paths. When you mask paths, you create claim rules that assign the MASK_PATH plug-in to the specified paths.
Configuration Steps
1- Check what the next available rule ID is. The claim rules that you use to mask paths should have rule IDs in the range of 101 – 200. If this command shows that rule 101 and 102 already exist, you can specify 103 for the rule to add.
esxcli corestorage claimrule list
2- Assign the MASK_PATH plug-in to a path by creating a new claim rule for the plug-in.
esxcli corestorage claimrule add -r <claimrule_ID> -t <type> <required_option> -P <MASK_PATH>
3- Load the MASK_PATH claim rule into your system.
esxcli corestorage claimrule load
4- Verify that the MASK_PATH claim rule was added correctly.
esxcli corestorage claimrule list
5- If a claim rule for the masked path exists, remove the rule.
esxcli corestorage claiming unclaim <type> <required_option>
6- Run the path claiming rules.
esxcli corestorage claimrule run
After you assign the MASK_PATH plug-in to a path, the path state becomes irrelevant and is no longer maintained by the host. As a result, commands that display the masked path’s information might show the path state as dead.
Implementation Example:
This example masks the LUN 20 on targets T1 and T2 accessed through storage adapters vmhba2 and vmhba3. #esxcli corestorage claimrule list
#esxcli corestorage claimrule add -P MASK_PATH -r 109 -t location -A vmhba2 -C 0 -T 1 -L 20
#esxcli corestorage claimrule add -P MASK_PATH -r 110 -t location -A vmhba3 -C 0 -T 1 -L 20
#esxcli corestorage claimrule add -P MASK_PATH -r 111 -t location -A vmhba2 -C 0 -T 2 -L 20
#esxcli corestorage claimrule add -P MASK_PATH -r 112 -t location -A vmhba3 -C 0 -T 2 -L 20
#esxcli corestorage claimrule load
#esxcli corestorage claimrule list
#esxcli corestorage claiming unclaim -t location -A vmhba2
#esxcli corestorage claiming unclaim -t location -A vmhba3
#esxcli corestorage claimrule run
For more on Storage masking, check out Duncan Epping’s post on Storage Masking best practice at Yellow-Brick.com.
typetext/htmlbasehttp://www.punchingclouds.com/?feed=rss2
In a nutshell, Post To enables you to provide your application users the ability to post things to MySpace. In our initial launch we??ll be offering the following Post To targets:
- Posting to the viewers profile
- Posting a bulletin
- Posting to the viewers blog
- Adding a comment
- Sending a message
Each of the targets can accept different levels of text and markup. For instance, some will accept HTML while others don??t and this is sometimes controlled by the end users privacy settings. Because of this we recommend thoroughly testing your applications.
This should go without saying but, SPAM will not be tolerated!
Overview
Post To is one of our first features that will enable you to not only help your users communicate with friends but also to start virally spreading news of your application. With just a few lines of code you can start pushing content to your users profile and friends.
Post To works by allowing you to pass a few parameters to a JavaScript function that then displays an overlay over your application (see screenshots below) . The user can then perform different actions based on the target invoked and then submit or cancel the action.
Finally, Post To is currently only available on Canvas pages.
Invoking Post To
Below we??ll go through the basics of using Post To starting with a working out of the box code example. For information on things not covered please see the http://developer.myspace.com/community/myspace/referenceIntro.aspx
Sample Code
<script type='text/javascript'>
var os_token =
MyOpenSpace.MySpaceContainer.OSToken;
var
osContainer = opensocial.Container.get();
// gets all supported post to targets
var supported
= osContainer.getMySpaceEnvironment().getSupportedPostToTargets();
var
recipientPerson;
// need a person object for add comment and send message
function init() {
dataReqObj = osContainer.newDataRequest();
dataReqObj.add(osContainer.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER));
dataReqObj.send(ownerResponse);
}
function ownerResponse(data) {
recipientPerson = data.get(opensocial.DataRequest.PersonId.OWNER).getData();
loadSupportedTargets();
}
function loadSupportedTargets() {
var temp = "<select id=\"supportedTargets\">";
for (var i = 0; i < supported.length; i++)
{
temp += "<option>" + supported[ i ] + "</option>";
}
temp += "</select>";
document.getElementById("selectInsert").innerHTML = temp;
}
function invokePostTo(){
var target_is_supported = false;
var target = document.getElementById("supportedTargets").options[document.getElementById("supportedTargets").selectedIndex].value;
var subject = "subject text";
var content = "content text";
// make sure that the selected target is enabled
for (var i = 0; i < supported.length; i++) {
if (supported[ i ] === target) {
target_is_supported = true;
break;
}
}
if (target_is_supported) {
// create a new message object passing in the content to be posted and then set the subject and target fields
var message = opensocial.newMessage(content);
message.setField(opensocial.Message.Field.TITLE, subject);
message.setField(opensocial.Message.Field.TYPE, target);
// show post to
osContainer.postTo(os_token, message, recipientPerson);
}
}
init();
</script>
<div id="selectInsert"></div>
<br>
<input type="button" onclick="invokePostTo()" value="invoke" />
postTo
opensocial.Container.get().postTo(os_token, message, opt_person, opt_callback);
openSocial.Message
Below is the function for creating a new opensocial.Message object:
var message = opensocial.newMessage(body, opt_params);
The Post To opensocial.Message message allows for three fields:
1. opensocial.Message.Field.TYPE
A supported PostTo target type from MyOpenSpace.PostTo.Targets enum. You can check if a particular target is supported by invoking: opensocial.Container.get().getMySpaceEnvironment().getSupportedPostToTargets()
Currently supported targets:
- MyOpenSpace.PostTo.Targets.PROFILE
- MyOpenSpace.PostTo.Targets.SEND_MESSAGE
- MyOpenSpace.PostTo.Targets.COMMENTS
- MyOpenSpace.PostTo.Targets.BULLETINS
- MyOpenSpace.PostTo.Targets.BLOG
Example:
message.setField(opensocial.Message.Field.Type, MyOpenSpace.PostTo.Targets.PROFILE);
2. opensocial.Message.Field.TITLE
A title for the post ?? this is not used in every target
Example:
message.setField(opensocial.Message.Field.TITLE, ??Hello World?);
3. opensocial.Message.Field.BODY
The content you want to post.
Example:
message.setField(opensocial.Message.Field.BODY, ??Hello World?);
Note: Body can also be passed in the constructor.
Target Screen Shots
Below are screen shots of the various targets with links on where you can find the corresponding MySpace feature
Posting to Profile
Posting to the users profile copies functionality found here: http://profileedit.myspace.com/index.cfm?fuseaction=profile.interests
Posting to Bulletin
Posting a bulletin copies functionality found here: http://bulletins.myspace.com/index.cfm?fuseaction=bulletin.edit
Posting to Blog
Making a blog post copies functionality found here: http://blog.myspace.com/index.cfm?fuseaction=blog.create&editor=true

Posting a Comment
Posting a comment copies functionality found here: http://comment.myspace.com/index.cfm?fuseaction=user.viewProfile_commentForm&friendID=20599042

Sending a Message
Sending a message copies functionality found here: http://messaging.myspace.com/index.cfm?fuseaction=mail.message&friendID=20599042

Sample Application
Chris has created a handy sample application for you to see Post To in action. You can install it here: http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&friendid=364361327
In a nutshell, Post To enables you to provide your application users the ability to post things to MySpace. In our initial launch we??ll be offering the following Post To targets:
- Posting to the viewers profile
- Posting a bulletin
- Posting to the viewers blog
- Adding a comment
- Sending a message
Each of the targets can accept different levels of text and markup. For instance, some will accept HTML while others don??t and this is sometimes controlled by the end users privacy settings. Because of this we recommend thoroughly testing your applications.
This should go without saying but, SPAM will not be tolerated!
Overview
Post To is one of our first features that will enable you to not only help your users communicate with friends but also to start virally spreading news of your application. With just a few lines of code you can start pushing content to your users profile and friends.
Post To works by allowing you to pass a few parameters to a JavaScript function that then displays an overlay over your application (see screenshots below) . The user can then perform different actions based on the target invoked and then submit or cancel the action.
Finally, Post To is currently only available on Canvas pages.
Invoking Post To
Below we??ll go through the basics of using Post To starting with a working out of the box code example. For information on things not covered please see the http://developer.myspace.com/community/myspace/referenceIntro.aspx
Sample Code
<script type='text/javascript'>
var os_token =
MyOpenSpace.MySpaceContainer.OSToken;
var
osContainer = opensocial.Container.get();
// gets all supported post to targets
var supported
= osContainer.getMySpaceEnvironment().getSupportedPostToTargets();
var
recipientPerson;
// need a person object for add comment and send message
function init() {
dataReqObj = osContainer.newDataRequest();
dataReqObj.add(osContainer.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER));
dataReqObj.send(ownerResponse);
}
function ownerResponse(data) {
recipientPerson = data.get(opensocial.DataRequest.PersonId.OWNER).getData();
loadSupportedTargets();
}
function loadSupportedTargets() {
var temp = "<select id=\"supportedTargets\">";
for (var i = 0; i < supported.length; i++)
{
temp += "<option>" + supported[ i ] + "</option>";
}
temp += "</select>";
document.getElementById("selectInsert").innerHTML = temp;
}
function invokePostTo(){
var target_is_supported = false;
var target = document.getElementById("supportedTargets").options[document.getElementById("supportedTargets").selectedIndex].value;
var subject = "subject text";
var content = "content text";
// make sure that the selected target is enabled
for (var i = 0; i < supported.length; i++) {
if (supported[ i ] === target) {
target_is_supported = true;
break;
}
}
if (target_is_supported) {
// create a new message object passing in the content to be posted and then set the subject and target fields
var message = opensocial.newMessage(content);
message.setField(opensocial.Message.Field.TITLE, subject);
message.setField(opensocial.Message.Field.TYPE, target);
// show post to
osContainer.postTo(os_token, message, recipientPerson);
}
}
init();
</script>
<div id="selectInsert"></div>
<br>
<input type="button" onclick="invokePostTo()" value="invoke" />
postTo
opensocial.Container.get().postTo(os_token, message, opt_person, opt_callback);
openSocial.Message
Below is the function for creating a new opensocial.Message object:
var message = opensocial.newMessage(body, opt_params);
The Post To opensocial.Message message allows for three fields:
1. opensocial.Message.Field.TYPE
A supported PostTo target type from MyOpenSpace.PostTo.Targets enum. You can check if a particular target is supported by invoking: opensocial.Container.get().getMySpaceEnvironment().getSupportedPostToTargets()
Currently supported targets:
- MyOpenSpace.PostTo.Targets.PROFILE
- MyOpenSpace.PostTo.Targets.SEND_MESSAGE
- MyOpenSpace.PostTo.Targets.COMMENTS
- MyOpenSpace.PostTo.Targets.BULLETINS
- MyOpenSpace.PostTo.Targets.BLOG
Example:
message.setField(opensocial.Message.Field.Type, MyOpenSpace.PostTo.Targets.PROFILE);
2. opensocial.Message.Field.TITLE
A title for the post ?? this is not used in every target
Example:
message.setField(opensocial.Message.Field.TITLE, ??Hello World?);
3. opensocial.Message.Field.BODY
The content you want to post.
Example:
message.setField(opensocial.Message.Field.BODY, ??Hello World?);
Note: Body can also be passed in the constructor.
Target Screen Shots
Below are screen shots of the various targets with links on where you can find the corresponding MySpace feature
Posting to Profile
Posting to the users profile copies functionality found here: http://profileedit.myspace.com/index.cfm?fuseaction=profile.interests
Posting to Bulletin
Posting a bulletin copies functionality found here: http://bulletins.myspace.com/index.cfm?fuseaction=bulletin.edit
Posting to Blog
Making a blog post copies functionality found here: http://blog.myspace.com/index.cfm?fuseaction=blog.create&editor=true

Posting a Comment
Posting a comment copies functionality found here: http://comment.myspace.com/index.cfm?fuseaction=user.viewProfile_commentForm&friendID=20599042

Sending a Message
Sending a message copies functionality found here: http://messaging.myspace.com/index.cfm?fuseaction=mail.message&friendID=20599042

Sample Application
Chris has created a handy sample application for you to see Post To in action. You can install it here: http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&friendid=364361327
In a nutshell, Post To enables you to provide your application users the ability to post things to MySpace. In our initial launch we??ll be offering the following Post To targets:
- Posting to the viewers profile
- Posting a bulletin
- Posting to the viewers blog
- Adding a comment
- Sending a message
Each of the targets can accept different levels of text and markup. For instance, some will accept HTML while others don??t and this is sometimes controlled by the end users privacy settings. Because of this we recommend thoroughly testing your applications.
This should go without saying but, SPAM will not be tolerated!
Overview
Post To is one of our first features that will enable you to not only help your users communicate with friends but also to start virally spreading news of your application. With just a few lines of code you can start pushing content to your users profile and friends.
Post To works by allowing you to pass a few parameters to a JavaScript function that then displays an overlay over your application (see screenshots below) . The user can then perform different actions based on the target invoked and then submit or cancel the action.
Finally, Post To is currently only available on Canvas pages.
Invoking Post To
Below we??ll go through the basics of using Post To starting with a working out of the box code example. For information on things not covered please see the http://developer.myspace.com/community/myspace/referenceIntro.aspx
Sample Code
<script type='text/javascript'>
var os_token =
MyOpenSpace.MySpaceContainer.OSToken;
var
osContainer = opensocial.Container.get();
// gets all supported post to targets
var supported
= osContainer.getMySpaceEnvironment().getSupportedPostToTargets();
var
recipientPerson;
// need a person object for add comment and send message
function init() {
dataReqObj = osContainer.newDataRequest();
dataReqObj.add(osContainer.newFetchPersonRequest(opensocial.DataRequest.PersonId.OWNER));
dataReqObj.send(ownerResponse);
}
function ownerResponse(data) {
recipientPerson = data.get(opensocial.DataRequest.PersonId.OWNER).getData();
loadSupportedTargets();
}
function loadSupportedTargets() {
var temp = "<select id=\"supportedTargets\">";
for (var i = 0; i < supported.length; i++)
{
temp += "<option>" + supported[ i ] + "</option>";
}
temp += "</select>";
document.getElementById("selectInsert").innerHTML = temp;
}
function invokePostTo(){
var target_is_supported = false;
var target = document.getElementById("supportedTargets").options[document.getElementById("supportedTargets").selectedIndex].value;
var subject = "subject text";
var content = "content text";
// make sure that the selected target is enabled
for (var i = 0; i < supported.length; i++) {
if (supported[ i ] === target) {
target_is_supported = true;
break;
}
}
if (target_is_supported) {
// create a new message object passing in the content to be posted and then set the subject and target fields
var message = opensocial.newMessage(content);
message.setField(opensocial.Message.Field.TITLE, subject);
message.setField(opensocial.Message.Field.TYPE, target);
// show post to
osContainer.postTo(os_token, message, recipientPerson);
}
}
init();
</script>
<div id="selectInsert"></div>
<br>
<input type="button" onclick="invokePostTo()" value="invoke" />
postTo
opensocial.Container.get().postTo(os_token, message, opt_person, opt_callback);
openSocial.Message
Below is the function for creating a new opensocial.Message object:
var message = opensocial.newMessage(body, opt_params);
The Post To opensocial.Message message allows for three fields:
1. opensocial.Message.Field.TYPE
A supported PostTo target type from MyOpenSpace.PostTo.Targets enum. You can check if a particular target is supported by invoking: opensocial.Container.get().getMySpaceEnvironment().getSupportedPostToTargets()
Currently supported targets:
- MyOpenSpace.PostTo.Targets.PROFILE
- MyOpenSpace.PostTo.Targets.SEND_MESSAGE
- MyOpenSpace.PostTo.Targets.COMMENTS
- MyOpenSpace.PostTo.Targets.BULLETINS
- MyOpenSpace.PostTo.Targets.BLOG
Example:
message.setField(opensocial.Message.Field.Type, MyOpenSpace.PostTo.Targets.PROFILE);
2. opensocial.Message.Field.TITLE
A title for the post ?? this is not used in every target
Example:
message.setField(opensocial.Message.Field.TITLE, ??Hello World?);
3. opensocial.Message.Field.BODY
The content you want to post.
Example:
message.setField(opensocial.Message.Field.BODY, ??Hello World?);
Note: Body can also be passed in the constructor.
Target Screen Shots
Below are screen shots of the various targets with links on where you can find the corresponding MySpace feature
Posting to Profile
Posting to the users profile copies functionality found here: http://profileedit.myspace.com/index.cfm?fuseaction=profile.interests
Posting to Bulletin
Posting a bulletin copies functionality found here: http://bulletins.myspace.com/index.cfm?fuseaction=bulletin.edit
Posting to Blog
Making a blog post copies functionality found here: http://blog.myspace.com/index.cfm?fuseaction=blog.create&editor=true

Posting a Comment
Posting a comment copies functionality found here: http://comment.myspace.com/index.cfm?fuseaction=user.viewProfile_commentForm&friendID=20599042

Sending a Message
Sending a message copies functionality found here: http://messaging.myspace.com/index.cfm?fuseaction=mail.message&friendID=20599042

Sample Application
Chris has created a handy sample application for you to see Post To in action. You can install it here: http://profile.myspace.com/index.cfm?fuseaction=user.viewprofile&friendid=364361327
The Flash Player contains a number of APIs for handling collision detection within Flash content. The DisplayObject class contains hitTest and hitTestPoint which can be useful if you need to detect bounding box collisions, or detect collisions between an individual point and bounding boxes or shapes.
However, BitmapData also contains a hitTest API, which can check collisions on BitmapData. Where the API really shines, is when you need to detect collisions between the visible areas of DisplayObjects (and not just of their bounding boxes). The API contains functionality for testing collisions between BitmapData and a Point, BitmapData and a Rectangle, and BitmapData and another BitmapData. It is the last item that I will focus on in this post.
Since you can get BitmapData from a DisplayObject the API can be used to detect very exact collisions between the visible areas of DisplayObjects, even if the DisplayObjects have irregular shapes.
Here is a simple example that uses the API to detect collisions between the visible areas of two MovieClips using BitmapData.hitTest.

And here is the code
var redRect:Rectangle = redClip.getBounds(this); var redClipBmpData = new BitmapData(redRect.width, redRect.height, true, 0); redClipBmpData.draw(redClip); var blueRect:Rectangle = blueClip.getBounds(this); var blueClipBmpData = new BitmapData(blueRect.width, blueRect.height, true, 0); blueClipBmpData.draw(blueClip); addEventListener(Event.ENTER_FRAME, enterFrame); function enterFrame(e:Event):void { blueClip.x = mouseX; blueClip.y = mouseY; if(redClipBmpData.hitTest(new Point(redClip.x, redClip.y), 255, blueClipBmpData, new Point(blueClip.x, blueClip.y), 255 )) { trace("hit"); redClip.filters = [new GlowFilter()]; } else { redClip.filters = []; } }
Basically, the content contains two MovieClips on the timeline. We draw the graphics for each MovieClip into a BitmapData instance, and then use the BitmapData.hitTest API to see if the visible parts of the MovieClip (non-transparent) instances collide.
Couple of notes on the example:
1. The initial fill for the BitmapData is transparent pixels. This is necessary to detect just the visible areas of the DisplayObject.
2. The Point instances passed to hitTest are used to align the BitmapData instances for the comparisons.
This example works regardless of the contents or shape of the DisplayObjects. However, if either of the DisplayObjects have had any transformations applied to them (such as rotation), then the collision detection wont work correctly.
In order to get it to work, you need to apply a Matrix when drawing the BitmapData to account for the transformation applied to one or both DisplayObjects. If you haven’t worked with Matrices and DisplayObject transformations, this can be a little daunting at first (it was for me). If you are new to using Matrices, I suggest reading this excellent article on Matrices in Flash over at senocular.com.
Luckily for me, Trevor McCauley, who runs senocular.com, also happens to works for Adobe on the Flash Player team. He really helped me understand how how to get the hit detection to work when the DisplayObjects have had transformations applied to them.
Here is the example:

and the code:
addEventListener(Event.ENTER_FRAME, enterFrame); function enterFrame(e:Event):void { blueClip.x = mouseX; blueClip.y = mouseY; redClip.rotation++; var blueRect:Rectangle = blueClip.getBounds(this); var blueOffset:Matrix = blueClip.transform.matrix; blueOffset.tx = blueClip.x - blueRect.x; blueOffset.ty = blueClip.y - blueRect.y; var blueClipBmpData = new BitmapData(blueRect.width, blueRect.height, true, 0); blueClipBmpData.draw(blueClip, blueOffset); var redRect:Rectangle = redClip.getBounds(this); var redClipBmpData = new BitmapData(redRect.width, redRect.height, true, 0); var redOffset:Matrix = redClip.transform.matrix; redOffset.tx = redClip.x - redRect.x; redOffset.ty = redClip.y - redRect.y; redClipBmpData.draw(redClip, redOffset); var rLoc:Point = new Point(redRect.x, redRect.y); var bLoc:Point = new Point(blueRect.x, blueRect.y); if(redClipBmpData.hitTest(rLoc, 255, blueClipBmpData, bLoc, 255 )) { trace("hit"); redClip.filters = [new GlowFilter()]; } else { redClip.filters = []; } blueClipBmpData.dispose(); redClipBmpData.dispose(); }
Note that we use the bounds of each DisplayObject to determine the BitmapData size and not the height / width of the DisplayObject. This is because the transformation will most likely modify the bounds, and we need to take this into account. In the first example, we could have just used the height and width of the DisplayObjects since they were the same as the bounds, but in general you should get in the habit of using the bounds.
We also pass a Matrix to each BitmapData.draw call to account for any transformations that may have been applied to the DisplayObjects (in this case rotations). I could try and explain what the Matrix is doing, but to be honest, im still trying to get my head around it. Instead, Ill let Trevor explain it (from an email he sent to me):
For this you need the transformation of the object as defined by DisplayObject.transform.matrix. Since everything is in the same container, we still won’t have to worry about walking up hierarchies to get contcatenated/global matrices – we can just use that which is directly applied to the target object (transform.matrix). This gives you the full transform of that object. But for the purposes of capturing a bitmap, we only want the non-translation parts of that transform. This is because when a bitmap is captured, it’s captured from the 0,0 location in the coordinate space of the captured object outward into positive space. The translation of the matrix of the desired object is its position in its parent coordinate space, not its own. HOWEVER, if that object’s own 0,0 location is within the middle of its graphic elements, drawing it into a Bitmap directly from 0,0 could cause cropping. So in terms of that translation as it is to be used with BitmapData.draw(), it’s still important to make sure everything in the target object is captured. And in doing that, it means shifting everything that would appear in negative coordinate space over into positive coordinate space.
Luckily, using getBounds (again) this is quite simple. We can use getBounds to determine the bounds of an object in its parent coordinate space – this includes its transformations. We also know the location of 0,0 within the parent coordinate space because that is the same location it places the target object using its x and y properties. With that, we can get the needed bitmap translation by simply subtracting the bounds x,y from the object’s own x,y. In code that essentially becomes
var b = t.getBounds(t.parent);
var m = t.transform.matrix;
m.tx = t.x – b.x;
m.ty = t.y – b.y;
var bmp = new BitmapData(b.width, b.height, true, 0);
bmp.draw(t, m);
where ‘t’ is the target display object.
Now, I will be the first to admit that I am still wrapping my head around some of this stuff, especially with the use of the Matrices to offset the transformation. However, the second example above is generic and robust enough to be used for general pixel perfect collision detection on visible portions of DisplayObjects.
One note, is that the examples above assumes that the items being compared share the same parent. If they don’t you need to make some additional adjustments (to take into consideration other transformations), but that is a post for another day.
Btw, if you don’t already, you need to read senocular.com. This is one of the best resources on understanding ActionScript 3 and the Flash Player.
Update : One optimzation which you can make is to first check if the bounding boxes of the DisplayObjects overlap (using DisplayObject.hitTestObject), and only if they do, use BitmapData.hitTest to see if their visible areas are touching.
I finally got around to trying out the new hardware overlay support in Windows 7:
http://msdn.microsoft.com/en-us/library/dd797814(VS.85).aspx
Hardware overlays are a quirk of video hardware that have survived in spite of their lack of evolution. They're essentially a secondary display scan out path in the video chip and are intended for video display, so that a video in a window can use a more optimized display format instead of the rest of the desktop for better playback performance. The biggest advantages of a hardware overlay are hardware accelerated scaling and color conversion from YCbCr to RGB, formerly very expensive operations; in some cases, you also got primitive deinterlacing and some additional TV-out support. Unfortunately, they were often also buggy in drivers. Windows Vista appeared to be the end of the line for overlays, as they were not supported in desktop composition mode, but guess what... they're back in Windows 7. As it turns out, hardware overlays are still valuable for a couple of reasons, one being that you can flip them faster and asynchronously from the composited desktop (good for performance) and because you can't capture their image in a screen grab operation (good for the paranoid). And this time, they have a few improvements, too.
The way you get to overlays is a bit different in Windows 7. In older versions, they were a feature of DirectDraw, and that meant you basically couldn't do anything other than lock-and-load -- DirectDraw couldn't even do color conversion, other than what the hardware overlay itself supported. This time, they're hooked up to Direct3D, which makes them a lot more useful since you can process video through DXVA and shader hardware and push the result into the overlay. The color space is now better defined, as there are flags for whether RGB output is computer RGB (0-255) or studio RGB (16-235), and whether YCbCr output is Rec.601/709 or xvYcc. So far, so good -- time to try it!
Now, it's not easy to get VirtualDub talking to the new overlays yet, for two reasons: the existing overlay code uses DirectDraw, and the Direct3D path only supports D3D9, whereas you need Direct3D9Ex in order to use the overlays. Therefore, I ended up just writing a one-off application to test it. Well, having gotten overlays to work and tested them a bit, I have to say they're a bit underwhelming. The good news:
Now, the bad news:
Disclaimer: I used Windows 7 RC for testing, since I don't have RTM.
So, what do we have at this point? Well, you can create a non-stretched RGB overlay with regular 0-255 range. That means unless you are either in a situation where you are being hampered by a low desktop composition rate or you need to prevent your image from being grabbed, it's unlikely that the overlay will have any advantages over plain blitting to the desktop. And of course, you need to use Direct3D9Ex to access them, which is juuuust different enough from regular Direct3D9 to be annoying. The situation might get better over time, and it may just be my crappy video card... but I'll wait until I actually see improvement.
If anyone wants to experiment with WDDM 1.1 overlays, here's the code I used to test them: d3doverlay.cpp. It's obviously not production code, but I assume if you're trying to build it you have some familiarity with setting up a project and with D3D9.
typetext/htmlbasehttp://virtualdub.org/blog/pivot/entry.php?id=282
Disclaimer: Every time we've run a piece about benchmarking or performance numbers on Ruby Inside, a retraction or significant correction has come out shortly thereafter. Benchmarking is hard, ugly, and quite often wrong or biased. It is not useless, however, but if you depend on the results in any way, you should certainly try to do your own benchmarking to confirm.
Last week, libxml-ruby 1 was released - a significant achievement since it had been under development for seven years. I suspected that it might just pip Nokogiri to the "fastest way to parse XML in Ruby" post and invited people to benchmark them. Turns out.. it ain't so. Nokogiri is the fastest.
Aaron Peterson, the developer behind Nokogiri, decided to run some tests and he's published the results in a dossier called xml_truth. The benchmarking environment was Ruby 1.8.6 on OS X 10.5 with libxml2 2.7.3 installed. Hpricot 0.6.170 competes against Nokogiri 1.2.2, LibXML-Ruby 1.1.2, and the standard library's REXML.
Aaron put together a whole suite of benchmarks, but if you just want an overview, here's a chart showing the results for in memory parsing of a 14 megabyte XML document. Note that the parsing time is in seconds and the Y-axis is logarithmic. Yes, Hpricot took over a minute, and REXML took over two minutes, while Nokogiri and libxml-ruby came in at a few seconds each:

Want all the actual numbers? Want to see the actual tests? Want to run them for yourself? Head over to Aaron's project here. Have fun! I'll putting on my flame-retardant jacket in preparation for all of the fallout about how inaccurate these tests are in 3.. 2.. 1.. :-)
Update: Hpricot 0.7 has been released and Patrick Tulskie has run some extra benchmarks. These results show that Hpricot beats libxml-ruby and Nokogiri under certain circumstances (quite significantly under an XPath test).
Update 2 (March 22, 2009): libxml-ruby's developer Charles Savage has found why libxml-ruby lagged behind Nokogiri and has resolved it.. :)
Support from: Brightbox; - Europe's leading provider of Ruby on Rails hosting. Now with Phusion Passenger support, each Brightbox server comes with access to a managed MySQL cluster and redundant SAN storage. Brightbox also provides managed services for large scale applications and dedicated clusters.
No se que pasa que cuando necesito los bootloaders para utilizarlos con QuickPwn, PwnageTool, WinPWN? no los encuentro jeje, así que pongo este post para facilitar encontrarlos, tanto a mi como a cualquiera que pueda resultarle util
Descarga: Bootloaders 3.9 y 4.6 para el iPhone
A ver si ahora ya no me vuelve a pasar jeje
Aviso: Este post es original de iPhoneApps: Todo para tu iPhone / iPod Touch
Diviértete con las viñetas de Sifón y Blackguarry en exclusiva para iPhoneApps
If you havn??t heard of Facebook. Where you been, living in a cave! Well you also probably know that in June 2007 Facebook opened a development platform for integrating new applications into Facebook, also codenamed F8. By the 24th June there were a 1,000 new applications available for the Facebook networkers to play with. According to both the online and traditional news media, Facebook have changed the game.
Well ZDNet are reporting that 1,000 developers a day are joining Facebook platform. That as it may, they are not all creating applications right away. The documentation is patchy, spread-out, difficult to understand and incomplete. It is a wonder so many applications are built because there is pain to go through to get there.
But this article is a complete tutorial for building a simple Facebook application in Ruby On Rails and should allow you to hit the ground running. We are going to create a recipes sharing application for Facebook from scratch.
UPDATE: The second part can be found here
If you havn??t heard of Facebook. Where you been, living in a cave! Well you also probably know that in June 2007 Facebook opened a development platform for integrating new applications into Facebook, also codenamed F8. By the 24th June there were a 1,000 new applications available for the Facebook networkers to play with. According to both the online and traditional news media, Facebook have changed the game.
Well ZDNet are reporting that 1,000 developers a day are joining Facebook platform. That as it may, they are not all creating applications right away. The documentation is patchy, spread-out, difficult to understand and incomplete. It is a wonder so many applications are built because there is pain to go through to get there.
But this article is a complete tutorial for building a simple Facebook application in Ruby On Rails and should allow you to hit the ground running. We are going to create a recipes sharing application for Facebook from scratch.
UPDATE: The second part can be found here
First of all some useful links:Facebook has provided many different integration points and different APIs to an application so it is worth reading Anatomy of a Facebook Application first which will explain the areas an application can affect for a user.
There are two different types of Facebook applicationWe are only going to be concerned with website applications for now. There is also 3 different ways an application can interact with Facebook.
The application can use one or all of these techniques. We are going to try all three in this tutorial.
But first lets start by creating a Rails application with NO Facebook stuff and then we??ll look at FB-ing it. Originally I planned to do this completely RESTfully but it turns out it doesn??t work well with Facebook canvas, so it??s old-skool Rails i??m afraid.
Lets create the application:
rails socialrecipe cd socialrecipeAnd create some models. We are keeping this application very simple for demo purposes so just a recipe and a comment model needed. (you will need to concate these lines properly)
ruby script/generate model Recipe title:string summary:text ingredients:text instructions:text cooking_time:string created_at:datetime updated_at:datetime ruby script/generate model Comment recipe_id:integer body:text created_at:datetime updated_at:datetimeLets create our databases. I??m using MySQL
sudo mysqladmin create socialrecipe_development sudo mysqladmin create socialrecipe_testLets changed to using database sessions. Now edit config/environment.rb change the Rails Initializer section and uncomment the following line
config.action_controller.session_store = :active_record_storeAnd add a line at the end of config/environment.rb
ActionController::AbstractRequest.relative_url_root = "/socialrecipe"What this does is change the Rails application to run starting with a socialrecipe in the first part of the URL. We need this for later but you will need your own unique name (i??m using socialrecipe). So think of one and take note.
Now lets create our development database.
rake db:sessions:create rake db:migrateNow lets create our controllers
ruby script/generate controller recipes ruby script/generate controller commentsExcellent. Now lets change our model definitions so that Recipes can have many comments. Edit app/models/recipe.rb to
class Recipe < ActiveRecord::Base has_many :comments validates_presence_of :title, :summary, :ingredients, :instructions endAnd edit models/comment.rb to
class Comment < ActiveRecord::Base belongs_to :recipe validates_presence_of :body, :recipe_id endNow lets add the controller for the recipe. Edit app/controllers/recipes_controller.rb and change it to
class RecipesController < ApplicationController def index @recipes = Recipe.find(:all) @title = "All recipes" end def show @recipe = Recipe.find(params[:id]) end def new @recipe = Recipe.new end def edit @recipe = Recipe.find(params[:id]) end def create @recipe = Recipe.new(params[:recipe]) if @recipe.save flash[:notice] = 'Recipe was successfully created.' redirect_to :action => 'show', :id => @recipe else render :action => "new" end end def update @recipe = Recipe.find(params[:id]) if @recipe.update_attributes(params[:recipe]) flash[:notice] = 'Recipe was successfully updated.' redirect_to :action => 'show', :id => @recipe else render :action => "edit" end end endEdit app/controllers/comments_controller.rb and change it to
class CommentsController < ApplicationController def new @comment = Comment.new @comment.recipe_id = params[:recipe_id] end def create @comment = Comment.new(params[:comment]) if @comment.save flash[:notice] = 'Comment was successfully created.' redirect_to :controller => 'recipes', :action => 'show', :id => @comment.recipe else render_action 'new' end end endPretty standard stuff so far creating simple controllers to create, read and update recipes and create comments. Lets setup the views
Add app/views/recipes/index.rhtml with
<h2><%= @title %></h2> <%@recipes.each do |recipe|%> <div> <h3><%= link_to h(recipe.title), :controller => 'recipes', :action => 'show', :id => recipe%></h3> <p><%=h recipe.summary %></p> </div> <%end%> <br/> <%= link_to 'New recipe', :controller => 'recipes', :action => 'new' %>Add app/views/recipes/new.rhtml with
<h1>New recipe</h1> <%= error_messages_for :recipe %> <% form_for(:recipe, :url => {:controller => 'recipes', :action => 'create'}) do |f| %> <dl> <dt><label for="recipe_title">Title:</label></dt> <dd><%= f.text_field :title %></dd> <dt><label for="recipe_summary">Summary:</label></dt> <dd><%= f.text_area :summary %></dd> <dt><label for="recipe_ingredients">Ingredients:</label></dt> <dd><%= f.text_area :ingredients %></dd> <dt><label for="recipe_instructions">Cooking Instructions:</label></dt> <dd><%= f.text_area :instructions %></dd> <dt><label for="recipe_cooking_time">Cooking Time:</label></dt> <dd><%= f.text_field :cooking_time %> mins</dd> <dt></dt> <dd><%= submit_tag "Create" %></dd> </dl> <% end %> <br/> <%= link_to 'Back', :controller => 'recipes' %>The use of dl tags for forms is not a facebook thing. It??s just the way I rock it.
Add app/views/recipes/edit.rhtml with
<h1>Editing recipe</h1> <%= error_messages_for :recipe %> <% form_for(:recipe, :url => {:controller =>'recipes', :action => 'update', :id => @recipe}) do |f| %> <dl> <dt><label for="recipe_title">Title:</label></dt> <dd><%= f.text_field :title %></dd> <dt><label for="recipe_summary">Summary:</label></dt> <dd><%= f.text_area :summary %></dd> <dt><label for="recipe_ingredients">Ingredients:</label></dt> <dd><%= f.text_area :ingredients %></dd> <dt><label for="recipe_instructions">Cooking Instructions:</label></dt> <dd><%= f.text_area :instructions %></dd> <dt><label for="recipe_cooking_time">Cooking Time:</label></dt> <dd><%= f.text_field :cooking_time %> mins</dd> <dt></dt> <dd><%= submit_tag "Update" %></dd> </dl> <% end %> <br/> <%= link_to 'Show', :controller => 'recipes', :action => 'show', :id =>@recipe %> | <%= link_to 'Back', :controller => 'recipes' %>Add app/views/recipes/show.rhtml with
<h1><%=h @recipe.title %></h1> <p><%=h @recipe.summary %></p> <h2>Ingredients:</h2> <p><%=h @recipe.ingredients %></p> <h2>Instructions:</h2> <p><%=h @recipe.instructions %></p> <p><em>Cooking time is around <%=h @recipe.cooking_time %> mins</em></p> <div id="comments"> <h2>Displaying <%=pluralize(@recipe.comments.size, 'comment')%></h2> <%= link_to 'New comment', :controller => 'comments', :action => 'new', :recipe_id => @recipe %> <% @recipe.comments.each do |comment| %> <div> <p><%= comment.body %></p> posted <%= time_ago_in_words(comment.created_at) %> ago </div> <%end %> </div> <br/> <%= link_to 'Edit', :controller => 'recipes', :action => 'edit', :id => @recipe %> | <%= link_to 'Back', :controller => 'recipes' %>Add app/views/comments/new.rhtml with
<h1>New comment</h1> <%= error_messages_for :comment %> <% form_for(:comment, :url => {:controller => 'comments', :action => 'create'}) do |f| %> <dl> <dt><label for="comment_body">Body Content:</label></dt> <dd><%= f.text_area :body %></dd> <dt></dt> <dd><%= submit_tag "Create" %></dd> </dl> <%= f.hidden_field :recipe_id, :value => @comment.recipe_id %> <% end %>And lets create a layout at app/views/layouts/index.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <title>Recipes: <%= controller.action_name %></title> </head> <body> <p style="color: green"><%= flash[:notice] %></p> <%= yield %> </body> </html> and add this line to the app/controllers/application.rb layout 'index'change config/routes.rb to have a default route
map.connect '', :controller => "recipes"and delete index.html from your public directory. That??s it. We now have a simple (and very ugly application). Fire it up with script/server and go to http://localhost:3000/socialrecipe

Lets facebook-it!! First of all we need to install the Ruby Gem RFacebook (this tutorial uses the version 0.6.2. This is a helper for interacting with the Facebook APIs. It will require you install Hpricot but make sure you pick the ruby version not the jruby one.
sudo gem install rfacebook -v 0.6.2Now you??ll need to log on to facebook (what do you mean you??re not on facebook!) and add the Developer application. Once you have done that press the big ??Set Up New Application? button.

Now fill in the following fields
Application Name: Social Recipes (You will need to change this as i have done social recipes) Check the box for Check here to indicate that you have read and agree to the terms of the Facebook Platform. Callback Url: http://localhost:3000/socialrecipe/ (The end of this is the same as your relative_url_root) Canvas Page URL: http://apps.facebook.com/ socialrecipe (The field of this is the same as your relative_url_root) Check Use iframe for now Can your application be added on Facebook? Yes Post-Add URL: http://apps.facebook.com/socialrecipe/ (The end of this is the same as your relative_url_root)
That is all hit save and you should have a page listing your application with an API Key and a Secret. Make a note of your applications API Key and Secret

Now lets edit our rails application. Add the following to your ApplicationController in app/controllers/application.rb
before_filter :require_facebook_login, :set_user include RFacebook::RailsControllerExtensions def facebook_api_key return "ADD YOUR API KEY HERE" end def facebook_api_secret return "ADD YOUR SECRET HERE" end def finish_facebook_login redirect_to :controller => "recipes" end def set_user @current_fb_user_id = fbsession.session_user_id endand add the following to your config/environment.rb
require "facebook_rails_controller_extensions" You??ll see you need to add your own key and own secret to this. The set_user filter is going to set a variable in the controller with the logged in facebook users id. We need this because we are going to store which users created which recipes and comments. To do this we need to add columns to our recipes and comments tables to store the id in. These must be BIGINT if you are using MySQL. Facebook has A LOT of users. script/generate migration add_fb_user_idsNow edit db/migrate/004_add_fb_user_ids.rb to:
class AddFbUserIds < ActiveRecord::Migration def self.up add_column :recipes, :fb_user_id, :integer add_column :comments, :fb_user_id, :integer #if mysql execute("alter table recipes modify fb_user_id bigint") execute("alter table comments modify fb_user_id bigint") end def self.down remove_column :recipes, :fb_user_id remove_column :comments, :fb_user_id end end rake db:migrateWe now need to store the facebook user ids in the tables so we??ll add a hidden field to the forms
Add the following to app/views/recipes/new.rhtml and app/views/comments/new.rhtml just before the end of the form
<%= f.hidden_field :fb_user_id, :value => @current_fb_user_id %>We are also going to protect the edit recipe to only allow you to edit your own recipes in app/views/recipes/show.rhtml change
<%= link_to 'Edit', :controller => 'recipes', :action => 'edit', :id => @recipe %> | to <%is_my_recipe? @recipe do %> <%= link_to 'Edit', :controller => 'recipes', :action => 'edit', :id => @recipe %> | <%end%>and add the following to app/helpers/recipes_helper.rb
def is_my_recipe?(recipe, &block) yield if recipe.fb_user_id.to_i == @current_fb_user_id.to_i endSee how we cast the facebook user ids to ints. This makes the match actually possible.
Now that was easy but it??s not very Facebooky. Where??s the social? Lets add some friends stuff.
Edit app/controllers/recipes_controller.rb and add the following actions
def my @title = "My recipes" @recipes = Recipe.find_my_recipes(@current_fb_user_id) render :file => "recipes/index", :use_full_path => true end def friends @title = "Friends recipes" xml_friends_get = fbsession.friends_get friend_ids = xml_friends_get.search("//uid").map{|uidNode| uidNode.inner_html.to_i} @recipes = Recipe.find_friends_recipes(friend_ids) render :file => "recipes/index", :use_full_path => true endAdd the following to your Recipe model at app/models/recipe.rb
class << self def find_my_recipes(fb_user_id) find(:all, :conditions => ['fb_user_id = ?', fb_user_id]) end def find_friends_recipes(friends_fb_ids) find(:all, :conditions => ['fb_user_id IN (?)', friends_fb_ids]) end endYou can see how we use the facebook API through the rfacebook fbsession.friends_get. This then returns Hpricot XML which we parse to get all the friends of the current user and then look for any Recipes they have created. lets just add these actions to some basic navigation.
Edit app/views/layouts/index.rhtml and include the following just under the body tag
<div id="navigation"> <%= link_to 'All recipes', :controller=>'recipes'%> | <%= link_to 'My recipes', :controller=>'recipes', :action => 'my'%> | <%= link_to 'Friends recipes', :controller=>'recipes', :action => 'friends'%> </div>We??re done lets start with script/server and navigate to http://localhost:3000/socialrecipe. Woah did you just get redirected to Facebook. Oh yes! It should be asking you to add your new Facebook application now. Tick keep me logged in and press the Log in to button.

You should now get returned to your local application. This is an example of an External Facebook Application. Try creating a new recipe and check it appears in My Recipes.

Try going to http://apps.facebook.com/socialrecipe/. You should see your application inside Facebook. This is an example of an IFrame Facebook Application.

Your application could now be ready to go, you could deploy your application to a server, submit it to the directory and let people add it. But its still not very facebook??y. We shall now go on and look at turning this into a Canvas application. In a canvas FBML application, instead of embedding your application in an IFrame, Facebook is going to make a proxy request to your application and parse the resulting markup. In this markup it can contain the Facebook Markup Language which can display more Facebook like interfaces and other direct interactions but it does limit you in what markup you can use and what you can achieve.
Now because Facebook needs to make a request to a server it must be accessible to Facebook, hence you can??t just run it on your laptop (or you can if you have a static Ip you could route facebook to). But i??m going to use my excellent RailsMachine serving to deploy the application at http://socialrecipe.liverail.net/. So don??t attempt these next steps unless you can also deploy your server to the world.
First of all we need to switch our layouts if we are in the canvas. So change the app/controllers/application.rb layout 'index'to
layout :check_fb_layout def check_fb_layout if in_facebook_canvas? "index_fbml" else "index" end endThis is going to check if the request is in a facebook canvas and if so render a different layout. So add a new layout at app/views/layouts/index_fbml.rhtml
<fb:dashboard> <fb:header decoration="add_border" icon="false">Liverail Recipes</fb:header> <fb:create-button href="<%= url_for(:controller => 'recipes', :action => "new", :only_path => true) %>"> New Recipe</fb:create-button> </fb:dashboard> <fb:tabs> <fb:tab_item href="http://apps.facebook.com<%= url_for(:controller => 'recipes', :action => "index", :only_path => true) %>" title="All Recipes"></fb:tab_item> <fb:tab_item href="http://apps.facebook.com<%= url_for(:controller => 'recipes', :action => "my", :only_path => true) %>" title="My Recipes">My Recipes</fb:tab_item> <fb:tab_item href="http://apps.facebook.com<%= url_for(:controller => 'recipes', :action => "friends", :only_path => true) %>" title="Friends Recipes">Friends Recipes</fb:tab_item> </fb:tabs> <%unless flash[:notice].blank? %> <fb:status><%= flash[:notice] %></fb:status> <%end%> <%= yield %>This will add a Facebook navigation tabs. Notice how the fb:create-button_ works fine with a relative URL but the fb:tab_item requires an absolute url with the http://apps.facebook.com, this is one of the many oddities with FBML. Additionaly we must surround the fb:status with a check because it won??t work if you have a blank tag.
We now need to render different markup for our pages.
Add the following to app/controllers/application.rb
def render_facebook(template = default_template_name) if in_facebook_canvas? #or true render :action => "#{template}_fbml" else render :action => "#{template}" end endYou now need to add a call to render_facebook at the end of actions index, show, new, edit for the recipes controller, add a call to render_facebook ??index? at the end of actions my, friends for the recipes controller and finally render_facebook at the end of actions new for the comments controller.
Lets create some FBML rendering templates.
First app/views/recipes/index_fbml.rhtml
<fb:header decoration="add_border" icon="false"><%= @title %></fb:header> <%@recipes.each do |recipe| %> <div> <h3><%= link_to h(recipe.title), :controller => 'recipes', :action => 'show', :id => recipe%></h3> <p> <fb:profile-pic uid="<%= recipe.fb_user_id %>" size="thumb" /> <fb:name uid="<%= recipe.fb_user_id %>" ifcantsee="anonymous" /> </p> <p><%=h recipe.summary %></p> </div> <%end%>app/views/recipes/new_fbml.rhtml
<fb:header decoration="add_border" icon="false">New Recipe</fb:header> <%unless @recipe.errors.blank?%> <fb:error><%= error_messages_for :recipe %></fb:error> <%end%> <% form_for(:recipe, :url => {:controller => 'recipes', :action => 'create'}) do |f| %> <dl> <dt><label for="recipe_title">Title:</label></dt> <dd><%= f.text_field :title %></dd> <dt><label for="recipe_summary">Summary:</label></dt> <dd><%= f.text_area :summary %></dd> <dt><label for="recipe_ingredients">Ingredients:</label></dt> <dd><%= f.text_area :ingredients %></dd> <dt><label for="recipe_instructions">Cooking Instructions:</label></dt> <dd><%= f.text_area :instructions %></dd> <dt><label for="recipe_cooking_time">Cooking Time:</label></dt> <dd><%= f.text_field :cooking_time %> mins</dd> <dt></dt> <dd><%= submit_tag "Create" %></dd> </dl> <%= f.hidden_field :fb_user_id, :value => @current_fb_user_id %> <% end %> <br/> <%= link_to 'Back', :controller => 'recipes' %>app/views/recipes/edit_fbml.rhtml
<fb:header decoration="add_border" icon="false">Edit Recipe</fb:header> <%unless @recipe.errors.blank?%> <fb:error><%= error_messages_for :recipe %></fb:error> <%end%> <% form_for(:recipe, :url => {:controller =>'recipes', :action => 'update', :id => @recipe}) do |f| %> <dl> <dt><label for="recipe_title">Title:</label></dt> <dd><%= f.text_field :title %></dd> <dt><label for="recipe_summary">Summary:</label></dt> <dd><%= f.text_area :summary %></dd> <dt><label for="recipe_ingredients">Ingredients:</label></dt> <dd><%= f.text_area :ingredients %></dd> <dt><label for="recipe_instructions">Cooking Instructions:</label></dt> <dd><%= f.text_area :instructions %></dd> <dt><label for="recipe_cooking_time">Cooking Time:</label></dt> <dd><%= f.text_field :cooking_time %> mins</dd> <dt></dt> <dd><%= submit_tag "Update" %></dd> </dl> <% end %> <br/> <%= link_to 'Show', :controller => 'recipes', :action => 'show', :id =>@recipe %> | <%= link_to 'Back', :controller => 'recipes' %>app/views/recipes/show_fbml.rhtml
<fb:header decoration="add_border" icon="false"> <%=h @recipe.title %> </fb:header> <fb:profile-pic uid="<%= @recipe.fb_user_id %>" size="normal" /> <fb:name uid="<%= @recipe.fb_user_id %>" ifcantsee="anonymous" /> <p><%=h @recipe.summary %></p> <h2>Ingredients:</h2> <p><%=h @recipe.ingredients %></p> <h2>Instructions:</h2> <p><%=h @recipe.instructions %></p> <p><em>Cooking time is around <%=h @recipe.cooking_time %> mins</em></p> <div id="comments"> <h2>Displaying <%=pluralize(@recipe.comments.size, 'comment')%></h2> <%= link_to 'New comment', :controller => 'comments', :action => 'new', :recipe_id => @recipe %> <% @recipe.comments.each do |comment| %> <div> <fb:profile-pic uid="<%= comment.fb_user_id %>" size="thumb" /> <p><%= comment.body %></p> posted <%= time_ago_in_words(comment.created_at) %> ago by <strong> <fb:name uid="<%= comment.fb_user_id %>" ifcantsee="anonymous" /> </strong> </div> <%end %> </div> <br/> <%is_my_recipe? @recipe do %> <%= link_to 'Edit', :controller => 'recipes', :action => 'edit', :id => @recipe %> | <%end%> <%= link_to 'Back', :controller => 'recipes' %>app/views/comments/new_fbml.rhtml
<fb:header decoration="add_border" icon="false">New Comment</fb:header> <%unless @comment.errors.blank?%> <fb:error><%= error_messages_for :comment %></fb:error> <%end%> <% form_for(:comment, :url => {:controller => 'comments', :action => 'create'}) do |f| %> <dl> <dt><label for="comment_body">Body Content:</label></dt> <dd><%= f.text_area :body %></dd> <dt></dt> <dd><%= submit_tag "Create" %></dd> </dl> <%= f.hidden_field :recipe_id, :value => @comment.recipe_id %> <%= f.hidden_field :fb_user_id, :value => @current_fb_user_id %> <% end %> <br/> <%= link_to 'Back', :controller => 'recipes', :action => 'show', :id => @comment.recipe_id %>Now i??m all done. I??m deploying my application to socialrecipe.liverail.net using capistrano and their great 5 min app deployment but you use whichever method you do to deploy your application (remember to install the rfacebook gem on your server). Once that is done you need to change the application settings in Facebook. Log on to Facebook and go the Developer application > See my apps > Edit Settings. Now change the Callback URL from http://localhost:3000/socialrecipe/ to http://socialrecipe.liverail.net/socialrecipe/ with your own names of course. Now click the Use FBML radio button and save
Go to http://apps.facebook.com/socialrecipe. Done! Ruby on Rails Facebook application.

It isn??t the best looking but you can style to your heart??s content. Go to here if you want to add my demo application and play it. In the next part of this tutorial we can do some cool stuff with events and profiles.
UPDATE: The second part can be found here
I was enjoying trying to develop a kind of completor suggestor on a textarea, I wanted it to jump when the tab key was pressed, that what easy with capturing the keydown event and the help of event.preventDefault.
But the thing what wasn’t such easy was the capturing the last word on the textarea from the cursor.
But with the help of the code of the insertAtCaret function I was abble to obtain it:
jQuery.fn.lastWord = function() { var buffer = ''; this.each(function(){ if (this.selectionStart || this.selectionStart == '0') { var startPos = this.selectionStart; var endPos = this.selectionEnd; var scrollTop = this.scrollTop; var index = 0; var new_char = ''; do{ index += 1; buffer = new_char + buffer; new_char = this.value.substr(startPos - index, 1); } while( new_char.search( /^(\w|\.)$/|> ) != -1 ) } else { alert("lastWord not supported on this navigator"); } }); return buffer; };Example of use:
alert( "last word from cursor: " + $('#my_textarea').lastWord() );Don’t copy and paste from here, WP does weird stuff with code, download from here: http://gist.github.com/143808
This script is almost not tested, it works for me on FireFox 3.0.11 and Safari 4.0.1, so use it under your own responsability.
basehttp://feeds2.feedburner.com/unDesarrolladorWebFreelancePor fin los programas de Canal Cocina, con recetas de calidad, sencillas, rápidas y variadas, gratis y en Internet. Descubre recetas para cada día con Julius Exprés, o las propiedades de cada ingrediente con Sabes lo que comes. El canal temático de recetas de cocina y dedicado a la buena mesa ya está disponible gratis.
Y si eso te parece poco, Cocina Stress te enseña a mantener una dieta sana y deliciosa sin dejarte llevar por el ajetreo de la rutina diaria: pechugas rellenas, arroz caldoso, flan con chocolate o una clásica tortilla de patata. Pero si eres de los que ya saben algo más que batir un huevo, también hay trucos de cocina y programas para tí: Darío Barrio, Ángel León…los mejores cocineros se ponen delante de las cámaras para acompañarte paso a paso en los platso más asombrosos.

Más programas e información de nuestro nuevo canal en CanalCocina.es
basehttp://blog.adnstream.tv/feed/ya habíamos escrito en un articulo anterior sobre la posibilidad de hacer flotar una carta e inclusive es vendida por 6.95 dólares en youtube.. vayaaa!!?El truco genero un gran debate entre los comentarios?
hey, tu?pagarías por aprender el truco??..Pues personalmente no pagaría si es que encuentro la forma de aprenderlo en el Internet, ustedes como yo, saben que en la web, como un poco de investigación, podemos encontrar muchas cosas interesantes..
Lo que más me impresiono de todos los comentarios recibidos, es que la mayoría pudo acertar de lo que de trataba!!.. Mis aplausos!!!..
Aquí les dejo algunas opiniones que vale la pena estudiar:
yo siento ke el tipo tiene algún tipo de hilo agarrado de su cabeza o de su pañoleta o lentes?
por ke miren, como mueve la cabeza al mover las cosas
las cosas se mueven exactamente como el mueve la cabeza!
pareciera ke tuviera un hilo de su frente o algo asi y al mover la cabeza, se mueven los objetos!
=)
eso es mi punto de vista, claro?
Es un truco relativamente sencillo, lo q tiene nuestro amigo en un hilo que le pasa por la cabeza baja por el cuello hasta la mano derecha. Porque si se fijan la carta cuando se para y la hace subir el baja dicha mano. y con el billete usa el mismo procedimiento.
Por lo menos este es el procedimiento q uso yo =)
Si os fijáis en el minuto 1:16 se le ve el hilo en el cuello, quizá sea un colgante, yo creo que efectivamente es el hilo.
Sin embargo, da un efecto bastante bueno =)
Saludos
Es fácil, tiene el hilo ese que se usa para pescar que es invisible, lo ata a la carta y el otro extremo a su oreja y pasa el hilo por sus dedos y la mueve
De que se trata el truco????
Todos acertaron, aunque por allí hubierón algunas cositas que corregir, pero todo bien!!!..La solución esta en el vídeo, pero lo que si quiero recalcar es que el hilo, está pegado detrás de la oreja para evitar que alguien lo vea?
El truco está explicado y revelado gracias al inmenso aporte de mis amigos lectores?
<embed pluginspage="http://www.macromedia.com/go/getflashplayer" src="http://www.metacafe.com/fplayer/330426/amazing_card_trick_revealed.swf" width="400" height="345" type="application/x-shockwave-flash" wmode="transparent"/>
Etiquetas de Technorati: Amazing Card Trick Revealed,flotar una carta revelado,hacer flotar una carta explicado,trucos de cartas,hacer volar unna carta,cartas,magia con cartas,magia gratis.
Ahora, pagarías por el truco???.. Pues es sencillo, simplemente ponle muchas ganas y buscate los implementos.. el resto es historia!!..
Our CEO was interviewed by Andrew Warner of Mixergy.
You can also view the interview and the transcript here . The related Hacker News thread is here .
Our CEO was interviewed by Andrew Warner of Mixergy.
You can also view the interview and the transcript here . The related Hacker News thread is here .