Angular.js CoffeeScript Controller Base Class
I <3 CoffeeScript and Angular.js. Here’s a little technique to make Angular controllers play better with CoffeeScript classes:
Here’s a running example: http://plnkr.co/edit/XqYizAvY5DADziwurgRE?p=preview
Speeding Up Heroku Boot Time for Rails App - Beating the Error R10 Boot Timeout
1 2 3 4 |
|
After tons of boot timeouts of a Heroku Ruby on Rails app (Error R10), it was time to optimize the app.
What I did:
- Removed some gems require on load and required on demand in runtime
To know what gems take the most time to load, I added the following code to
1 2 3
gem 'aws-sdk', require: false gem 'rmagick', require: false ...
config/boot.rb
(thanks to this answer on StackOverflow)watched the app’s log and analyzed the slowest gems.1 2 3 4 5 6 7 8 9
require 'benchmark' def require(file) result = nil puts Benchmark.measure("") { result = super }.format("%t require #{file}") result end
- Made sure no external resource access is made during boot (Redis, Neo4j, Solr) except MySQL which is on RDS and Rails requires this connection on start. To do that, I pointed all resources to non-existing ones and started the app locally. No operation is done with the DB on boot.
- Precompiled all assets locally and pushed to S3 with asset_sync gem (optimized precompilation with gem turbo-sprockets-rails3)
- Moved all asset-related gems into
:assets
group in theGemfile
(jquery-rails
,sass-rails
,coffee-rails
,compass-rails
etc) - Switched to Ruby 1.9.3 - https://devcenter.heroku.com/articles/ruby-versions
- Removed rails_admin from the main app as it adds a few seconds to boot even if initialization is skipped. I’m going to create another, smaller app that’ll contain only rails_admin, its dependencies, models, observers etc.
Result: Heroku boot time less than 30s.
On my local machine I get 15s on production env (including the connection to external DB on RDS), but maybe it’s only because I have a faster CPU than Heroku’s (i7 2.7).
Jastor - Translate JSON/NSDictionary to Typed Objective-C Classes
[ Jastor on Github ]
Jastor is an Objective-C base class that is initialized with a dictionary (probably from your JSON response), and assigns dictionary values to all its (derived class?s) typed @properties.
It supports nested types, arrays, NSString, NSNumber, NSDate and more.
Jastor is NOT a JSON parser. For that, you have JSONKit, yajl and many others.
The name sounds like JSON to Objecter. Or something.
Examples
You have the following JSON:
1 2 3 4 |
|
and the following class:
1 2 3 4 5 6 7 8 |
|
with Jastor, you can just inherit from Jastor
class, and use initWithDictionary
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Nested Objects
Jastor also converts nested objects to their destination type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
Arrays
Having fun so far?
Jastor also supports arrays of a certain type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
|
Notice the declaration of
1 2 3 |
|
it tells Jastor what class of items the array holds.
Nested + Arrays = Trees
Jastor can handle trees of data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
How does it work?
Runtime API. The class?s properties are read in runtime and assigns all values from dictionary to these properties with NSObject setValue:forKey:
. For Dictionaries, Jastor instantiates a new class, based on the property type, and issues another initWithDictionary
. Arrays are only a list of items such as strings (which are not converted) or dictionaries (which are treated the same as other dictionaries).
Installation
Clone Jastor from github: https://github.com/elado/jastor
Copy Jastor.m+.h and JastorRuntimeHelper.m+.h to your project, create a class, inherit, use the initWithDictionary
and enjoy!
REALLY Good to know
Where?s the dealloc in the inheritor classes?
dealloc
is implemented in the base class and it nilifies all properties.
What about properties that are reserved words?
As for now, id
is converted to objectId
automatically. Maybe someday Jastor will have ability to map server and obj-c fields.
Jastor classes also conforms to NSCoding
protocol
So you get initWithCoder
/encodeWithCoder
for free.
You can look at the tests for real samples.
Convert Ruby Hash Syntax to 1.9 (:sym => Value to Sym: Value) on Files
After complaining to our developers about using the old, <1.8’s =>
syntax in hashes, I was challenged by my ninja colleague Avi Tzurel to create a script that will convert all the old Ruby hash syntax to the new 1.9, beautiful colon notation.
I came up with this:
1 2 3 4 5 6 7 8 |
|
The crazy negative lookbehinds ensures that nothing like
1 2 3 4 5 |
|
1 2 3 |
|
will get replaced. Turns out that after return
you can only use the old syntax, or have curly brackets. Also, unfortunately, negative lookbehinds can’t contain Regexp inside them. So the multiple negative lookbehinds are like a big ‘or’.
Our really big project, with hundreds of .rb files, Gogobot, converted and is working great. Still afraid to do the final git push
though ;)
Enjoy!
Isotope - Hybrid Ruby on Rails Template Engine for Client Side and Server Side (Updated)
Update: Jul 23th, 2011
Updated to Ruby 1.9.2 with ArthurN’s amazing fork.
Update: Apr 13th, 2011
Updated API, external script support and fixes.
The problem:
In Ajax-based sites, there’s a constant dilemma: How to get objects rendered in templates? In server side (and output full HTML)? Client side (and mess with JSON objects and HTML strings/DOM generation)? What should be the role division between server and client?
Common Approaches, Pros & Cons:
A few approaches to output a rendered template evaluated with an object are:
Approach #1: Regular ERB Partial
Evaluate a simple ERB partial with a local object, and server it as a string to the client, simply by
1
|
|
in a view, or from a controller and request it by Ajax.
This partial can look like:
1 2 3 4 5 6 7 8 9 |
|
Pros
- Simple, readable and well known ERB for Rails/Sinatra
- SEO and accessibility - HTML code is downloaded into the source
Cons
- Server side only
- Requires download of the whole HTML code, can cause performance issues
- Cannot bind easily to a different object on client side. Must re-rendered in the server-side and be downloaded
Approach #2: Client Side EJS Template with JSON Objects
Having an EJS template in the HTML code, with techniques such as John Resig’s JavaScript Micro-Templating
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Query the server for a JSON article and evaluate the template with this object into a string, and place it inside a container, using a technique as mentioned:
1 2 |
|
Pros
- Fast - requires the server to send only the JSON object and the HTML is downloaded only once as a template
Cons
- SEO and accessibility - HTML code isn’t in the source of the page but being rendered after load
Approach #3: Regular ERB Partial With Marked Spots for Data Place Holders
This approach tries to combine server side and client side but requires a lot of work. It contains a regular ERB template and place holder markers like class names on elements. The template can be first evaluated on the server with a Ruby object and on the client side it can be evaluated with a different JS object (probably from a JSON request).
Template file should look like:
1 2 3 4 5 6 7 8 9 |
|
And then, from a JS function, doing something like:
1 2 3 4 5 6 7 8 |
|
Pros
- One template for both client and server (not really, see Cons)
- SEO and accessibility - HTML code is downloaded into the source
Cons
- On the client side - Must mimic the Ruby functionality with JS when it comes to loops, conditions etc. However, text values are pretty easy to embed. This code should probably written manually for everything that is not a simple textual content.
- Must maintain data place holder markers
So…
In these three approaches, the developer needs to choose according to the task and the project requirements, or worse, maintain two templates, ERB and EJS.
Each approach is written in a totally different way, and switching between the approaches means a lot of work.
Introducing: Isotope - Ruby Hybrid Template Engine for Client Side and Server Side
So why not combining all the pros of the approaches together?
The biggest constraints to be considered are:
- Client side doesn’t understand Ruby
- Ruby can’t be translated fully into JavaScript
- And the most important one: Template should be maintained in one single file for both client and server uses
Isotope is from greek - “Equal Place”. An equal place of editing a template for both client and server (Thanks @yuvalraz for the name!).
Using jbarnette’s AWESOME Johnson gem, Ruby and JavaScript can interact together!
That means, that ruby code can handle EJS templates and JSON objects. A great and very inspiring article is Write your Rails view in? JavaScript? by Aaron Patterson.
In this approach, only one template is written and maintained in an EJS format, for both client side and server side.
Usage
Isotope gives the ability to have a single template file, and easily switch between the approaches:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
On the Client Side
Outputting from the server side (controller or view)
1
|
|
The above code will output:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
which is easy to evaluate with any JS object using the mentioned technique.
On the Server Side (The Holy Grail)
Using Johnson, the famous micro-templating technique and JSONed Ruby objects, this library provides the following functionality:
1
|
|
This code reads the source of the EJS file, uses Johnson and John Resig’s technique and serves a string as an output.
Configuration
External JS files can be included in order to have special functionality in the EJS templates, on both client and server. To include files, create a config/isotope.yml file and fill this array, relatively to the app root:
1 2 |
|
And in order to have it available on client side, put this line before the close:
1
|
|
Scripts will be automatically included in server side.
Scripts and templates are never cached on development environment.
Installation:
1 2 |
|
1 2 |
|
Rails
Rails 3.x
Add to your Gemfile
1 2 3 |
|
and run bundle install
Rails 2.3.x
Add to config/environment.rb
1 2 3 |
|
and run rake gems:install
Add to config/environment.rb
require ‘isotope’
Server Side Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Or, with a view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Client Side Example:
1 2 3 |
|
Sinatra
Actually the same usage, more or less.
Run Tests
Install rspec (gem install rspec)
1
|
|
Launch sample Rails app
1
|
|
and go to http://localhost:3000
Development Tip: Realtime Code Backup With Dropbox
Backups are important. But usually they are made daily or even less often than this.
Quick tip I wish I had known a month ago when my MacBook froze and didn’t boot after a fruitful, productive day: backup all the code in realtime, all the time, with Dropbox.
Every CMD+S sends the file to Dropbox, and that means, that if something terrible happens to my computer (can’t boot, coffee accident, or it gets stolen), I know that all my code is backed up to the latest save.
That doesn’t even mean you should put your code directory inside the Dropbox’s one, you can Symlink it, excluding big files that don’t need to be backed up, or if you’re short on space.
A template I use for Rails projects w/ Git, excluding the tmp, log and other irrelevant folders:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
If you still don’t have a Dropbox account, you can use my referral link: Create Dropbox account or create a new account without my referral here.
Tree Rendering in Client-Side, No Recursion
I once built a nested message board (using ASP & VBScript, bah). In order to print all messages, nested, I created a recursive function that queries the DB for all messages of a certain parent, prints the messages and calls the same function itself with parent ID of the current message. That was a disaster to the server, as a single page could execute about 100 queries.
I decided to move the rendering logic to the client side, since SEO wasn’t such a big of a deal for this, and the load time was critical. So at first I queried the messages I wanted (I could do this in one query thanks to the DB structure), I pushed the data to JavaScript, as a flat, unordered array of objects, using JSON:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
The first approach to print this, nested, is using a recursive function in JavaScript, that, on every call needs to find the child messages based on their parentId
, and actually mimic the server behavior (loop on root messages, query child messages, print, recursively).
But a way cooler approach, is to utilize the DOM itself for nesting, and to utilize a hash table indexer to store and find messages based on their id.
After creating all elements for all messages, a hash table (associative array, or just a JavaScript “object”) can be used to store a node based on its id, so when we want to find it, we can just use nodesById[someNodeId]
:
1 2 3 4 |
|
Then, the magic of having all elements nested happens when looping on all nodes. Each node has a parent_id
except root nodes. We need to find the parent of current node in the nodesById
object, by using nodesById[nodeParentId]
, and append the current node to its parent we found. Root nodes appended to a root container.
1 2 3 4 5 |
|
That way, we utilize the DOM for native nesting, without a recursion, and a simple single loop. The array doesn’t even have to be ordered, and no worries about requesting a node when its parent isn’t exist, as all of the elements are already created before.
The Entire Code
[iframe: style=“width: 100%; height: 860px” src=“http://jsfiddle.net/elado/yxmKZ/embedded/js,css,result”]
Mac OS X, I Love You but You?re Bringing Me Down
I’ve been using Mac OS X for a almost two years. I like it, I really do. But there are a lot of things that drive me crazy. At least in the native/default configuration:
- You cannot rename/move/copy files in a save dialog. And you cannot open the enclosing folder to do so. You must open Finder yourself and look for that folder. This should be useful if you just want to replace a file but maintain the original in a different name.
- On that same file dialog, you can’t paste a web URL (http), which means, that if you want to open a file from web you must first download the it and then open it manually.
- You can’t delete a single file from trash. What happens if you just want to destroy evidence of something?
- Sometimes (e.g. in Chrome), when I mark text, it forgets where I started to mark from and where I ended. If I change the mark using Shift+Arrow/Shift+Click elsewhere, it either enlarges the selection when I wanted to subtract, or vice-versa. It should always proceed from the place the last mark was stopped at.
- When multiple windows of the same application are opened, a click on the dock icon brings them all to front. Same for cmd+tab menu. To me, it seems it happens because of poor window management. When I have a lot of Finder windows it’s very annoying. Partial solutions: HyperDock (for dock) and Witch (for alt+tab between all windows, not apps)
- You can’t cut & paste files. As time goes by I see how I really need it. Imagine you wouldn’t be able to cut & paste text, but only copy-paste-delete. Solution: TotalFinder
- You can’t merge folders. Drag / copy&paste of a folder named A, onto a folder which contains another folder named A, will totally remove the second A and replace it by the first one. The only way to merge is to use Terminal or an external tool.
- If your Finder window with Details view is packed with files, you can’t create a new folder with the right click menu unless you either enlarge the window, to get space below the files where a right click have New Folder command or use shortcut/main menu. On Windows - right click would work after the last column because a files don’t spread over an entire line.
- In details view, with a tree of files opened (great feature!), when pasting a file it’ll paste it to the top most directory you’re in, and not the one you marked.
- In native apps, if a text field is disabled, you can’t select the text in it at all.
- Several applications require you to right click on their dock icon in order to open them. For example, Adium: when the contact list is closed and there’s a conversation opened. True, it’s also Adium’s fault, but it’s more a window management UI issue.
- Deleting a file on the Finder (cmd+Backspace) clears the selected file. If you want to go to the next file with the down arrow - it’ll start from the first file on the top of the list. It should remember the location of the last deleted file and focus on the one that was next to it (or previous if it’s the last file).
- You must use Terminal for lots of advanced configurations. They don’t appear on System Preferences. Things like “Show hidden files” and more.
- No editable address bar in finder. ‘Go to Folder’ doesn’t count. It would, if it was showing the full current address of a window, but it shows only the last accessed path. Again, only terminal can make things easier.
- The Preview application won’t let you navigate through files in the same directory, unless they were all opened together initially.
- Weird and inconsistent Home & End buttons. I want it to go to the beginning/end of a line and not the top of the document. Several applications use the first approach and others use the second one. Solution: KeyFixer
- No Right-Click+Dragging (used for copy/move/extract etc.)
- Cmd+N in a Finder window opens the home directory. But most of the times I used it, I meant to duplicate the same window. Solution: TotalFinder
- Windows are resizable only from one corner. That means, that if a window is “stuck” on a size that is bigger than the screen, it cannot be resized, and you’re probably doomed, because most apps remember their size/location. It happend to me more than once after plugging off an external screen. Solution: Divvy
I guess that most of the users don’t need all of these, but I’m sure I’m not the only one complaining about them. Apple might want to protect the general users, and their approach seems like “We are way smarter than you”. But why don’t they create “Advanced Mode” for developers and advanced users?
I still use it because of the full native support for Ruby on Rails, Apache, iPhone development and such, but sometimes, I miss Windows 7.
Links^2 - December 13th, 2010
- MooTools 1.3 by Ryan Florence - A comprehensive guide
- Maki - A free web design mock-up tool for pixel perfect layouts
- CSS Animations - A transition framework that utilizes CSS3 animation abilities
- ImageOptim - Optimizes images so they take up less disk space and load faster by finding best compression technique
- CSS: CamelCase Seriously Sucks! - Well put
- What?s new in JavaScript 1.8.5 - Well, mostly to be used under Server Side like Node.js
Links^2 - November 16th, 2010
- Shoulda.js - A test framework for JS, inspired by Shoulda for Ruby
- Understanding JavaScript Closures - Great one!
- Slim templating engine - and I thought Haml was cute….
- GitX - Git GUI for Mac OS X
- easyXDM - Cross domain requests with JavaScript, works on all browsers (but implemented differently for each)
- Moock - A test-suite agnostic JS stubbing library