Tigraine

Daniel Hoelbling-Inzko talks about programming

CanCan: Beware of symbol conditions

CanCan is probably the most widely used authorization solution for Ruby on Rails, and for good reason. But sometimes weird things happen.

Given the following ability:

can :read, User, role: :developer

I was experiencing the following:

@user = User.accessible_by(current_ability).first
can? :read, @user #=> false ???

As you can see, the accessible_by method was returning the user list just fine, so I obviously had the permission to read the user at this point, but once I asked the authorize! or can? methods about the same user they promptly replied with false.

The culprit here is ActiveRecord's indifferent-access of strings and hashes. Something that had me scratching my head at more than one occasion over the last few years. ActiveRecord doesn't care if the keys in a hash are strings or symbols, so a beginner might be tempted to think Ruby does not differentiate between those.

But Ruby does care, 'test' != :test will return true! Whereas ActiveRecord doesn't care: ``` User.where('role' => 'developer')

or

User.where(:role => :developer) ```

This is due to the heavy use of ActiveSupport::HashWithIndifferentAccess that makes this possible in Rails:

a = {}
a[:foo] = 'test'
puts a['foo'] #=> 'test'

Now if we look at the conditions derived from the above ability you will quickly see the problem:

current_ability.model_adapter(User, :read).conditions
# => { role: :developer }

ActiveRecord doesn't care about the symbol, it will happily return all Users with the role column set to the string developer, whereas CanCan will do the can? check in Ruby, doing essentially this:

puts @user.role #=> 'developer'
# user.role is a string - the condition a Symbol
puts @user.role == :developer #=> false

Conclusion: Always make sure your conditions are valid both in ActiveRecord AND Ruby! Where ActiveRecord and Rails in general promote a sloppy type-free behavior, other frameworks don't necessarily see it that way. So keep in mind that a symbol is not a string!

Also when you know you might get a symbol and want to compare it to a string, don't use .to_sym on the string but rather .to_s on the symbol - symbols don't get garbage-collected, so they will stick around in memory forever. Never .to_sym user input or bad things will happen™!

Filed under ruby, rails, cancan

Focus point tester

I am currently trying to reduce my reliance on the backside display on my camera. All relevant information on the current frame are right inside the viewfinder, so taking the eye away from the finder to fiddle with controls is really unnecessary.

This works reasonably well for normal settings, but I quickly became annoyed with my own clumsiness with the two dials when selecting a new focus point (since there is that handy button next to the shutter).

Canon 70D AF Control Scheme. Image Taken from Canon EOS 70D Manual

So I wrote a little page that helps me practice the AF selection by providing me with a point grid and randomly selecting one point to manually change to while looking through the viewfinder.

You can find it here: http://www.tigraine.at/uploads/focus.html

Filed under photography

Thoughts on photographing fireworks

alt

I have recently rediscovered my love for photography, and have been looking forward to New Year's Eve 2013 for quite some time as I expected to be able to get some pretty spectacular firework shots. The rationale was simple: Photographing stuff with a slow shutter speed is incredibly easy - anyone getting into photography should get a tripod and experiment with low shutter speeds and moving lights. And when applied to fireworks the results look really spectacular.

So I looked at a few places around Klagenfurt (my home town) for one with convenient access and a decent view on the action. I did not want to go too far out on any of the surrounding mountains since the weather had been a bit unpredictable lately, and I figured inside the city I'd at least see some fireworks, even when they are a bit obscured by fog. Outside you could end up with zero visibility on the action.

But still I needed something with elevation, so after visiting a few locations I decided on this nice view from Kreuzbergl:

Kreuzbergl View

I figured the road straight to the city center would give the pictures some depth, while the sky around us should be filled with exploding fireworks.

So at 23:00 our party headed out to the chosen spot and on to my first lesson: Take the whole bag!

I figured I'd best use the EF-S 10-22mm for the fireworks and thought I could save myself the hassle of taking the whole heavy camera bag with me. So I left the camera bag in the car and just took camera + tripod with me. 20 Meters down the road I noticed that I had forgotten the lens hood and darted back to the car. I picked up the lens hood and ran back to where I had left the tripod, just when I remembered that I had forgotten the cable release in the bag too. At that point I decided to just pick up the whole bag and be done with it - really annoying.

Taking the whole bag was a great idea, because lesson #2 presented itself to me at 00:00 - I had not bothered to ask anyone who might know if there are any fireworks at all at Kreuzbergl. So when the new year came, the fireworks where concentrated on the horizon, but there where virtually none in the sky above me (and I was zoomed out to 10mm).

alt

As you can see there where a lot of fireworks in the distance, but none above me. Apparently nobody shoots fireworks in this part of town :(. And I was now stuck with the wrong lens on my camera. Thank god I had taken all of my gear, so I decided to switch to the 70-200.

After changing the lens, screwing it to my tripod and adjusting my exposure I managed to get some decent shots of the fireworks. But the whole process had taken too long, and I missed most of the initial action. My friend next to me who shot at 55 mm focal length managed to get this really awesome shot (while my keepers consisted mostly of crops with one or two fireworks in the distance):

alt

This then led me to lesson #3: Ask around for commercial fireworks.

Around 200 meters behind the spot where I was shooting towards the city center is a really nice restaurant that traditionally shoots a lot of fireworks. I did not know that! They waited a few minutes for the initial burst to die down, and right when I had finished switching from my ultra-wide lens to a telephoto they started lighting the sky right above me.

The fireworks display from Schweizerhaus was impressive. Had I not bothered with the rest of the city, just shooting the fireworks from the Schweizerhaus would have been awesome. Especially since it's location was very predictable, the delay between explosions was essentially fixed and they all exploded at roughly the same height. So if possible, ask around what hotels or restaurants put on a fireworks show and find out where they usually launch theirs. It's a lot more predictable than hoping for random fireworks to appear in your frame.

Anyway, at that point I took my camera off the tripod, and shot the fireworks @70mm 1/200 f/2.8 and got some really nice action shots of exploding fireworks. But once again I had the wrong lens, unable to do the shots I had planned initially.

So to sum up the lessons I learned this year:

  • Take the whole bag - you never know when you need another lens. (I never thought I'd need a telephoto when shooting fireworks!)
  • Either shoot in locations where you know there will be plenty of fireworks in your frame - or ask around.
  • Use the right lens. Great fireworks that cover only 20% of your frame look really unspectacular.
  • Ask for commercial fireworks displays. They are usually well done, their location is quite predictable and once you know where to expect them you can usually find a nice spot to shoot from knowing you'll get some action inside your frame.
Filed under photography

How to upgrade to an SSD with minimal effort

We have all been there - that dreaded family gathering where some relative walks up to you and starts complaining how slow his computer has become and that he needs a new one. In the old days this was a serious problem. They really meant what they said: They need a new computer and you are the only one to make that happen. Go buy and setup a new rig, then spend at least an afternoon installing all kinds of things so the new computer works just like the old one, but moderately faster.

Thank god we got SSDs now, so I can make any computer ten times faster without having to replace the whole damn thing. And there is even a trick how you can migrate from the old hard-drive to the new SSD without you having to reinstall Windows or anything. The trick is to clone the existing drive using a nifty tool called GParted. Here is how it's done:

(It's kind of a long post, but believe me you can do this in less than 20-30 minutes)

Prerequisites

Buy an SSD

Don't waste money on anything fancy. Any SSD will make a PC fly compared to a mechanical drive. So just get a decent drive with the capacity you feel is required and be done with it. (I just got a 240GB drive for 150€ and score a 7.9 in Windows Performance Measurements)

Backup the old Data

As always with disk operations, they might result in lost data if something goes wrong, so please back up any relevant data on the drive you want to copy.

Step 1- Prepare a GParted-Live USB-Key

Get an USB thumb-drive and install GParted-Live using the excellent Pendrive Linux installer. That's simple:

After that it's as simple as selecting GParted in the dialog, pointing it to the GParted iso file and selecting the USB drive letter you want to install your GParted image to.

Step 2 - Delete some data from the original drive

Usually the new SSD will have less capacity than the existing drive (you're usually going from 500GB to 240 or something) so you have to make sure the old data fits on the new drive. Uninstall applications, move data - make sure the used space on your old drive is less than your SSD capacity before proceeding.

Step 3 - Unplug all unnecessary drives

You're going to do some pretty low-level disk operations and any chance you can mess up drive letters is a recipe for desaster. So I like to just disconnect all drives except for the old drive that contains Windows. Just to make it harder to accidentally screw up.

Step 4 - Install the SSD into the computer

Step 5 - Plug in the USB-Key with GParted and boot it

You will soon be greeted by GParted running in a rather hideous Linux GUI.

Step 6 - Shrink the old disk (optional)

If you are trying to fit a bigger old drive onto the new SSD you have to shrink the old partition to a size that's smaller then the new SSD. That's important otherwise you'll screw up the partition table when copying the disks.

Thankfully GParted can do that for almost any file system, even with NTFS. Just select the old partition and shrink it. All partitions together should be less than the new disk capacity - the rest should be unpartitioned space at the end of the disk.

Step 7 - Clone the disk

What you need next is to use GParted to find out the drive paths of your old drive and your new one. This can usually be deduced from their respective sizes, but also the new one should not contain any partitions yet.

Just click the drive path to the top right and you will see a listing of all connected hard drives with their linux mount point (/dev/sda is the first one and /dev/sdb the second etc..)

alt

Once you know the respective drive names, open up the Terminal and run the dd command like this:

dd if=/dev/sda of=/dev/sdb bs=100M

if should point to the old disk and of is the new disk. (if is short for InputFile and of for OutputFile)

Make sure that you get this absolutely right, otherwise you end up cloning the empty disk onto the full disk! Once done just restart the computer and boot once again into GParted.

Step 8 - Grow the new disk.

You are almost done, but you usually have a bit of unused disk space on the SSD left - so you GParted to grow the partition to fill the whole space.

Step 9 - Format the old disk

If you are feeling brave you can do this right away, I like to unplug the old boot disk and reboot from the SSD to make sure everything is working. After you are sure the new SSD boots into Windows, plug the old hard drive back in and boot into GParted again. You should now just remove all partitions from the old disk to free up the space and make sure you don't accidentally boot to the wrong Windows. (Don't worry about new partitions, you can do that from the Windows disk manager).

Step 10 - Reboot into Windows

Done! Unplug the GParted USB-Key and boot the PC. You will be greeted by checkdisk, but once done you should see a very speedy boot into the old desktop. Now you can use the disk-management tool inside Windows to create a partition on the old disk and you are done.

Everything works as before, you just saved yourself countless hours of reinstalling every spyware/malware the relative has accumulated over the last few years.

Filed under howto, computers

dotless v1.4 released!

After a long slump there has been a lot of activity on GitHub going on lately. I've kept myself busy merging the awesome stuff people have been contributing and I am happy to announce we have a new release!

dotless is now able to compile Bootstrap 3 so it seemed like the perfect time to release a new version to users.

You can get the newest version through NuGet or compile it yourself from GitHub. Please give it a spin and report any bugs/problems directly to GitHub.

Disclaimer: The version is called 1.4 because we didn't want to create problems for other packages depending on us and it seems there have been some minor breakages. 1.4 does not mean we have total feature parity with lessjs 1.4.

Again: Thanks for all the contributions. This would not have been possible otherwise - please keep up the great work everyone!

Filed under dotless, .net, open-source

Mongoid gotcha: Id equality comparisons

One quick thing I just ran into in my Rails app with Mongoid:

Ids in model instances are not Strings objects and thus their == method doesn't work against normal Strings.

This means:

@post.id == '51abcb7b421aa90cdf000146'   # always false

will never be true unless you explicitly cast the ObjectId to a string:

@post.id.to_s == '51abcb7b421aa90cdf000146'  # correct comparison

Oh and yes: you shouldn't do things like that anyways in your code - but if you have to - be aware.

Filed under mongoid, rails, mongodb

Moving Ember.js Handlebars templates into the asset pipeline

I am a big believer in not starting out full throttle with things like ember-rails or other crazy asset-pipeline helpers when you have absolutely no clue what you are doing. So naturally when I did my first serious Ember.js application I just went with the basic Ember starter kit and dumped all my templates into script tags in the html.

Well, after getting the basics to work I decided to clean up the mess that was quickly becoming of the HTML and found the wonderful HandlebarsAssets gem that promises to compile Handlebars down to JavaScript and serve it through the Rails 3.1+ asset pipeline. After doing so I can say with confidence I managed to hit every single stumbling block along the way so I decided to write down where I went wrong. Hopefully this helps some other poor soul before he has to dive deep into the bowels of Ember like I had to :).

First step was to move the content of my script tags into a /templates folder inside my app/assets/javascripts and name them accordingly ('slots/create' goes into the file templates/slots/create.hbs etc). Don't forget to require the directory from your application.js manifest file.

Once done the Handlebars compilation part seemed to work perfectly. Only problem: Ember.js doesn't actually care for the contents of HandlebarsTemplates and will just silenlty ignore them. Instead Ember.js wants it's templates to be registered on Ember.TEMPLATES and even more annoying: It won't complain if a template is not registered correctly unless you turned the right arcane debug setting on (yay!)

To actually get Ember to tell you if your templates can't be found you have to turn on debugging through the Ember.Application.create call:

Ember.Application.create({
  LOG_TRANSITIONS: true
  DEBUG: true,
  LOG_VIEW_LOOKUPS: true  //the important part!
});

Now on to get the HandlebarsTemplates into Ember.TEMPLATES:

First I RTFM and HandlebarsAssets has Ember.js support built in, so to enable it you simply create a config/initializers/handlebars.rb file and put the following in:

if defined?(HandlebarsAssets)
   HandlebarsAssets::Config.ember = true
end

And if you did compile your templates before you'll see absolutely no change. Yes that's right, nothing will happen because HandlebarsAssets caches the template output in /tmp. So to actually see your Ember templates show up you'll have to do a rm -rf tmp/.

Hope this helps - I'm now off raising tickets and maybe fixing some of these stupidities.. There is just no real reason for this to be such a piss-poor experience.

Mongoid .length on query ignores limit

I just ran into this and wanted to share this quite puzzling behavior:

20.times { Fabricate(:post) }
Post.scoped.limit(10).length.should eq(10)
# => Test failed
#    expected: 12
#         got: 20

Weird right? But once you look at MongoDB's capabilities and the Mongoid implementation you'll quickly discover that this is only kind of a semi-bug :). MongoDB supports an .count() command that takes a filter and returns the number of matches documents. This command is being issued by Mongoid whenever you call .length on a criterion (since it's much cheaper than executing the actual query and counting the returned objects).

So don't write tests like this:

# method under test:
def self.most_played
  self.order_by(:play_count.desc).limit(12)  
end

# test
it 'returns the 12 most played items' do
  Video.most_played.length.should eq(12)
end

This test will fail, even though the method is doing everything perfectly right. I'd even say that in a regular ActiveRecord setting this would be a passing test. But since I am utilizing the delayed execution functionality of Mongoid most_played method is only returning a Criteria object that represents the query and can be composed into a more complicated query.

This causes .length to be executed on Criteria where it causes Mongoid to call the .count() method instead of running .length on Array. Since limit is no query parameter it will not be passed to MongoDB and the returning count will correctly be equal to the total number of Documents in the collection.

The more correct way to write that test is to actually force Mongoid to execute it's query and count the result:

it 'returns the 12 most played items' do
  Video.most_played.to_a.length.should eq(12)
end
Filed under mongoid, rails, ruby

German programming-friendly keyboard layout for Mac OSX

This may sound totally hilarious to people used to the english layout, but german programmers use shortcuts like Shift + 8 to write a [ and ALT-GR + 8 for a {. (Oh and semicolons are only available through shift - yay for C-style languages!) The main reason for this is that we have these useless little umlauts üöä that sit right where the useful keys for a programmer would be, were it not for the german keyboard.

But after years of arm-twisting and cursing you get used to that and develop a reasonable degree of efficiency even with a absolutely unsuitable keyboard layout. Only problem: these shortcuts are radically different on the Mac! (And breaking the built-in keyboard of your Laptop is not really an option as others suggest)

Instead of Shift 8 for a brace it's ALT + 5, and the backslash is skillfully hidden behind ALT+Shift+6 yuck!

So I tried for a few days and then I decided to stop the madness! Instead of learning to use yet another crappy german keyboard layout I started to use the standard english one. And it's awesome, once you get used to it feels absolutely natural, and it also shows that all programming languages have been written to be easy on people with english keyboard layouts.

Only problem: I was severly handicapped when writing german emails to customers or writing german translation texts. I mean, my friends and colleagues can read written out umlauts (ä = au ..) just fine, but it looks totally stupid when writing something official and well phrased and you are misspelling stuff (ß can be sloppily substituted by ss, but there are cases where ss is orthographically wrong and in other cases ß would be wrong and ss right).

So I investigated and found this wonderful Mac program called Ukulele that allows you to write your own keyboard layout files for OSX. I took the standard US layout and altered it to incorporate the german umlaut keys where they are actually printed on the keys, but only if you hit ALT. So ALT + ; turns into a ö etc..

Here a quick overview of the english layout (notice how conveniently located all those symbols are):

alt

And once you hold down ALT:

alt

Since most people I mention this to usually give me a: "wow that's a really good idea" I decided to simply upload the .keylayout file so people don't have to bother with Ukulele themselves.

You can download the keylayout here: US-daniel.keylayout.

Installation:

Download the file and place it in ~/Library/Keyboard Layouts/, logout and log back into the machine. Now open your System preferences (Sprache & Text) and search for U.S. Tick the checkbox next to it and you can now select the U.S. Keyboard from the OSX menu bar.

Tipp: If you have the screen real estate to share and are still learning the english keyboard layout it's really useful to enable the "Keyboard overview" (Tastaturübersicht anzeigen in german). You can see in real-time what keys are mapped to what buttons on your keyboard while holding down modifier keys.

Filed under osx, programming

Failing silently: Carrierwave ignores store_dir

Carrierwave, my favorite file upload framework of choice in Rails requires something along the lines of 5 lines of code to set up a file upload. The uploader can then be mounted on a model and receive file_field uploads from forms. Especially with the numerous storage backends and the not so common support for ORM frameworks besides ActiveRecord Carrierwave is right on par with other important Gems like Devise.

But then, after having used it upwards of 20 times, just when you think you remember the syntax without having to check the site something unexpected puzzles you:

In my case that was a file upload that was technically working, but seemed to completely ignore the options specified in the uploader. The store_dir was ignored, the different versions were simply never called - but the file upload worked like a charm.

I thought I did everything right (the uploader code looked just fine) and apparently I was uploading files just fine - but it didn't work.

After some investigation and re-doing everything following the getting-started instructions the following code in my model caught my eye:

  mount_uploader :menu_image

Since my uploader was called MenuImageUploader I thought: well that looks reasonable.

Turns out I was wrong (shocking I know) .. Carrierwave requires you to explicitly specify the desired uploader class instead of deducing it from the name.

  mount_uploader :menu_image, MenuImageUploader

Suddently everything started working again, yay. So: If you ever need to just simply upload a file that has no special storage directory or other processing going on - just mount a uploader without a uploader class. Carrierwave will default to Carrierwave::Uploader::Base for you. And if that wasn't you intention - it will still screw you over :).

Maybe I should raise this as an issue with the developers. At least a simple logger.warn would be in order in cases like these.

Filed under rails, ruby, carrierwave