@yorzi

great people share knowledge

Fork me on GitHub

Downloadable SVG in PNG Format

Recently, I worked on some interesting features, we use Highcharts and/or Raphaeljs to build complex charts, including bar chart, scatter chart or heat map, etc. In an extreme sample, we build a complicated one-page charting engine by which user is able to compose a group of conditions and then render a meaningful chart according to what are selected. It’s pretty cool.

Meanwhile, client is willing to download these generated charts on individual chart level. They also want to have an ability to share the individual chart as a link or even as a piece of HTML code. What’s the best solution to add these functionalities? Well, we did try many solutions for the features, let me show you how we make it finally.

Start from a HTML template

Above HTML code is the generated content on my page, I will mainly explain the solution based on it. Here is also a sample SVG file: sample.svg, you can use it to go through the whole senario if you want to experiment by yourself.

Deal with SVG via HTML5 Canvas

HighCharts and Rapheal are JS libaries by which you are able to generate complex SVG charts, normally, people can not download a svg file directly, and it’s also not a popular image format for sharing around. We’d better convert it to a PNG or JPG image, as PNG and JPG format is downloadable from web page. I will take PNG format as a sample in this post.

How to convert a SVG image to a PNG image? Mainly, you can do the convertion job from server side. There is a SVG toolkit provided by Apache which is named as Batik. But I don’t like this solution, it’s a bit comoplex to install Batik and make it work with Ruby on Rails. I’d like to work the convertion out via pure javascript. Yes, use canvg to move all SVG information to a HTML5 Canvas object.

Using the HTML5 canvas element, you can create all sorts of cool graphics client-side on the fly using Javascript. There is a neat function on the the canvas object called toDataURL(). This functions encodes the image data as a base64 encoded PNG file and returns it as a data: URI. By using the data:URI string, you can make it a downloadable PNG file.

There is also a libary to help you do so, it’s Canvas2Image that can convert canvas to image as BMP, PNG or JPEG format.

Customize default filename while downloading

Canvas2Image lib will implement a pop out window to allow you download the data:URI as a PNG image file with a default name download, which is not acceptable by our client, I have to figure out a way to customize the downloadable filename.

It might be easy if you just want to cover your Chrome or Firefox user, as there is a download attribute for <a> tag, when you set it as something like <a src='the data:uri string' download='test.png'> then you will get the default filename in this the case when you click the download link.

I am not lucky, I have to cover IE9 at least. So I need to push the data:uri to server, then I can render the data with specific headers(see below code), that will make the downloadable file with a customized file name.

Pay attention to above html2canvas([$(".hidden_container")[0]],{ … }) parts. It helps to convert whole HTML code to a canvas based on html2canvas lib, that’s our case as we have to wrap up some HTML code out side the the charts.

A trick to overcome IE9 issue

When you work on IE9, the canvg fails to translate the SVG to Canvas, it seems IE9’s DOMParser() is not able to parse the SVG successfully. After some search from Google, we found only one line code will resove the SVG parser issue. Just replace some invalid string in SVG data as below:

Conclusion

To summarize this post, you are suggested to use several JS libs above to convert SVG to Canvas, then convert Canvas to PNG file, if you also want to customize a piece of HTML code out side the SVG chart, then you are able to convert HTML to Canvas, then again from Canvas to PNG, when you want to set a customized filename for the generated PNG file, you have to send the data:uri string onto server side, then rewrite the response headers, all these handling will implement a downloading feature for you.

Run a Static Website on Heroku for Free

Andy Wang - Professional Ruby on Rails Engineer, Senior Web Application Developer.
Uploaded with Skitch!

Recently, I plan to update my personal information on internet, I also plan to have a professional personal website on which I can show my introduction, skills and working experiences. I guess it will introduce me to the world in a cool way.

Well, first of all, I bought an awesome template on wrapbootstrap, where all pretty templates are built on Twitter’s BootStrap, I guess everyone loves BootStrap, who doesn’t?

Once I get the simple static HTML template for website, I am going to deploy it to Heroku for free. We know Heroku deliveries their popular cloud hosting for Ruby on Rails, Node.js and other framework. How does it work for static HTML website hosting?

I found that, we actually can build s simple Rack application to run the static website on heroku. But how? See below:

  • Add Gemfile to require the rack gem for the website.

source 'http://rubygems.org' gem 'rack'

  • Add config.ru file in root folder of the website, this will enable the Rack handlings.

“` $stdout.sync = true

use Rack::Static, :urls => [“/font-awesome”, “/js”, “/img”, “/style”], :root => “.”

run lambda { |env| [

200,
{
  'Content-Type'  => 'text/html',
  'Cache-Control' => 'public, max-age=86400'
},
File.open('index.html', File::RDONLY)

] } `` - AddProcfile` in root folder to config the heroku web server and worker(if there is any).

web: bundle exec rackup -p $PORT

Ok, now it’s ready to deploy the whole website to Heroku, here is a detailed document that can help you to deploy a codebase to Heroku. Meanwhile, you are allow to customize your domain for any app running on Heroku, here is also a docment for this purpose on heroku help center.

Easy, right? I’ve run my awesome personal website on wangyaodi.com according to above steps, give it a look if you are interested in it. You are also welcomed to fork its source code on github. Enjoy it!

Now My Blog Is Running on Octopress

Octopress

Octopress is owesome!

Last time I tried to migrate my wordpress blog to Jekyll, then I failed to find some beautiful theme. And when intridea cn blog was built using nanoc, I’d like to give it try, you know, I still gave nanoc up as I can not make the theme pretty by myself.

Days ago, I came across the octopress, I totally fell in love with its convenience and cool blog theme. I spent several hours to move my blog to github this afternoon. Oh my, Now I can write blogs in Markdown and deploy it to github.

Octopress has its official website with many valuable materials to help you get start and doing other regarding interesting things. Cool, hah? Try it out now!

Riding on Rails3 With Full Stack of Gems

NOTICE: Below post was released a month ago on Intridea Company Blog, also post here as a backup.

It’s been close to a year since Rails3 came out. Luckily, I’ve worked on several Rails3 projects after it’s released, so I’d like to share a stack of gems that I used in my previous projects. I guess they will give people a bit help while developing a new Rails3 app.

I don’t want to explain too much on these gems separately, well, most of the gems have good documents on their project wiki(every great gem should be well documented, right?). Instead, I just add regarding links to their repos so that you’d better take a further look while you really use it. In order to introduce the lists of gems clearly, I simply categorized them based on a rough structure.

Ok, here we start:

» Authentication

The above two are really amazing gems to speed up your authentication. Yes, I love both of them in different cases: ideally OmniAuth is better for applications which want to support multi-provider external authentication, so I’ve just added OmniAuth into RefactorMyCode Rails3 branch to take its auth benefits; Devise is totally powerful enough for classic authentication case. However, if you have too much your own business logic inside your login/registration/auth flow, you definitely need to make your own authentication.

» Access Control

Ryan is a star in Rails world, so his CanCan is really popular, which aims to do neat but powerful authorization. However, the declarative_autharization is also an option, actually, Ryan mentioned CanCan was inspired by declarative_autharization.

» Views/Page and Admin Scaffold

From a front-end perspective, I suggest you might need to try above gems to speed up and simplify your UI designing. For example on the admin section, it’d be great if you can apply your CRUD quickly to pages, that’s what rails_admin does. Surely, these gems won’t end all your UI problems, but it really helps when you doing prototype or being lack of some real designers.

» Quick SNS

Well, I don’t mean a whole solution of SNS or regarding feature, here theses gems can help you add the basic cross-object function rapidly, it increases your confidence to focus on designing over programming at the very beginning. Here I want to give a simple introduction to acts_as_favable, it allows for favorites refer to be added to multiple and different models.

» Form and Related Tools

Most of above gems are famous through <railscasts.com> created by Ryan. There are two pairs of options here: simple_form and formtastic / paperclip and carrierwave. I like all these solutions, you should pick up one to fit your project, if you want to know differences between each pair, get more details on their wiki :) Tiny is an HUGE gem for rich editing, I list it here to remind its exist, but I recommend you get the WYSWYG via some JS lib like CLEditor, it works gracefully.

» Searching Solutions

Talking about searching in rails, I think you have many words to say. Here I wanna roughly split these gems into two types: Object-based searching and Full-Text searching. I heavily recommend you use meta_search and/or meta_where as your model based searching, it can convert your form params directly to a search solution, that’s convenient. Full-Test searching depends on your case, but all these three gems(thinking-sphinx, acts_as_indexed, sunspot) are great.

» Pagination

No more will_paginate in Rails3, absolutely, the only option is kaminari.

» Background Work

There is one post to introduce resque clearly here, in that post, github staff mentioned their brief history of doing background jobs, so I think you can understand well the differences between delayed_job and resque solution.

» Status Machine

I like to use workflow a bit more, since it’s much natural to me, you definitely need one status machine to control your stable flow stuff, such as a registration flow status or a wizard-like features.

» Rack API framework

This gem is for adding API to Rails/Sinatra application. Michael gave people an awesome speech in RubyConf2010 on his Grape, here I suggest you should watch it to know more details about GRAPE. I believe you will fall in love with it.

» Memcached Client

These two gems are actually mainly written by one same author Mike Perham, he mentioned that Dalli is a high performance pure Ruby client for accessing memcached servers. It works with memcached 1.4+ only as it uses the newer binary protocol. It should be considered a replacement for the memcache-client gem. The API tries to be mostly compatible with memcache-client with the goal being to make it a drop-in replacement for Rails.

» Deployment and Monitor

I am not a system administrator, so every time talking about the regarding aspects will make me feel silly, I just try to describe tools which can help me out on unfamiliar area, that’s not bad, at least people like me, will do deployment and monitor quickly based on these gems, they do help.

» Cron job and Backup as a Pro

Above two gems are my favorites, before knowing these two gems, I have to write complex and stupid scripts to do backups that I am not familiar with. Cron job is also a pain in ass if you are not a system administrator. Now time changes, you, as a ruby programmer, can do the corn job and backup in ruby way, surely as a PRO. :)

» Testing Gracefully

Testing is always important, I know TDD and BDD are getting more and more popular, that means you have to own your super gun to make it happen. Right, here is a list of gems which can help you out, I didn’t cover all different levels of testing with these gems. Point is, rspec is my favorite framework for testing, factory_girl and faker are good supports. Anyway, test by your way.

» Toolkit

There are many handy gems which will give you convenience and power. Take above four as examples, ruby-debuy gives you a chance to check your running applications’ context at specific program point; hirb display your AR items in table view in console; cheat makes your terminal working as a pool of other gems’ manual; rails-settings-cached is for global configurations in Rails3 application. Yeah, throwing the brick out is to meet your GEMS.

How to find great gems?

First, you need to follow up Ryan’s railscasts, he is good at introducing new stuff in video. Second, you can go through great open source project’s Gemfile, yeah, it’s definitely the best way to come across valuable gems. Third, just subscribe github ruby trends to know what’s going on in Ruby/Rails community. There are also some other involving sites, like rubygems and railsplugins, you should take a glance when you free, I bet you will find useful gems.

It’s nearly the end of this post, this topic was originally shared with all Intridea China Team members during last Friday Teahour. You can find the PPT here. To share with more people, I turn it into this blog, I must miss many valuable gems in this list, so please comment your thoughts.

Weekly Updates : Javascript Rocks!

After quit from Idapted/Eleutian, I’d like to have a long term plan for writing blogs. However, as everything starts, it’s always hard. I thought it around, and finally decided to open my mind, and just try to start with a strong belief : Sharing! Then an idea comes out.

First of all, I think my weekly updates will help to share great things I came across or even I started to use, it has much fun to replay all these stuff, so I will do that in the weekend, that’s also part of my study review.

Ok, turn to the points:

  1. Now you must know JSLint. JSlint is a Javascript checker, which can help you ensure your JS’ quality. There are many great open source projects helping you to program in Javascript.

Sources: Github Proj: https://github.com/douglascrockford/JSLint Add JSLint to you TextMate: https://github.com/subtleGradient/javascript-tools.tmbundle

  1. Are you familiar with BDD? You should start to learn it now if you did not have a change to give it a try. Specially, if you are using Ruby/Ruby on Rails, I strongly recommend you try rSpec for the BDD. Back to the topic, I wanna share with you some similar BDD way in programming Javascript, jspec and Jasmine, obviously, they are cool. I just mention this as a reminder people who want to try interesting programming. I didn’t try them yet, but I guess I will do that in soon.

  2. JS in real-time application Node.js and NowJS

  3. Books to speed you up! • Javascript: The Good Parts (http://oreilly.com/catalog/9780596517748) • JavaScript Patterns (http://oreilly.com/catalog/9780596806767/) • High Performance JavaScript (http://oreilly.com/catalog/9780596802806/)

Javascript is a long journey, I am just on the start point. Anyway, exciting!

JS Note: setTimeout and setInterval

Yesterday, I discussed a JS issue with Blade, that I have to set up an automatic photo-switch effect on an existing page. I don’t want to change anything except adding a piece of javascript for doing that job because this page is already messy up by another engineer. Blade suggested I should use setTimeout for this effect.

* Case Study

The basic case is something like below(there are some other effects based on the structure and style, so don’t affect others):

会议城市:海口

时间:8月26日 14:00-18:00

地点:海口鑫源温泉大酒店

Now the task is to write a js to roll the cities and regarding images, how to make it happen?

* Solution with setTimeout

Actually, you can figure out this effect with setInterval as well. The difference between setTimeout and setInterval is how many times you want to run the function which is set as their parameters. setTimeout will execute the function only once when time is out. But setInterval execute the function repeatedly in certain interval which is set as a parameter.

Every time you should remember to clear the Timeout or Interval after finish your job through clearTimeout and clearInterval.

I have linked the regarding references for the four methods about, you should read the document and related samples to know more details.

More Resources: 如何在jQuery中使用 setInterval,setTimeout jQuery:Tab切换功能的集合

Real-Time Application With Rails3

I researched a little bit these two days about Real-Time Application(RTA), I found many useful solution to build real-time application.

First, a RTA is an application program that functions within a time frame that the user senses as immediate or current. The latency must be less than a defined value, usually measured in seconds. The use of RTAs is called real-time computing (RTC).

There are some example use cases of RTAs, including:

   * Videoconference applications
   * VoIP (voice over Internet Protocol)
   * Online gaming
   * Community storage solutions
   * Chatting
   * IM (instant messaging)

Mainly, I am interested in two solutions, which are Cramp based RTA and a NR2J(Node.js+Redis+Juggernaut+Jquery) solution, both of these two solutions have existing samples, I suggest you should go through all of them to understand RTA well.

Cramp based RTA Cramp is a ruby web framework with asynchronous feature, which is always running inside EventMachine reactor loop, there is a detailed introduction for it. A sample code is available here.

NR2J solution Introduction is here and sample code is here. I tried Node.js before, it’s getting popular recently, but I still don’t be used to implementing server side code with JS. I love Ruby and Rails anyway.

Other RTA resources: Real-Time/WebSocket/Rails3: http://laktek.com/tag/realie/ JSChat.org: http://jschat.org/

Zen Coding for TextMate

Bundles make TextMate as a super Editor, so if you love TextMate, you must love colorful bundles based on it.

I just find an interesting bundle to speed up your HTML/CSS coding, which is named as Zen Coding.

The core of this plugin is a powerful abbreviation engine which allows you to expand expressions—similar to CSS selectors—into HTML code. For example: div#page>div.logo+ul#navigation>li*5>a …can be expanded into:

The sytax is simple to understand, there is a sytax list here. You can also get more details about this bundle on its official site.

Enjoy it.

Dalli on Rails3

Today I tried a new pure Ruby memcahed client in one of my Rails3 projects, it’s named as ”Dalli”. It’s an excellent memcached client as Mike Perham announced in August last year. You can detect more details about it on its code. Dalli is just faster performance than memcache-client and easy to use in Rails3 or on Heroku.

Make sure you’ve installed 1.4+ memcached on your machine, then you can configure Dalli as what you did with memcache-client before: 1. add gem in Gemfile gem 'dalli' 2. Config the underlying cache store as dalli_store in production.rb

Memcached is delaulted on port 11211.

config.cache_store = :dalli_store, 'localhost:11211' 3. Now you will find the Rails.cache class is changed to Rails.cache.class:

Rails.cache.class == ActiveSupport::Cache::DalliStore 4. You can use it easily in you Rails3 application class Food < ActiveRecord::Base after_save :expire_food_caches

def self.all_view_types

  Rails.cache.fetch("food_types") do
      Food.all.map{|s| s.view_type}.uniq
  end

end

protected def expire_food_caches

   unless Food.all_view_types.include?(self.view_type)
       Rails.cache.delete("food_types")
   end

end end Note: Rails.cache.fetch() with a block will return the cached value if it exists, otherwise it will return the value and write cache with the value at the same time.

Resource about Cache: Scaling Rails :
http://railslab.newrelic.com/scaling-rails Caching with Rails :
http://guides.rubyonrails.org/caching_with_rails.html ActiveSupport::Cache::Store :
http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html#method-i-clear ActiveSupport::Memoizable :
http://ilstar.blogbus.com/logs/84754288.html#cmt