Posted over 2 years back at RailsTips.org - Home
In which I show how to reach the promised land of multiple file uploads using Uploadify, a spot of rack middleware and Rails 2.3.
A few weeks back we (Steve and I) added multiple asset upload to Harmony using Uploadify. If you are thinking that sounds easy, you would be sorely mistaken. Uploadify uses flash to send the files to Rails. This isn’t a big deal except that we are using cookie sessions on Harmony and flash wasn’t sending the session information with the files, so to Rails the files appeared as unauthenticated.
We found multiple articles online showing how to get this working, but none of them worked as promised. At the time Harmony was running on Rails 2.2. Knowing that rack was probably the best way to solve our issue, we updated to 2.3, which was pretty painless, and started hacking. Be sure to check out a quick screencast of the finished product at some point as well.
Add Uploadify
First, we added the uploadify files and the following js to the assets/index view. We actually set many more options, but these are the ones pertinent to this article. Script is the url to post the files to. fileDataName is the name of the file field you would like to use. scriptData is any additional data you would like to post to the url.
<%- session_key_name = ActionController::Base.session_options[:key] -%>
<script type="text/javascript">
$('#upload_files').fileUpload({
script : '/admin/assets',
fileDataName : 'asset[file]',
scriptData : {
'<%= session_key_name %>' : '<%= u cookies[session_key_name] %>',
'authenticity_token' : '<%= u form_authenticity_token if protect_against_forgery? %>'
}
});
</script>
As you can see, it adds the session key and the cookie value along with the authenticity token as data that gets sent with the file. We then use a piece of rack middleware to intercept the upload and properly set the Rails session cookie.
Add Some Middleware
We created an app/middleware directory and added it to the load path in environment.rb.
%w(observers sweepers mailers middleware).each do |dir|
config.load_paths << "#{RAILS_ROOT}/app/#{dir}"
end
Next, we dropped flash_session_cookie_middleware.rb in the app/middleware directory.
require 'rack/utils'
class FlashSessionCookieMiddleware
def initialize(app, session_key = '_session_id')
@app = app
@session_key = session_key
end
def call(env)
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
unless params[@session_key].nil?
env['HTTP_COOKIE'] = "#{@session_key}=#{params[@session_key]}".freeze
end
end
@app.call(env)
end
end
And, finally, we added the following to our session_store.rb initializer.
ActionController::Dispatcher.middleware.insert_before(
ActionController::Session::CookieStore,
FlashSessionCookieMiddleware,
ActionController::Base.session_options[:key]
)
This inserts our middleware before ActionController’s CookieStore so that everything will just work as expected.
Assign the Content Type
The only other thing we needed to do was manually set the content type of the file. We were using paperclip (which is awesome) to do uploads, so something like this did the trick:
@asset.file_content_type = MIME::Types.type_for(@asset.original_filename).to_s
Be sure to add the mime type gem to your environment.rb file as well.
config.gem 'mime-types', :lib => 'mime/types'
But Why?
So why did we go through all this trouble to allow multiple uploads at once? Taking a quick look at the finished product might help. I didn’t record the entire screen in the video, as we haven’t actually released Harmony yet (ooooh secrets!), but I did capture enough that you can see the awesome uploads in action.

Hope this spares some other poor soul attempting the same thing some time.
Posted over 2 years back at RailsTips.org - Home
A few weeks back we (Steve and I) added multiple asset upload to Harmony using Uploadify. If you are thinking that sounds easy, you would be sorely mistaken. Uploadify uses flash to send the files to Rails. This isn’t a big deal except that we are using cookie sessions on Harmony and flash wasn’t sending the session information with the files, so to Rails the files appeared as unauthenticated.
We found multiple articles online showing how to get this working, but none of them worked as promised. At the time Harmony was running on Rails 2.2. Knowing that rack was probably the best way to solve our issue, we updated to 2.3, which was pretty painless, and started hacking. Be sure to check out a quick screencast of the finished product at some point as well.
Add Uploadify
First, we added the uploadify files and the following js to the assets/index view. We actually set many more options, but these are the ones pertinent to this article. Script is the url to post the files to. fileDataName is the name of the file field you would like to use. scriptData is any additional data you would like to post to the url.
<%- session_key_name = ActionController::Base.session_options[:key] -%>
<script type="text/javascript">
$('#upload_files').fileUpload({
script : '/admin/assets',
fileDataName : 'asset[file]',
scriptData : {
'<%= session_key_name %>' : '<%= u cookies[session_key_name] %>',
'authenticity_token' : '<%= u form_authenticity_token if protect_against_forgery? %>'
}
});
</script>
As you can see, it adds the session key and the cookie value along with the authenticity token as data that gets sent with the file. We then use a piece of rack middleware to intercept the upload and properly set the Rails session cookie.
Add Some Middleware
We created an app/middleware directory and added it to the load path in environment.rb.
%w(observers sweepers mailers middleware).each do |dir|
config.load_paths << "#{RAILS_ROOT}/app/#{dir}"
end
Next, we dropped flash_session_cookie_middleware.rb in the app/middleware directory.
require 'rack/utils'
class FlashSessionCookieMiddleware
def initialize(app, session_key = '_session_id')
@app = app
@session_key = session_key
end
def call(env)
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
unless params[@session_key].nil?
env['HTTP_COOKIE'] = "#{@session_key}=#{params[@session_key]}".freeze
end
end
@app.call(env)
end
end
And, finally, we added the following to our session_store.rb initializer.
ActionController::Dispatcher.middleware.insert_before(
ActionController::Session::CookieStore,
FlashSessionCookieMiddleware,
ActionController::Base.session_options[:key]
)
This inserts our middleware before ActionController’s CookieStore so that everything will just work as expected.
Assign the Content Type
The only other thing we needed to do was manually set the content type of the file. We were using paperclip (which is awesome) to do uploads, so something like this did the trick:
@asset.file_content_type = MIME::Types.type_for(@asset.original_filename).to_s
Be sure to add the mime type gem to your environment.rb file as well.
config.gem 'mime-types', :lib => 'mime/types'
But Why?
So why did we go through all this trouble to allow multiple uploads at once? Taking a quick look at the finished product might help. I didn’t record the entire screen in the video, as we haven’t actually released Harmony yet (ooooh secrets!), but I did capture enough that you can see the awesome uploads in action.

Hope this spares some other poor soul attempting the same thing some time.
Posted over 2 years back at RailsTips.org - Home
In which I show how to reach the promised land of multiple file uploads using Uploadify, a spot of rack middleware and Rails 2.3.
A few weeks back we (Steve and I) added multiple asset upload to Harmony using Uploadify. If you are thinking that sounds easy, you would be sorely mistaken. Uploadify uses flash to send the files to Rails. This isn’t a big deal except that we are using cookie sessions on Harmony and flash wasn’t sending the session information with the files, so to Rails the files appeared as unauthenticated.
We found multiple articles online showing how to get this working, but none of them worked as promised. At the time Harmony was running on Rails 2.2. Knowing that rack was probably the best way to solve our issue, we updated to 2.3, which was pretty painless, and started hacking. Be sure to check out a quick screencast of the finished product at some point as well.
Add Uploadify
First, we added the uploadify files and the following js to the assets/index view. We actually set many more options, but these are the ones pertinent to this article. Script is the url to post the files to. fileDataName is the name of the file field you would like to use. scriptData is any additional data you would like to post to the url.
<%- session_key_name = ActionController::Base.session_options[:key] -%>
<script type="text/javascript">
$('#upload_files').fileUpload({
script : '/admin/assets',
fileDataName : 'asset[file]',
scriptData : {
'<%= session_key_name %>' : '<%= u cookies[session_key_name] %>',
'authenticity_token' : '<%= u form_authenticity_token if protect_against_forgery? %>'
}
});
</script>
As you can see, it adds the session key and the cookie value along with the authenticity token as data that gets sent with the file. We then use a piece of rack middleware to intercept the upload and properly set the Rails session cookie.
Add Some Middleware
We created an app/middleware directory and added it to the load path in environment.rb.
%w(observers sweepers mailers middleware).each do |dir|
config.load_paths << "#{RAILS_ROOT}/app/#{dir}"
end
Next, we dropped flash_session_cookie_middleware.rb in the app/middleware directory.
require 'rack/utils'
class FlashSessionCookieMiddleware
def initialize(app, session_key = '_session_id')
@app = app
@session_key = session_key
end
def call(env)
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
unless params[@session_key].nil?
env['HTTP_COOKIE'] = "#{@session_key}=#{params[@session_key]}".freeze
end
end
@app.call(env)
end
end
And, finally, we added the following to our session_store.rb initializer.
ActionController::Dispatcher.middleware.insert_before(
ActionController::Session::CookieStore,
FlashSessionCookieMiddleware,
ActionController::Base.session_options[:key]
)
This inserts our middleware before ActionController’s CookieStore so that everything will just work as expected.
Assign the Content Type
The only other thing we needed to do was manually set the content type of the file. We were using paperclip (which is awesome) to do uploads, so something like this did the trick:
@asset.file_content_type = MIME::Types.type_for(@asset.original_filename).to_s
Be sure to add the mime type gem to your environment.rb file as well.
config.gem 'mime-types', :lib => 'mime/types'
But Why?
So why did we go through all this trouble to allow multiple uploads at once? Taking a quick look at the finished product might help. I didn’t record the entire screen in the video, as we haven’t actually released Harmony yet (ooooh secrets!), but I did capture enough that you can see the awesome uploads in action.

Hope this spares some other poor soul attempting the same thing some time.
Posted over 2 years back at Jake Scruggs
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Tuesday 7-20-04
Second day of A.O.O.D. and I'm getting pretty good with UML. Today we discussed the various principles of software development:
Single responsibility,
Open/closed,
Liskov,
Interface segregation, and
Dependency inversion (Which, all together, spells
S.O.L.I.D. - you can learn things from XPAU mouse pads).
Paul an I spent an hour or so trying to design an system that could take in information about a bunch of different types of employees. Then, after we designed a system with enough interfaces and uses of inheritance to avoid violation of the principles, more user stories were added and we had to refactor. It was an initially frustrating, but ultimately fun project to take a system and make it do something new without, hopefully, coupling the classes together too much. I think we got it, but we'll find out tomorrow morning if we did.
Bob said he liked my blog, especially the bit where Micah came back after a week, looked at out project and asked us what we thought we were supposed to do. Apparently this is a pretty common experience in software -- after a few weeks the customer looks at what you've produced and either realizes that what you did isn't what s/he asked, or what they asked for isn't what they really want. One of the big points of XP is trying to make this conflict between intent and execution happen earlier rather than later. There's always going to be changes to the system, but big ones need to happen early (changing the look and feel of the GUI -- not so bad, changing a 2-D side scroller into a 3-D first person shooter? Little bit more difficult).
I still have one of those 'S.O.L.I.D.' mouse pads - I don't really need it for my optical mouse but I have it. Also nice to have an Uncle Bob (Martin) sighting. People often ask me about all the Object Mentor employees I must know, but most of them were off teaching classes at the client site or doing agile/xp coaching during the summer of 2004. I mostly hung around with David, Paul, and Micah that summer and had shorter interactions with the rest. The same thing happened at ThoughtWorks were people would assume I knew this, that, or the other person who worked there while I did. But often person 'X' was in Texas while I was in New Jersey and our interaction was limited to possible bumping into each other at a company function.
Posted over 2 years back at InfoQ Personalized Feed for unregistered user - Register to upgrade!
Ruby 1.9.2 Preview 1 is now available and brings API improvements such as Method#parameters, GC optimization for long lived objects, and more. Also: to keep up to speed with Ruby implementations, David A. Black announced ruby-versions.net which provides a long list of MRI versions as well as JRuby, Rubinius and REE installations.
By Werner Schuster
Posted over 2 years back at Ruby Inside
François Vaux has recently published a Ruby module called Rackable which allows you to make any Ruby object Rack-friendly, providing it with a REST-like interface.
What does this mean? Well, a Rack application is essentially a Ruby object that responds to call(). Rackable just gives your object a call method which uses the Rack environment to dispatch to a method.
So, you just need to include Rackable in your class and implement methods for the the appropriate REST verbs. This means you can create a hello_world.ru file like this:
require 'rackable'
class HelloWorld
include Rackable
def get()
"Hello, world!"
end
end
run HelloWorld.new
... start it with rackup, and then use something like curl (or even your browser) to call the methods.
Thanks to Alex Young for putting me on to this.
Also.. Got a slow Test::Unit or RSpec suite? Run them up to three times faster on Devver's cloud! Setup is simple and requires no code changes. Request a beta invite today!
Posted over 2 years back at Rails Inside
David Heinemeier Hansson, creator of Rails, has just announced the release of Rails 2.3.3.
Rails 2.3.3 is primarily a bug fixing release, but a few new features have creeped in, including decoding backends for faster JSON and YAML libraries, the touch method for "touching" a record's timestamp (but nothing else), and a :primary_key option for belongs_to associations to allow support for more legacy schemas.
Other than that, not a particularly exciting release, but the main focus is now on Rails 3.0.
Also.. Got a slow Test::Unit or RSpec suite? Run them up to three times faster on Devver's cloud! Setup is simple and requires no code changes. Request a beta invite today!
Posted over 2 years back at Riding Rails - home
We’ve released Ruby on Rails version 2.3.3. This release fixes a lot of bugs and introduces a handful of new features.
Active Record
touch is a convenient method to update a record’s timestamp and nothing else. This is extracted from apps whose models “touch” others when they change, such as a comment updating the parent.replies_changed_at timestamp after save and destroy. Timestamping an entire has_many association makes it easy to build a key for fragment caching that covers changes to the parent object and any of its children. This pattern is wrapped up as belongs_to :parent, :touch => :replies_changed_at. When the child changes, parent.replies_changed_at is touched. :touch => true is defaults to :touch => :updated_at.
:primary_key option for belongs_to for broader support of legacy schemas and those using a separate UUID primary key: belongs_to :employee, :primary_key => 'SSN', :foreign_key => 'EMPID' changeset
JSON
- decoding backends for the json and yajl libraries. Both are significantly faster than the default YAML backend. To get started, install the json gem and set
ActiveSupport::JSON.backend = 'JSONGem'.
* leaner user-facing encoding
API. Since a
JSON libraries implement
to_json with varying compatibility, safely overriding it is difficult. Most custom
to_json looks like
def to_json(*encoder_specific_args)
{ :some => "json representation" }.to_json(*encoder_specific_args)
end
so we DRYed the user-facing
API down to a more natural
def as_json(options = {})
{ :some => "json representation" }
end
without the ugly internal state exposed by overloading
to_json as both public-facing and internal builder
API. Rails 3 splits the
API explicitly, so prepare now by switching from
to_json to
as_json.
Other Features
- Add :concat option to asset tag helpers to force concatenation. changeset
- Restore backwards compatibility for AR::Base#to_xml. changeset
- Move from BlueCloth to Markdown for the markdown helper. Users using BlueCloth to provide their markdown functionality should upgrade to version 1.0.1 or 2.0.5 in order to restore compatibility.
Notable Bug Fixes
- Fix errors caused by class-reloading with streaming responses in development mode.
- Several fixes to the gem bundling, unpacking and installing system.
- Make text_area_tag escape contents by default.
- Make filter_parameters work correctly with array parameters.
- Thread-safety fixes for postgresql string quoting.
- Performance fixes for large response bodies.
Posted over 2 years back at Riding Rails - home
We’ve released Ruby on Rails version 2.3.3. This release fixes a lot of bugs and introduces a handful of new features.
Active Record
touch is a convenient method to update a record’s timestamp and nothing else. This is extracted from apps whose models “touch” others when they change, such as a comment updating the parent.replies_changed_at timestamp after save and destroy. Timestamping an entire has_many association makes it easy to build a key for fragment caching that covers changes to the parent object and any of its children. This pattern is wrapped up as belongs_to :parent, :touch => :replies_changed_at. When the child changes, parent.replies_changed_at is touched. :touch => true is defaults to :touch => :updated_at.
:primary_key option for belongs_to for broader support of legacy schemas and those using a separate UUID primary key: belongs_to :employee, :primary_key => 'SSN', :foreign_key => 'EMPID' changeset
JSON
Other Features
- Add :concat option to asset tag helpers to force concatenation. changeset
- Restore backwards compatibility for AR::Base#to_xml. changeset
- Move from BlueCloth to Markdown for the markdown helper. Users using BlueCloth to provide their markdown functionality should upgrade to version 1.0.1 or 2.0.5 in order to restore compatibility.
Notable Bug Fixes
- Fix errors caused by class-reloading with streaming responses in development mode.
- Several fixes to the gem bundling, unpacking and installing system.
- Make text_area_tag escape contents by default.
- Make filter_parameters work correctly with array parameters.
- Thread-safety fixes for postgresql string quoting.
- Performance fixes for large response bodies.
Posted over 2 years back at InfoQ Personalized Feed for unregistered user - Register to upgrade!
Responding to a call from developers, the Android Native Developer Kit (NDK) now supports calling native code in the Dalvik virtual machine. CPU-intensive operations that don't allocate much memory may benefit from increased performance and the ability to reuse existing code. Some example applications are signal processing, intensive physics simulations, and some kinds of data processing. By Nicholas Nezis
Posted over 2 years back at WyeWorks Blog - Home
At WyeWorks headquarters, every once in a while, we come across some project that needs a media edition/transcoding solution to build into. This was the case of our latest project in which we built a pretty simple interface with Brightcove, a powerful video platform on which we may write something about it in our forthcoming posts, but it’s not the point right now.
Turns out to be that Brightcove recommends that files should be encoded using either H.264 or VP6. As usual, we ask ffmpeg for salvation when we need to transcode media files and this was not the exception. But we didn’t want to transcode just every file nor make the choice based on the file’s extension. We wanted a way to check the current file encoding.
Searches made at that time lead us to think that the usual way to get a media file encoding is by running:
ffmpeg -i
which i must say that it’s pretty ugly for me since that command it’s supposed to be used for conversion and as far as i know it doesn’t offer some flag to get only the file information.
In fact, that command returns an error (but still prints the information we need):
jose:~$ ffmpeg -i barsandtone.flv
FFmpeg version 0.5-svn17737+3:0.svn20090303-1ubuntu6, Copyright (c) 2000-2009 Fabrice Bellard, et al.
configuration: --enable-gpl --enable-postproc --enable-swscale --enable-x11grab --extra-version=svn17737+3:0.svn20090303-1ubuntu6 --prefix=/usr --enable-avfilter --enable-avfilter-lavf --enable-libgsm --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libvorbis --enable-pthreads --disable-stripping --disable-vhook --enable-libdc1394 --disable-armv5te --disable-armv6 --disable-armv6t2 --disable-armvfp --disable-neon --disable-altivec --disable-vis --enable-shared --disable-static
libavutil 49.15. 0 / 49.15. 0
libavcodec 52.20. 0 / 52.20. 0
libavformat 52.31. 0 / 52.31. 0
libavdevice 52. 1. 0 / 52. 1. 0
libavfilter 0. 4. 0 / 0. 4. 0
libswscale 0. 7. 1 / 0. 7. 1
libpostproc 51. 2. 0 / 51. 2. 0
built on Apr 10 2009 23:18:41, gcc: 4.3.3
Input #0, flv, from 'barsandtone.flv':
Duration: 00:00:06.00, start: 0.000000, bitrate: 505 kb/s
Stream #0.0: Video: vp6f, yuv420p, 360x288, 409 kb/s, 1k tbr, 1k tbn, 1k tbc
Stream #0.1: Audio: mp3, 44100 Hz, stereo, s16, 96 kb/s
Must supply at least one output file
The information we need is the video codec (in this case vp6f) to determine if we need to transcode it.
Another thing to mention is that nothing that you see as the output there outputs to the stdout.
No rocket science needed but i was kind of lazy to parse this from scratch. Lucky for me, there was this not so new rvideo gem (still unknown for me) that made me save some precious time.
RVideo still relies in ffmpeg command and also it’s internal work to get the information we need involves that same output parsing, you just don’t have to do it yourself.
After installation (not covered here, just check rvideo readme file), you can do things as shown below:
inspector = RVideo::Inspector.new(:file => file.path)
inspector.video_codec
=> "vp6f"
inspector.duration
=> 6000
inspector.audio_codec
=> "mp3"
We’ve just made a tiny introduction to inspection. I’m not covering video processing. Check rvideo for more details!
Enjoy!
Posted over 2 years back at Railscasts
Is there a long running task which should be handled in the background? One of the best ways is using the delayed_job plugin like I show in this episode.
Posted over 2 years back at Rail Spikes
Watch out for validates_length_of if you need to make sure a string is a certain number of bytes long. For example, SMS messages can be no longer than 160 bytes in length. I recently got bit by this because some unicode “curly” quotes slipped into a reply message, but they weren’t detected by the validation.
Here’s the problem.
Consider this string:
str = "€"
It is 3 bytes long:
str.size => 3
However, ActiveRecord’s validates_length_of records this as only one character, because it uses str.split(//).size to measure the size.
If you NEED to be certain that a string is less than a certain number of bytes, you’ll need to override the default behavior of validate_length_of.
Fortunately, you can supply your own tokenizer, which makes this easy. The tokenizer is called, and size is called on its return value to find out how many tokens there are. Since String responds to size which returns the number of bytes, you can simply return the attribute value itself as the tokenizer, like this:
validates_length_of :message, :maximum => 160, :tokenizer => lambda { |str| str }
Will this still work in Ruby 1.9? I’m not sure. I now have a test case which will warn me if it doesn’t…