07 12 / 2012
Autocomplete addEventListener constants in AS3
I’ve been having some difficulty getting Flash Builder to autocomplete event type constants on addEventListener. Seems like you need to do each of the following to get it to work properly:
1. Put the event meta tag above the dispatching class
[Event(name="foo",type="pkg.events.Constants")]
class SomethingThatDispatchesFoo extends EventDispatcher {
Be sure not to accidentally put it on top of the constructor.
2. Make sure the type corresponds to the event class
AS3 gives you the handy CTRL+click functionality on the type string. Unfortunately, it doesn’t autoupdate it during a normal refactor.
If you don’t do this, AS3 will autocomplete it but only as a string.
3. Use double quotes everywhere
The [Event] metatag won’t work at all with single quotes. Also, in code, if you define your string constant with single quotes, constant resolution will not work.
class Constants {
public static const FOO:String = 'foo';
}
// autocomplete will suggest 'foo'
You must use double quotes.
class Constants {
public static const FOO:String = "foo"
}
// autocomplete will suggest Constants.FOO
Some things that you don’t have to do for it to work
- Your event constant name in code (e.g.,
pkg.events.Constants.FOO) does not have to bear any resemblance to the string value it references. You can havepublic static const FOO = "bar"and it will work just great. - It doesn’t appear that you need to recompile to have FB pick up on the new constants.
24 2 / 2012
Array#uniq in Ruby 1.8.7
On github: https://gist.github.com/1905081
class Equal
attr_accessor :name
def initialize(name)
@name = name
end
def inspect
@name
end
def hash
puts "#{name}: hash"
super
end
def eql?(co)
puts "#{name}: eql? against #{co.name}"
super
end
def ==(co)
puts "#{name}: == against #{co.name}"
super
end
end
EqualA = Equal.new('EqualA')
EqualB = Equal.new('EqualB')
EqualC = Equal.new('EqualC')
puts
def run(cmd)
puts "~~ #{cmd} ~~"
puts eval(cmd).inspect
puts
end
run '[EqualA, EqualB].uniq'
run '[EqualA, EqualB, EqualC].uniq'
class EqualHash < Equal
def hash
puts "#{name}: hash"
1000
end
end
EqualHashA = EqualHash.new('EqualHashA')
EqualHashB = EqualHash.new('EqualHashB')
EqualHashC = EqualHash.new('EqualHashC')
puts
run '[EqualHashA, EqualHashB].uniq'
run '[EqualHashA, EqualHashB, EqualHashC].uniq'
class EqualHashAndEql < EqualHash
def eql?(co)
puts "#{name}: eql? against #{co.name}"
true
end
end
EqualHashAndEqlA = EqualHashAndEql.new('EqualHashAndEqlA')
EqualHashAndEqlB = EqualHashAndEql.new('EqualHashAndEqlB')
EqualHashAndEqlC = EqualHashAndEql.new('EqualHashAndEqlC')
EqualHashAndEqlD = EqualHashAndEql.new('EqualHashAndEqlD')
puts
run '[EqualHashAndEqlA, EqualHashAndEqlB].uniq'
run '[EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC].uniq'
run '[EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC, EqualHashAndEqlD].uniq'
Equal is little more than a wrapper to Object to make things prettier. EqualHash is a subclass of Equal whose instances always return 1000 for #hash. EqualHashAndEql is a subclass of EqualHash whose instances always return true for #eql?.
Here’s the output with commentary:
~~ [EqualA, EqualB].uniq ~~
EqualA: hash
EqualB: hash
[EqualA, EqualB]
~~ [EqualA, EqualB, EqualC].uniq ~~
EqualA: hash
EqualB: hash
EqualC: hash
[EqualA, EqualB, EqualC]
#uniq internally calls #hash on each element, realizes they’re different and allows both in the resulting array.
~~ [EqualHashA, EqualHashB].uniq ~~
EqualHashA: hash
EqualHashB: hash
EqualHashB: eql? against EqualHashA
[EqualHashA, EqualHashB]
~~ [EqualHashA, EqualHashB, EqualHashC].uniq ~~
EqualHashA: hash
EqualHashB: hash
EqualHashB: eql? against EqualHashA
EqualHashC: hash
EqualHashC: eql? against EqualHashB
EqualHashC: eql? against EqualHashA
[EqualHashA, EqualHashB, EqualHashC]
#uniq sees the hash collisions and falls back to calling #eql? in a n^2 loop.
~~ [EqualHashAndEqlA, EqualHashAndEqlB].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
[EqualHashAndEqlA]
~~ [EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlC: hash
EqualHashAndEqlC: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlC: hash
[EqualHashAndEqlA]
~~ [EqualHashAndEqlA, EqualHashAndEqlB, EqualHashAndEqlC, EqualHashAndEqlD].uniq ~~
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlB: eql? against EqualHashAndEqlA
EqualHashAndEqlC: hash
EqualHashAndEqlC: eql? against EqualHashAndEqlA
EqualHashAndEqlD: hash
EqualHashAndEqlD: eql? against EqualHashAndEqlA
EqualHashAndEqlA: hash
EqualHashAndEqlB: hash
EqualHashAndEqlC: hash
EqualHashAndEqlD: hash
[EqualHashAndEqlA]
Same as above, except that because #eql? returns true, B, C, and D are not added to the intermediate resulting array. I’m not entirely sure why #hash is called again once everything is done though.
01 2 / 2012
Autoloading in Rails 3
Rails 3 by default adds these to the autoload paths:
app/*
vendor/plugins/*/lib
vendor/plugins/*/app/*
In addition, gems, when they are defined as Rails engines/railties, get each directory in app added to the autoload path.
Notable exceptions: Rails does not automatically add its own lib directory or the lib directories of any plugins to the load path.
11 9 / 2011
Asset fallback paths in Rails 3.1
Many things can cause your production asset paths to change. When that happens, your previous assets just stop working at all. Moreover, it seems like it would make sense for the bare asset path (without the md5 postfix) should just point to the most recent version of the asset. This little tidbit should take care of all of that.
Myapp::Application.routes.draw do
match 'assets/:id.:format' => 'assets#show'
end
class AssetsController < ApplicationController
def show
asset_without_digest = "#{params[:id].gsub /-[0-9a-f]{32}$/, ''}.#{params[:format]}"
new_path = ActionView::Base.new.image_path(asset_without_digest)
if url_for(params).include? new_path
head 404
else
redirect_to new_path, :status => 301
end
end
end