Monday, December 10, 2007
Advanced Rails Recipes in Beta
Tuesday, December 4, 2007
random_data v1.2.1 released
1 major enhancement
- Added method_missing to Random class, which looks for a method_name.dat file and fetches a random line for you (see docs for details) (Hugh Sasse)
- Added Random.date_between method to get a date between 2 given dates (Paul Barry)
- Added Random.boolean method to get a random true or false (Paul Barry)
- Added Random.number to get a random number less than a number or within a given range (Paul Barry)
- Enhanced Random.date method to handle a Range as well as a Fixnum, which allows you to get a date guaranteed to be in the past (Paul Barry)
- Location sources organized into more understandable categories, for easier future expansion (Hugh Sasse)
- Fixed path of require statements in random_data.rb (Paul Barry)
- Make initial never return nil, because if it returns nil then ContactInfo#email can thrown and error because it tries to call nil. (Paul Barry)
Wednesday, November 28, 2007
Testing Rails SSL Requirements on Your Development Machine
I am building a Rails app that requires some portions of the site to use HTTPS, so naturally I'm using the SSL requirement plugin. The plugin works great, but if you're using Mongrel or WEBrick running out of script/server in your development environment, you now won't be able to talk to those parts of your site (since these servers do not include SSL encryption).
The solution is pretty easy, but it's not something I found written up elsewhere, so I thought I'd document it here. All you have to do is install your own local Apache server and have it proxy requests to the Mongrel or WEBrick instance, similar to how you would set up your production environment. For simplicity I didn't use a cluster of mongrels, or mod_balance, or anything like that, just a straight-through proxy. See "A Simple Single Mongrel Configuration" on the Mongrel site for details.
But there's a bit more you need to do in order to make things work with Rails and the SSL requirement plugin. Below is a subset of my httpd.conf file; for clarity, I cut out all the default settings and just left what I added or changed.
Listen 80 # included in the default config
Listen 443 # Apache needs to know you want to accept connections over HTTPS
SSLCertificateFile /usr/local/apache/conf/newcert.pem
SSLCertificateKeyFile /usr/local/apache/conf/newkey.pem
# Below is optional, but was helpful to me in debugging this setup
CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
<VirtualHost *:80>ServerName localhost
ServerAlias 127.0.0.1
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000
ProxyPreserveHost on</VirtualHost>
<VirtualHost *:443>SSLEngine On
ServerName localhost
ServerAlias 127.0.0.1
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000
ProxyPreserveHost on
RequestHeader set X_FORWARDED_PROTO 'https' # don't forget this line!
</VirtualHost>
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>
What you're doing is setting up two different proxies through Apache to your Mongrel server; one via port 80, unencrypted, and one via port 443, encrypted with SSL. If you don't include the X_FORWARDED_PROTO line in your 443 virtual host, Rails won't know that it's using SSL and the SSL requirement filter will fail.wymanpark~ $ sudo httpd -k start Apache/2.2.6 mod_ssl/2.2.6 (Pass Phrase Dialog) Some of your private key files are encrypted for security reasons. In order to read them you have to provide the pass phrases. Server localhost:443 (RSA) Enter pass phrase: OK: Pass Phrase Dialog successful. wymanpark~ $
Friday, November 23, 2007
Notes from Asaf Ronen at Philadelphia Improv Festival
- First he had us lead each other in exercises, and checked-in with the leader during the exercise, asking "What level are they at?" and "How are they doing?". Then he had the leader provide feedback to the group to make them more successful.
- All warmup exercises have a focus, don't just do them to do them, and make sure the participants understand the point. e.g. Zip-Zap-Zop
can be played to enhance concentration, listening skills, etc. - He recommended directors/teachers delegate warmups to group members because it helps them be invested in the group, work on their own stuff. But
be sure to lead one final warmup as a way of taking back control - He led an interesting, instructive warmup:
- We all took a breath in, let it out
- We all took a breath in, let out a "sound from the bowels of hell"
- We all took a breath in, let out a musical note
The "ugly sound" was much bigger with more committment than the musical note; why? Because you're allowed to screw up -- there's no pressure
to make the "right note" or to harmonize. Interestingly, with the ugly sound we eventually harmonized anyway. People associate the note
with perfection. Judgements happen regularly in improv, even with a simple game like zip-zap-zop. So we should improvise in the spirit
of that ugly note -- having fun with it, not trying for perfection or even to harmonize. Those things take care of themselves. - It's better to give notes what TO DO, vs. what NOT TO DO
- "Any good thing you do can become a crutch"
- To give us practice on our directing skills, he split us into group A & B. Each person had an observer in the other group, so when group A did
scenes, a member of group B was just watching them. After all members of group A had done scenes in every combination with other members of group A,
the observers in group B gave their notes to Asaf (vs. directly to the performer). - He asked us to look for patterns and to give a specific challenge to the performer (via Asaf) without being corrective or even explaining
why we were giving the challenge. For example, my observer gave the challenge that I should assume a dynamic, fixed posed at the beginning of every
scene and not move. - Group A then did another round of scenes with their challenges, and the observers gave another round of feedback (which included explaining
why they picked the challenge). This was a great format and one I intend to use in the future. - Good tip for thinking of challenges: "If not, then what?"
- Challenges are like lifting weights: they need to be extreme in order to cause a change, even though in real life you're not going to go to those
extremes (e.g. not many people are going to be benchpressing 200 lbs but that's what they need to lift to produce a change in their body) - All of improv boils down to making a choice and committing to a choice. So all challenges are about encouraging different choices or more committment
to choices. - Don't start your notes by giving people a compliment, it makes them feel like a "but" is coming and they anticipate that "but"
- Helpful to say things like "I remove your responsibility to be scenic" or "to be funny"
- With challenges, if you affect one thing, it tends to 'trickle down' and affect others (hence only one challenge needed at a time)
- Challenges create impulse/immediacy -- With immediacy comes impulse and with impulse comes energy
- Can apply challenges globally to the group
- All short form comes from Spolin's acting exercises; those exercises were designed to relieve judgement and fear
- The more specific the challenge, the more easy it is to succeed right away
- One good challenge he gave was to give five pieces of tape to a performer, and had that person put tape all over the stage, with the last two pieces
being "in unusual places". The performer's challenge was to hit all of those marks as often as possible throughout the scene. - Put your focus on succeeding in the NEXT scene; don't make your notes about the PREVIOUS scenes
- You don't act emotions; you do things that convey emotion.
- If you feel emotionally ambiguous, make a sound and see what happens (that was another good challenge: make a human sound before every line)
- We then did a round of extend/continue
- helps people with physical work
- helps free people of fulfilling obligations to the scene
- People feel need to constantly introduce cnflict and solve problems right away, but it can be good to be in an environment for awhile
before a conflict starts -- or letting problems get worse before we try to solve them. - Scenes can be slice of life, not just conflict
- Sidecoaching is often choice coaching -- doesn't help in next scene (but sidecoaching can be good to help keep challenges present in the mind
of the performer) - Best sidecoaching is about choices and committments
- Need to make things as tangible for actors as possible "You're at a 5, go to a 10"
- Sounds are more informative than sound effects
- Play from inspiration, not obligation
- The way he gives notes after a show: takes less than five minutes, has two parts. What were the strongest, most fun parts of the show?
What's the challenge for next time?
Asaf Ronen Physical Improv Workshop Notes (Philadelphia Improv Festival, November 2007)
- Too often we rely on words and forget other tools
- Laban movement exercises: we milled about the stage, then made choices based on one of these dimensions: Speed, Space, Direction, and Tension.
Then we combined choices in multiple different dimensions. - Grab an object, get informaton (about your character, the object, the scene, etc). Pull it towards you, get more information, use it, get more.
- Make a sound and grab an object
- You can explain everything physically except "Why?", but you don't need to explain why, because the audience fils it in.
- It's liberating to leave Why up to the audience -- experience is more personal as a result
Sunday, October 28, 2007
Better Capistrano Rewrite Rule for Maintenance Page
I found that the common configuration available on the Internet didn't work for me. Specifically, the Apache Rewrite rule needs to reference DOCUMENT_ROOT. Here are my rewrite rules; remember that for this to work, they have to be first:
RewriteCond %{DOCUMENT_ROOT}system/maintenance.html -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ %{DOCUMENT_ROOT}system/maintenance.html [L]
Thursday, October 25, 2007
acts_as_solr, Capistrano, and testing
I've recently deployed acts_as_solr and the Apache Solr server for full text searching in a new app I am building. The plugin works great, is easy to setup, but can cause some havoc with your deployment strategy if you don't pay attention.
For one thing, out of the box the plugin stores volatile information (tmp files, the indices used for searching, and log files) within the plugin itself, because it comes with its own version of Solr pre-installed. That makes it easy to get started and play with Solr but is not acceptable for a production environment (because every time you redeploy your code you'll be destroying and re-creating those directories within the plugin).
The Java Underworld
Unfortunately this means you'll have to descend from the mighty, glistening tower of Ruby into the Java underworld to setup a Tomcat servlet running Solr. This tutorial does a great job of explaining the process which is pretty easy.
Starting and Stopping Solr
I also have added some Capistrano tasks to start and stop the Solr server during deployments to lessen the chance that the index will be corrupted:
namespace :solr do
task :start, :roles => :app do
run "cd #{latest_release} && #{rake} solr:start RAILS_ENV=production 2>/dev/null"
end
task :stop, :roles => :app do
run "cd #{latest_release} && #{rake} solr:stop RAILS_ENV=production 2>/dev/null"
end
task :restart, :roles => :app do
solr.stop
solr.start
end
end
For Capistrano to be able to run the above tasks, I also had to patch the start:solr rake task that comes with acts_as_solr to use backticks instead of exec:`java -Dsolr.data.dir=solr/data/#{ENV['RAILS_ENV']} -Djetty.port=#{SOLR_PORT} -jar start.jar`
Testing
acts_as_solr will greatly slow down any tests that use fixtures (because the indices get updated every time the fixture data gets added or removed). Ideally you would mock the Solr server in unit and functional testing (unless you're directly testing your app's interaction with Solr), but I haven't found a way to mock Solr before your tests run, when fixtures are being added. One way to go might be to create something like mailtrap for Solr requests. The other thing that might help is installing a modification of Solr called background-solr which defers all the index save and destroy requests and performs them in batches -- the idea being that during testing, maybe you would just avoid calling that batch update method for most of your tests, except where you are testing interaction with Solr (as in an integration test).
Building the Index
This is really great rake task to help build the Solr index. It's much faster and more effective that doing it manually for each of your models.
Saturday, October 20, 2007
random_data v1.1 released
sudo gem install random_dataor get it manually from the rubyforge site.
Thanks, Hugh!
Friday, October 12, 2007
Finding Improv Musicians (advice from Travis Ploeger)
Interestingly, this advice matches what Neutrino told us when they trained us in their Neutrino Video Project techniques: it's better to teach improvisors how to film scenes than to teach camerapeople how to improvise.I would first try to find any actors/improvisers that happen to play piano-
then find out if they also compose/write songs.
(My own background is as an actor/improviser. I went to a music
school, but to be a Broadway star, not a music director.)
If the pianist can successfully put themselves "in the shoes" of the actor
on stage, then it goes a long way. The ability to be a great pianist is
honestly not that important. Being able to quickly follow singers is a
skill that can be learned if someone is able to play competently- provided they
already have an ability to improvise music at the piano on their own. Most
songs usually have about 3 to 4 chords in them. The better the pianist,
the "dressier" those chord/progressions end up being.
If you can't find an improviser/actor that plays piano, the next place to
look would be an accompanist that has experience with accompanying live musical
theater, pref. somebody who also writes songs on their own and has a sense of
humor. They can borrow chord progressions from the catalog of past shows
they remember, if they can't come up with tunes and progressions on their
own.
Monday, September 24, 2007
My Love of Haml, Sass, and Standalone Sass
.content_box
%h1= link_to(@page_title,show_url(@audio.show))
= render :partial => 'display', :locals => { :audio => @audio }
= graphic_link(@audio.show,'show_default')
But half the joy of Haml comes from using its excellent stylesheet engine, Sass. Sass adds a powerful abstraction layer on top of CSS, letting you use constant variables and simple expressions, and handling a lot of nested selector drudgery. It really feels like magic to use:.storyteller_summary
:width 300px
:margin= 0 !one_gutter 0.25em 0
:float left
:clear left
.storyteller_photo
:float left
a
img.photo
:float left
:margin= 0 !half_gutter !half_gutter 0
becomes
Which is a beautiful thing. Recently I hired an excellent designer from elance.com to redesign this blog; while I can't say I executed her design perfectly, I got pretty close, and it really helped to use Sass in standalone mode. I had been using it exclusively as a Rails plugin, but as a gem it performs great as well. I wrote this little helper script to handle the transformation:
.storyteller_summary {
width: 300px;
margin: 0 10px 0.25em 0;
float: left;
clear: left; }
.storyteller_summary .storyteller_photo {
float: left; }
.storyteller_summary .storyteller_photo a img.photo {
float: left;
margin: 0 5px 5px 0; }
.storyteller_summary p {
margin: 0 10px 0.25em 0px; }
.storyteller_summary p .block_description {
display: block;
margin: 0;
padding: 0; }
.storyteller_summary p .inline_description {
display: inline; }
.storyteller_summary p a.audio_icon img {
display: inline;
float: none;
margin: 0;
padding: 0; }
.storyteller_summary p strong {
margin: 0; }
#!/usr/local/bin/ruby
require 'rubygems'
gem 'haml'
require 'sass'
template = IO.read('subelsky.sass')
open('subelsky.css','w+') { |file| file.write(Sass::Engine.new(template).render) }
Thursday, September 20, 2007
random_data gem released
It provides a Random singleton class with a series of methods for generating random test data including names, mailing addresses, dates, phone numbers, e-mail addresses, and text. This lets you quickly mock up realistic looking data for informal testing.
Instead of:
>> foo.name = "John Doe"
You get:>> foo.name = "#{Random.firstname} #{Random.initial} #{Random.lastname}"
>> foo.name
=> "Miriam R. Xichuan"
The gem also includes code for phone numbers, e-mail addresses, physical addresses, and (primitive) text generation.
You can install it via:
For more details and full documentation, visit the rubyforge site.
sudo gem install random_data
Wednesday, September 5, 2007
What's an improv class like?
The video does a good job of showing the essence of what classes are like, except that they naturally focused on the zaniest moments of the class -- we spend just as much time working on other kinds of theatrical expression and making realistic scenes. Nonetheless I think it shows how much fun we have. Thanks to Fox 45 for covering us!
To view the video, visit the Fox 45 website, then click on the "Improv" option on the right-hand "Video List" menu.
Friday, August 31, 2007
Everything I Need to Know About Improv I Learned in Camp
Some of these tips are specific to working with kids in theater, and some are not as useful for adult improvisors (because you're often trying to get adults to be MORE like kids, while the teachers were trying to get the kids to be a bit more focused), but overall I think they are great advice. Sort of an "Everything I Need to Know About Improv I Learned in Summer Camp":
Do
- Establish strong characters
- Support your peers and make _them_ look good: team effort!
- Allow yourself to be seen & heard
- Set up your relationships and environment
- Focus on an activity (but don't talk about it)
- Stay focused on the show whether you're on _or_ off stage
- Say "Yes...and..." - add info
- Use details and specificity
- Go with your instincts => don't second guess
- Project your voice
- Maintain your character (role, accent, etc.)
- Jump...and the net will catch you
- Keep up the energy
- Ask questions...give gifts instead!
- Talk over people or out of turn
- Negate your partner
- Leave the scene or kill partner
- Pull props out of thin air
- Talk or distract when off stage
- Hestitate
- Say our "list of words" [not a reference to profanity but to bad expository habits]
- Eat or remove clothing on stage
- Look at audience members - or Bridget!
- Forget to hold for laughter
Sunday, August 26, 2007
Cache Test Dummy
So, it seems obvious now, but it never occurred to me to change this line in my test.rb file:
config.action_controller.perform_caching = true
Note that you will have to make sure your pages get swept properly after running your tests. I have a rake task that deletes all of the files, I think I got it from the Peepcode caching episode:
desc "Delete all cached files"
task :sweep_cache => "tmp:cache:clear" do
%w(index.html shows* about.html audio.html contact.html photos.html photos/*.html).each do |pattern|
rm_rf(Dir[File.join(RAILS_ROOT, "public", pattern)])
end
end
A little clunky, but it works. I might someday come up with a way to invoke all of my sweepers instead so I don't have to manually add all of those filenames. I think call this task from an autotest hook:
[:red, :green].each do |hook|
Autotest.add_hook hook do |at|
`rake sweep_cache` if File.exist?("#{FileUtils.pwd}/lib/tasks/cache.rake")
end
end
Because the plugin doesn't have many examples, here's a couple of my tests:
caching_story_test.rb
class CachingStoryTest < ActionController::IntegrationTest
fixtures :all
def test_page_caching
assert_cache_pages(about_path, contact_path)
end
def test_storyteller_caching
storyteller = storytellers(:storyteller_show_1_id_1)
assert_cache_pages(show_storyteller_path(:id => storyteller.id, :show_id => storyteller.show.id))
end
end
sweeping_story_test.rb
class SweepingStoryTest < ActionController::IntegrationTest
fixtures :all
include LoginLogoutDSL
include StoopDefaults
def test_should_sweep_news_items
logs_in
news_item = news_items(:double_whammy)
assert_expire_pages(news_items_path, news_item_path(news_item), index_path) do |*urls|
put news_item_path(:id => news_item.id), :news_item => @@news_item_default_values
end
assert_expire_pages(news_items_path, index_path) do |*urls|
post news_items_path, :news_item => @@news_item_default_values
end
assert_expire_pages(news_items_path, news_item_path(news_item), index_path) do |*urls|
delete news_item_path(:id => news_item.id)
end
end
end
(I'm sure there's a way to DRY up that last test, but I found it much harder to figure out which test was failing when I did that.
Last note: the expiration test only work with path routes, not url routes. So you call "delete news_item_path(...)" vs "delete news_item_url(...)".
Tuesday, August 21, 2007
Roll your own podcast feed with Rails and Ruby's RSS library
Shoutout
I was inspired by the incomparable Topfunky's podcast application:
http://svn.topfunky.com/podcast/
I've added code to manage the iTunes metadata that extends the original RSS standard.
Ingredients
You need to use the RSS library that comes with that standard Ruby library, but if you want to add iTunes metadata, you'll need to update the standard library like so:
cd /usr/local/src/Then you need to require the right modules in a Rails initializer file. Mine is config/initializers/require.rb:
wget http://www.cozmixng.org/~kou/download/rss-0.1.9.tar.gz
tar zxvf rss-0.1.9.tar.gz
cd rss-0.1.9
ruby setup.rb
sudo ruby setup.rb
require 'rss/2.0'Model
require 'rss/itunes'
Like Topfunky, I found it easier to include the bulk of the function in the model. You could also build this up using a Builder template, which might be easier to test, since you can use assert_xml_select to test it. But my philosophy was generate it in the model, test it as best I could with a unit test, then test the output completely in my controller test.
def self.rss
author = "Overall Podcast Author/Artist"
rss = RSS::Rss.new("2.0")
channel = RSS::Rss::Channel.new
category = RSS::ITunesChannelModel::ITunesCategory.new("Arts")
category.itunes_categories << \
RSS::ITunesChannelModel::ITunesCategory.new("Literature")
channel.itunes_categories << category
channel.title = "Podcast Title"
channel.description = "Podcast description, can be a paragraph"
channel.link = "http://www.example.com/"
channel.language = "en-us"
channel.copyright = "Copyright #{Date.today.year} I Own This"
channel.lastBuildDate = Audio.last_modified.updated_at
# the above uses a method I built on the Audio model that finds
# the last modified file and makes that the build date for the
# whole podcast channel
# below is your "album art"
channel.image = RSS::Rss::Channel::Image.new
channel.image.url = "http://www.example.com/images/app_rss_logo.jpg"
channel.image.title = "Same as podcast title"
channel.image.link = "Should be same as link for whole channel"
channel.itunes_author = author
channel.itunes_owner = RSS::ITunesChannelModel::ITunesOwner.new
channel.itunes_owner.itunes_name=author
channel.itunes_owner.itunes_email='info@example.com'
channel.itunes_keywords = %w(Common Misspellings of Key Words)
channel.itunes_subtitle = "This appears in the description column of iTunes"
channel.itunes_summary = "This appears when you click the 'circle I' button in iTunes"
# below is what iTunes uses for your "album art", different from RSS standard
channel.itunes_image = RSS::ITunesChannelModel::ITunesImage.new("/path/to/logo.png")
channel.itunes_explicit = "No"
# above could also be "Yes" or "Clean"
Audio.find(:all).each do |audio|
item = RSS::Rss::Channel::Item.new
item.title = audio.title
link = "http://www.example.com/#{audio.public_filename}"
item.link = link
item.itunes_keywords = %w(Keywords For This Particular Audio Clip)
item.guid = RSS::Rss::Channel::Item::Guid.new
item.guid.content = link
item.guid.isPermaLink = true
item.pubDate = audio.updated_at
description = "Long description of this particular audio file, appears in circle I section of
iTunes"
item.description = description
item.itunes_summary = description
item.itunes_subtitle = audio.nice_title
item.itunes_explicit = "No"
item.itunes_author = author
# TODO can add duration once we can compute that somehow
item.enclosure = \
RSS::Rss::Channel::Item::Enclosure.new(item.link, audio.size, 'audio/mpeg')
channel.items << item
end
rss.channel = channel
return rss.to_s
end
Easy, right? What you're doing is building up an RSS feed that complies with the RSS 2.0 standard and with Apple's iTunes extension to the base standard. The category code is a little tricky and there may be a better way to do it. I found the RSS library docs a bit hard to understand.
Controller
All of the heavy lifting is done for us, so the controller is easy.
class AudioController < ApplicationController
def index
respond_to do |format|
format.html { @audio = Audio.find(:all) }
format.xml { render :xml => Audio.rss }
end
end
end
Route
Because of my inflection rules (where audio is singular and plural) I can't use the baked-in REST route to handle this situation, so for this to work I needed to manually wire the following route:
map.formatted_audio 'audio.:format', :controller => 'audio', :action => 'index'
Unit Test
I haven't written enough tests for this, but here's a start so I at least know the right number of audio files are in there. In audio_test.rb:
def test_should_generate_audio_rss
assert_equal Audio.count, Audio.rss.scan(/- /).size
end
Functional Test
As mentioned earlier, testing the method here gives you the added benefit of assert_select, but you need to apply Jamis Buck's wizardry to get it to work with XML files by creating an assert_xml_select method.
I'm testing almost the exact same thing as the unit test, but at least I know the file gets served up the way I expect it, and now I'm also testing whether the items have been nested properly within the channel.
def test_should_get_audio_rss
get :index, :format => 'xml'
assert_response :success
assert_xml_select 'channel item', :count => Audio.count
end
I want to improve this by incorporating XML validation into my tests but haven't figured that out yet. For now, I'm validating the feed itself.
Feed Validation
The last step before submitting to iTunes is to make sure this feed works and is valid XML. I used FeedValidator.
iTunes Submission
Pretty straightforward. Just follow Apple's directions. Getting the category right was a little tough, and there's also an issue with iTunes not recognizing the feed image properly. Doesn't look like they've fixed it yet.
Submitting Elsewhere
I added the following to the head section of my app's layout to help other aggregators find the feed:
%link{:rel=>"alternate", :type=>"application/rss+xml", :title=>"Stoop Storytelling Podcast", :href => formatted_audio_path(:format => 'xml', :only_path=>false)}
This reference was helpful in constructing the above tag.
Advertising the Link
Finally, I posted links to the iTunes store on the site itself. If people have iTunes or another podcast client installed, clicking on the store link will cause them to subscribe and help boost the rating of the podcast (thus, you don't want to give people the link to the audio.xml file itself so direct subscriptions won't get counted by Apple).
Final Product
You can listen to the podcasts here:
http://www.itunes.com/podcast?id=262444919
References
Beyond the references already cited, I relied heavily on the RSS library tutorial and reference.
Future
Is there interest in a plugin to help streamline this process further?
Saturday, August 18, 2007
REST, Caching, and Apache Rewrite problems SOLVED
Solution: This is a clash between page caching and the Apache rewrite rules. Apache sees that there is a directory in your RAILS_ROOT/public/ directory that matches the name of the URL you are POSTing to, and tries to satisfy the request by serving up content from that directory. You need to change your rewrite rules so that only GET requests for URLs are satisfied with a static file, and all POST requests are delivered to your rails app (to dispatch.fcgi, your mongrel cluster, etc.)
Solution 2: Even if you're not using caching, this problem could also occur if you have a directory in your public/ directory that matches a route in your app (so if you have a route for /assets/, and there's a RAILS_ROOT/public/assets/ directory, you may have the same problem.
Details:
1) Change this following rule in your .htaccess or your Directory directive:
RewriteCond %{REQUEST_FILENAME} !-f
to this:
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_METHOD} !^GET*
2) I'm not 100% sure this next step is necessary, but I couldn't get it to work otherwise. Add the following directive, IF the caveats in the mod_dir documentation don't apply:
DirectorySlash Off
These two steps will tweak the way Apache views incoming URLs and delivers them to your page_cached, RESTful Rails app.
Other Complications
This bug is hard to track down because it's intermittent, happening only when there are cached pages or a cached directory. On the site where I had this problem, I had a Capistrano task that swept my cached pages whenever I redeployed the app. So you can imagine my agony when I'd make a change, redeploy, the app would work great, then an hour later when pages had been cached, everything stopped working. Argh!
References
This is about 20 hours of my life I'll never get back, so I hope this saves you some pain. The following references were extremely helpful in devising this solution:
Rails mailing list post #1
Rails mailing list post #2
Mephisto wiki
Sunday, July 22, 2007
Getting Carried Away at Artscape
Wednesday, May 30, 2007
Functional Testing for Attachment-fu
def test_should_create_new_attachment
fdata = fixture_file_upload('/files/photo1.jpg', 'image/jpeg')
login_as :bob
assert_difference Photo, :count, 2 do
post :create, :photo => { :uploaded_data => fdata }, :html => { :multipart => true }
end
assert_redirected_to user_url(users(:bob))
assert_valid assigns(:photo)
end
The above assumes you create a 'files' directory inside of your fixtures directory. Also note that if you have thumbnailing enabled, each file you upload will create multiple attachment objects (in this case, one to represent the original image and one to represent a thumbnail).
If you're curious, here's how I have the plugin configured:
class Photo < ActiveRecord::Base
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '320x200>',
:thumbnails => { :thumb => '100x100>' },
:processor => 'ImageScience'
validates_as_attachment
end
Sunday, May 20, 2007
Rcov is awesome but not without these tweaks
Now I am going to try to get Heckle working for even better testing of my tests.
Friday, May 18, 2007
Notes from Mark Chalfant and Molly Woods
- What makes improv good?
- Believability
- Playfulness
- Fearlessness
- Helpful Exercises
- Cosby warmup: we all did short two-person scenes where everyone had to do their worst Bill Cosby impression. You could do this with any impression, the point of it was to get everyone used to taking risks and embracing failure.
- Two person scenes, focusing on whether players kept whatever big choice they started with
- Do a scene that is not funny but is realistic: focus on believability. Other players sit in audience and raise their hand when they see something that is not believable. Then pause the action to ask players what was not believable. [as when Nick Johne had us do a similar exercise, these scenes actually became incredibly funny]
- Audience enjoys great emotional commitment/interplay, not clever text or circumstances. Without emotional interchange, we have nothing but people being clever. This can work but you can't rely on being clever every night because that will fail you.
- Characters can ask each other to give up things or to leave, but each character has to fight for what's important to them -- you can't just give in right away.
- To move a scene forward/get yourself out trouble, ask yourself "What behavior have I created, and how can I create more?"
- At the top of scenes, each player "takes out a toy" (each 'choice' is a toy). You should play with each toy as much as possible before you throw it out. Find a way to embrace that first choice -- you don't have to 100% logically understand your choice, and you definitely don't have to explain everything to the audience, as long as there are real human emotions. Audience wants to recognize themselves on stage -- "I've been that guy or that girl" -- no matter the circumstance.
- Improvise in "the of course": assume as much as possible about your circumstances. Don't be polite or "check-in" with others.
- Let information in the scene go through you, change your character.
- On stage, we don't want to solve problems, we want to heighten them.
- Pop culture references are fine, but we need them to resonate with the scene. Don't just play clever games with your references.
- At its best, improv combines the whackiness of improvisation with the emotional commitment of theater leads.
- It's always easy to find conflict, so no need to frontload it. Explore other things in your scene, and if conflict doesn't emerge organically, you can always find it later.
- Good Challenges:
- Start every sentence with "I" or "you"
- Ask each player to state in one or two sentence what defines their character's viewpoint. Then only allow them to use those lines for dialogue for the rest of the scene.
- Only use emotional noises, no text or words (shows that you don't have to advance the plot all the time, can have a good scene just by being emotional)
Tuesday, May 15, 2007
Build a Toy First
I thought I knew Rails and Apache and MySQL and other technologies inside and out, but once I had to really cope with real-world obstacles I was knocked on my ass. My original configuration was not fast enough, and I had to implement caching to make things more responsive. I set up a number of monitoring systems to automatically restart my dispatchers if something went wrong. I found an awesome SSH client for my Treo which I had to use when my server started acting up and I was away from my home computer.
I also learned that the Internet is international -- I unconsciously assumed that most of my users would be based in the United States, but that's exactly wrong. I've got users from Växjö to Santiago de Compostela.
The site itself isn't much to look at -- I'm no graphic designer -- but it represents a major lesson for me in how to deploy a public-facing site. I'm greatly influenced by it while pursuing my other projects -- for instance, I now bake caching considerations directly into my code. I am not relying on flash[:notice] to pass messages back to the user. I'm either creating separate notification pages that can be cached, or I'm using Ajax to just update small parts of the page with status messages.
Monday, April 30, 2007
Chicago Improv Festival Artistic/Business Meeting Notes
- Mark and Jonathan offered to answer any questions we might have throughout the year about our artistic or business operations. I can't think of another art form where the leading practitioners would make themselves so available to beginners.
- CIF can help connect us with coaches from around the country through CIF artistic associates. We are definitely going to take them up on that offer.
- If you're unknown, PR for a particular media outlet can take six months to a year before you see any results.
- Annoyance Theater never used the word improv in their posters; always used the word "comedy" because that was more palatable to the audience. Audience doesn't care how the laughs are created as long as they are funny. Advised us not to use the word improv in our marketing (BIG is kind of screwed in this regard, but that's mainly why we use the tagline "Unscripted theater for Baltimore")
- Press kit is the most important element in creating a good impression on the media
- Mark told us the story of how Annoyance was founded. Mick Napier saw a Second City show and read the book Something Wonderful Right Away, and that's about all he knew about improv. They all started a troupe at Indiana University and were flying by the seat of their pants, doing weekly shows at a local bar. "Ignorance was a real advantage" -- they didn't question the validity of what they were doing.
- Jonathan outlined three layers of improv pedagogy:
- Teachers are invested in their teaching.
- Coaches are invested in the team.
- Directors are invested in the project.
- Every improv student question boils down to "Am I Good?"
- Every improv professionals' question boils down to "Is the work good?"
- When you are the director, you have to believe you are always right (they were discussing self-coached/self-directed teams)
- Annoyance has a rule: any given element of a show can only be talked about for a certain amount of time. "You can what-if everything to death"
- You should never introduce a game that you are performing in; hard for audience to accept you as a player, hard for you to get into player mindset
- Always buy your own theater if possible vs. leasing
- Realize who you are: teenage groups don't usually like to play as teenagers; all-women groups don't play as women or explore a unique female perspective on the world.
More interesting improv would result if people used who they were in their improv - Group challenges: We start all as a group of peers; some people progress at different rates, some stay behind. Some don't progress at all. It's an art form. Need to assess where a person is against where they want to be. Hard to handle this situation because you usually like all of the people you are working with, else you would not have started a group with them.
- If combining formats in one show, always do short form first. Audience will be more willing to take a ride into long form after that.
Chicago Improv Festival Coaching Notes
Each of the six apprentice teams (which included WIT's Jackie) was assigned a coach. Nick Johne coached us for 10 hours and helped us prepare a long-form set that we performed Saturday night. Nick gave us very excellent and specific coaching and was a real gift to work with.
Below are the rough notes I took during the festival. Most were drawn from Nick's coaching except where indicated:
- Warm-up design
Nick taught us a new warmup game called "Whoosh", which is a variation of other "pass the ball with a sound" games, but at the end he asked us to invent our own
moves to add to the game. I thought this was a neat way of emphasizing the improviser mentality that you should not be playing with rules that constrain you, you
should always be ready to adapt the form to your creative drive. I'm going to add this variation to every warmup that I lead. - Excessive agreement exercise
We faced each other in chairs, two at a time, and had a conversation where Nick forced us to say "yes" as many times as possible. This led to some great energy and funny moments
as people tried to affirm each other as strongly as possible. Nick pointed out that eventually we should be able to play with that same kind of energy and affirmation, but layer other emotions on top of it beyond happiness/excitement. - Learning how to create deeper, more satifying scenes
Nick taught us a ton of methods to create more meaningful scenes. My favorites were:- Doing a scene in real time
The best scenes we did in rehearsal were when Nick gave us a scenario, such as two people in a pharmacy, which had to play out in real time (i.e. waiting for the prescription to be filled took the real amount of time). This sounds like it would be boring, but in fact it encouraged the performers to play in a very patient way, to really enjoy discovering the environment and the characters. The scenes usually led to huge laughs that came from something ethereal like a pointed look. - Patient improv
Nick emphasized being patient with us a lot, a quality I had not previously emphasized in my own teaching. It hit home with me when we saw Dasariski perform. Three guys did a 40 minute single scene (with two or three short scenes sprinkled in) that was utterly brilliant. They started slowly and did not try to justify
everything through exposition. Gradually a story was teased out of the emotional dynamics among the characters, and there were some fast-paced moments, but
they stuck with the patient style. Why are we always in such a hurry? These guys were playing with total commitment and had crazy ideas, but because they didn't
force it, it was a very elegant, hilarious show. - Mirror each other physically
We performed two-person scenes where we had to mirror the other actor's physicality. If one player moved to a corner of the stage, the other had to move to the opposite corner. - Make eye contact, then look away
In pairs we did scenes where the characters made eye contact, then looked away, over and over again. - Politically Incorrect Scenes
We did scenes where Nick gave us permission to be as offensive as we possibly could. This actually led to some compelling scenes because we saw that when we played from the heart, it was clear that our characters were saying these things, and not us. The audience will allow you to be very dark (for example by playing a sexist or bigotted or racist character) if you commit to it, and the results can be hilarious and profound. Also I feel like this could be an antidote for troupes that play too nicely, or only rely on one or two people to be outrageous or dangerous (which I think is a limitation in BIG).
- Doing a scene in real time
- Four Scene Tones
When editing, we should vary the tone of scenes to create a diverse show and not get locked into one particular pattern:- Physical
- Surreal
- Intellectual
Emotional
We did an exercise where we had to edit every scene by deciding which category had just been played, and starting a new scene in a different category. If we did a very talky, intellectual scene, we had to follow it with something very emotional or physical or surreal. - Follow your feet
When he saw us stutter-stepping on the sidelines, this was Nick's commandment to us to get on their and edit and trust our instincts. - Editing exercise
Before introducing any edit techniques to us, we did a round of scenes where we were not allowed to use wipe edits. This forced us to discover our own ways of editing (or use techniques we had learned elsewhere, like tag edits). This is the best way to introduce editing in my opinion; don't tell people the "right way" to edit scenes. Let the group experiment and then coach on what works or doesn't work for a particular style. - Audience calls edit
Two person scenes performed until someone in the audience called "edit". We then discussed why that person had decided to edit when they did. This was a really good way to illuminate editing instincts. - Organic edit
Nick showed us a technique where multiple players started doing the same activity and the entire troupe piled on, making an organic group game that wiped the scene until two
players were left to start a new scene (hard to explain but powerful in practice). - Cartoony characters
Two people a time played very intense, over-the-top, cartoony characters. Mid-way through the scene, Nick had them switch characters, which was a great challenge for expanding range. - Repetition
One actor repeated everything the other actor said (sort of a half-duplex version of last line). This fostered agreement and discouraged storytelling/plotting, and led to a really cool scene - "Wear a veil instead of a mask"
Nick's note to me was that I often played very theatrical characters, and that I should try playing more realistically. This is problem an artefact of my roots in short form. - Source Scenes
One great way to use a scene to inspire other scenes was to show causes and effects of a scene. - Always go with the first offer
This echoed what Mark Sutton taught me a few weeks prior; improvisers fall in love the second idea, when the first one would be plenty sufficient. - Use your own worlds
Nick had us two scenes as ourselves, filtering everything that happened through something that we were expert in. This drove home the point that you can create
very interesting work just by being yourself and using what you know. - Improv is a folk tradition
I realized during this trip that improv really is a folk tradition. We do things here in Baltimore that we learned from people who trained in New York City, in San Diego, in Cambridge, and elsewhere, and many of these things were handed down to us by people who themselves received them from improv's master teachers. Gradually the names of concepts change, and new elements are added, to the point where we don't even know our own heritage. I really enjoyed being in Chicago and working with some of the pioneers of improv to see where some of these traditions come from.
Sunday, April 22, 2007
Taming assert_select with css_select and Regexp.escape
Fortunately, I noticed that Rails also has a css_select method which returns an array of selected elements without running tests on them. This lets you run your own tests using the results of the selection.
This isn't the prettiest code in the world (I'm also testing a formatting helper, hence the literals '$200.00' and so on), so I'll probably refactor it later. There might also be a way to do this more elegantly with assert_select. But I think this does show the utility of css_select.
elements = css_select('table#investors tr td')
[[investors(:investor_8),'$200.00'],
[investors(:investor_9),'$343.40']].each do |i,amount|
assert_not_nil elements.detect \
{ |e| e.to_s =~ /#{i.name}/ }
assert_not_nil elements.detect \
{ |e| e.to_s =~ /#{Regexp.escape(amount)}/ }
end
Things to watch out for:
- You need to force the conversion of the element to a String for the regular expression comparison (with to_s)
- In this particular example, since I am using string literals with special characters, I had to use Regexp.escape to make $ and . match properly
Tuesday, April 17, 2007
DC Comedy Festival improv workshop notes
Mark Sutton's workshop: Finding More
Box exercise
As a class, he had us explore an improvised box of items of personal significance. At various intervals he would say 'go' and we would start a monologue about the object in our hand. Helped reinforce the concept that environment work in improv should have some kind of importance for the characters, not just to give your hands something to do.
Chair exercises
He moved the chairs around in various positions and had us do the same scene premise (someone getting fired) over and over again but with different configurations. Very different scenes resulted from different configurations (close together, far apart, etc.). We also did scenes where at the end, the improvisers had to reposition the chairs. The next scene would be inspired by the position of the chairs (though we were not required to sit in the chairs at all). I found this led to some really cool new scenework and inspiration.
In one of these scenes, the chairs were used to demarcate the front half of the stage from the back. One actor was placed in the front and told never to look back at the other actor, who was in the back half and not allowed to cross the line into the front half. This led to a very interesting dynamic where the person in the front had high-status (because they never looked the other character in the eye) even though it was a seemingly-low status character.
How Improvisers Make Themselves Safe
We use words/dialogue to make sure everyone is okay. Improv is not about feeling okay, it's about taking risks. Words become information you have to deal with, a box you can't get out of (or spend lots of time trying to get out of).
Second City saying: "Bring a brick, not cathedral."
Joe Bill's workshop, "How to Stand Out in a Scene"
- A big difference between short and long form is the source of tension that's powering it.
- In short form, the game is the source of tension. Will they execute it? Will they do it in a way that's funny or surprising?
- In short form, you don't need to act; you can indicate. It's a head game, mostly, because it's a form built on rules and right and wrong--that's the nature of a game.
- In long form, the tension for the audience is: Do I believe you? Do I continue to believe you? Will I be surprised by what you get me to believe? It's lodged in the heart and gut, and any consideration of right or wrong will screw you.
- In long form, characters reveal themselves in three ways:
- What they say
- What they do
- What they value or stand for
- It doesn't matter whether you discover these things, or decide them--or in what order. But character is how you do what you do. If you know who you are, you'll know what to do.
- In improv, we're going for the absence of self-consciousness and judgment. The audience wants to see that as much as they want to see funny stuff--they're paying for something they want to do but can't.
Warmup
The whole class did three characters for 30 seconds each. Then they asked us to pick the most interesting/surprising character and revisit it for 30 seconds. We then did three scenes as that character, two students at a time.
- As the character we picked
- Using an object with meaning for that character
- Playing some aspect of that character to the extreme, over-the-top
You only have three things to work with: actions, speech, and internal point-of-view. They asked everyone to pick an internal point-of-view (such as an emotion or attitude). We then got into two lines and did two-person scenes. Line 1 started by projecting their POV onto their scene partner (e.g. my attitude is 'fear', so I start the scene by regarding my partner fearfully). Line 2 started by projecting their POV onto their environment (e.g. my attitude is 'boredom', so I start making a pizza in a bored way).
By doing this at the start of the scene, we started to get more information. Your bored pizza-making or fearful-regarding leads to more inspiration about the shape of your scene. Once this happens, they asked us to start dialogue and interaction.
The Improv Glance
They told us about this obvious 'tell': when an improviser looks around at the scene partner to check in with the partner. The tell is this shows you are looking for support instead of creating something for yourself. When you look at the other character it should be for a character reason.
Improv scenes are simple
They emphasized that great improv scenes are not usually very complicated. Many times we make them complicated by "feeding circumstances to the premise monster" -- which I found incredibly apt!
When characters ask questions, or argue, it's fine.
When improvisers do, its bad. This goes a long way to explaining why the 'Yes, And' rule is a bit simplistic; characters can say 'no' to each other as long as improvisers are not.
Circumstances vs. Dynamics
This was the best improv exercise I've ever done: in groups of three, Mark gave us a circumstance and told us to play it absolutely realistically. One was a doctor telling a patient he had a terminal illness, one was parents telling their daughter how much they loved her before her wedding day, etc. He asked us to remember exactly how the emotional dynamic felt between the characters.
After everyone had gone, the same groups replayed their scenes with the exact same dynamics, but this time with different circumstances. So in the first round, I was the doctor. In the second round, I was a car mechanic telling a guy that his car could not be fixed. So instead of playing the usual stereotyped car mechanic guy, I played a really serious, sober-minded car mechanic, and the 'victim' played a really hilarious (but totally deadpan) guy who was devastated by the loss of the car.
I'm still processing the implications of this exercise, but the main point was: the audience cares about emotional dynamics. Invest in the dynamics and don't worry about explaining everything by generating circumstances.
Improvisers often fall in love with the second idea
We waste too much time at the start of scenes figuring out what the scene is about. We do something that's plenty great at the top of a scene, but then drop that offer when we get 'the second idea'. The audience then wonders what happened to that first idea.
Mick Napier's Workshop
Personal Attention
He totally lived up to his reputation. First of all, he asked all 25 of us to introduce ourselves and memorized all of our names on the spot. Then all 25 of us did an hour of short scenes. He then gave us each a detailed, personal critique of what our improv was like, and gave us a single challenge to work on to make it better. Then we did another hour and a half of scenes that were much better. We finished up with a Q&A session (notes from that below).
The main thing I took away from Mick was the importance and the potential for giving improvisers individual attention. If he can do it for 25 people in a single 3.5 hour session, why can't we all do it for 6-12 people in weekly 2 hour sessions?
To keep a troupe fresh
- Learn new forms (even if you don't perform them)
- Bring new people in (as long as you're careful about screening them)
- Occasionally have a rehearsal where someone in the troupe brings something new to work on that the group has never done before
Decide to be good at learning people's names. Start telling people that you're good with names. This will change your brain so you can remember names.
Introduce a game never played before
He told us about something awesome that Second City sometimes does in rehearsal, but which you could do on stage: have a player stand in front of the audience and say "We're now going to perform a game/format that we've been doing for five years. It's called [made-up name], and here's how it works..." The player then invents the rules or the structure on the spot. Everyone on the backline listens attentively but pretends like this is old hat. Then you jump in and perform it.
Don't be funny exercise
He also recommended doing scenes in rehearsal that are explicitly not funny, that are serious and real, as a way of getting into more inspired improv.