Monday, April 29, 2013

Interactive CoffeeScript from Command Line

Here's how to install the CoffeeScript interpreter and test a ternary operation.


$ npm install -g coffee-script
npm http GET https://registry.npmjs.org/coffee-script
npm http 200 https://registry.npmjs.org/coffee-script
npm http GET https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.2.tgz
npm http 200 https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.2.tgz
/usr/local/bin/coffee -> /usr/local/lib/node_modules/coffee-script/bin/coffee
/usr/local/bin/cake -> /usr/local/lib/node_modules/coffee-script/bin/cake
coffee-script@1.6.2 /usr/local/lib/node_modules/coffee-script
$ coffee -h

Usage: coffee [options] path/to/script.coffee -- [args]

If called without options, `coffee` will run your script.

  -b, --bare         compile without a top-level function wrapper
  -c, --compile      compile to JavaScript and save as .js files
  -e, --eval         pass a string from the command line as input
  -h, --help         display this help message
  -i, --interactive  run an interactive CoffeeScript REPL
  -j, --join         concatenate the source CoffeeScript before compiling
  -l, --lint         pipe the compiled JavaScript through JavaScript Lint
  -m, --map          generate source map and save as .map files
  -n, --nodes        print out the parse tree that the parser produces
      --nodejs       pass options directly to the "node" binary
  -o, --output       set the output directory for compiled JavaScript
  -p, --print        print out the compiled JavaScript
  -s, --stdio        listen for and compile scripts over stdio
  -t, --tokens       print out the tokens that the lexer/rewriter produce
  -v, --version      display the version number
  -w, --watch        watch scripts for changes and rerun commands

$ coffee
coffee> name = "Activities"
'Activities'
coffee> a = if name==\"Activities\" then true else false
repl:1:15: error: missing ", starting
a = if name==\"Activities\" then true else false
              ^
coffee> a = if name=="Activities" then true else false
true
coffee>



References

Little Book on CoffeeScript
http://dailyjs.com/2011/05/30/code-review-coffeescript/



Sponsor Ads(Please visit one if you liked this article. Thanks!)

Tuesday, April 23, 2013

Online Business Risk Mitigation

First, let's look at what makes a business risky and unattractive to merchant account underwriters.

  • No financial and processing history
  • Stored value sales and accounts
  • Open ended time of use
  • Long Settlement Lag Times
  • High (over $500) ticket sales
  • High risk industries (travel, gaming, adult, liquor, online dating, debt consolidation, credit repair, and bankruptcy attorney)
  • Annual Billing, Lifetime Memberships, retainers and aggregation

Groupon


Now, let's look at an example, Groupon.  Groupon's business model as explained in Groupon’s site: “Each day, Groupon emails its members one unbeatable offer on something great to do in your city. We offer consumers great values by guaranteeing businesses a minimum number of customers. If a certain number of people sign up, then everyone gets the Groupon offer. If that minimum isn’t reached, then no one gets it.”

Here's what the merchant account underwriter gleaned from Groupon's own business model explanation:

  1. Groupon is selling other businesses' products and services that are easily contacted by the consumers who can then negotiate a better deal than Groupon can offer.  
  2. Groupon has a lot of competition from other online companies like Amazon.com, Expedia and Priceline.
  3.  Groupon sells mostly discretionary products and services that are more difficult to market and sell.


Groupon has little bargaining power with providers and a low barrier of entry from competitors which makes its business model unsustainable and unattractive.

Merchant Account Assessment

Since merchant account providers are ultimately financially liable for merchant losses, their underwriting and risk management team carefully assess each merchant account.

Merchant account providers would be financially liable if a merchant sold a lifetime membership but then went out of business within a few months.

Merchant Account Providers can mitigate risk by several means:

  • Reserving a percentage of sales for a specified period of time in an FDIC insured bank account, during which time the merchant proves their credit worthiness
  • Requiring an upfront reserve deposit
  • Requiring a personal guarantee

Online Merchants Risk Mitigation

Online businesses can make improve their attractiveness by:

  • Adopting a viable business model
  • Building a processing track record of low number of charge backs
  • Providing better user experience than their competitors with innovation/better technology and customer care
  • Selling high quality products and services with satisfaction guarantees
  • Clearly communicating terms and conditions
  • Fast and efficient problem resolution processes

References

http://www.forbes.com/sites/panosmourdoukoutas/2012/08/14/groupons-problem/

http://publicintelligence.net/glossary-of-terms-related-to-payment-clearing-and-settlement-systems/


Sponsor Ads(Say Thanks! by clicking an Ad)

Saturday, April 13, 2013

Localize Currency and I18N String Interpolation

number_to_currency is new to Rails 3.2.13

I found it necessary to specify the currency format options for each locale, which I put in separate .yml files, but you can put all of them in one .yml file for testing.

Open the rails console and include the NumberHelper class

>> include ActionView::Helpers::NumberHelper
=> Object

>> number_to_currency(1234567890.506)
=> "$1,234,567,890.51"

>> number_to_currency(1234567890.506, :locale => :en)
=> "$1,234,567,890.51"

>> number_to_currency(1234567890.506, :locale => :en_gb)
=> "1,234,567,890.51 £"

>> number_to_currency(1234567890.506, :locale => :fr)
=> "1 234 567 890.51 €"

>> number_to_currency(1234567890.506, :locale => :br)
=> "R$  1.234.567.890,51"

Locale yml File(s)


en:
  hello: "Hello world"
  hello-you: "Hello %{name}!"
  inbox:
    counting:
      one: You have 1 new message
      other: You have %{count} new messages
      zero: You have no messages  
  greetings:
    hello: "Hello"
    hey: "Hey"
  number:
    currency:
        format:
          significant: !'false'



fr:
  hello-you: "bonjour %{name}!"
  number:
    currency:
      format:
        format: "%n %u"
        unit: "€"
        delimiter: " "
        

en_gb:
  number:
    currency:
      format:
        format: "%n %u"
        unit: "£"

br:
  number:
    currency:
      format:
        format: "%u %n"
        unit: "R$ "
        delimiter: "."
        separator: ","


String Interpolation

You can build your I18N strings dynamically, assuming your .yml locale file is setup properly.

>> I18n.t("hello-you", {name: "John Doe"})
=> "Hello John Doe!"

>> I18n.t("inbox.counting", {count: 10})
=> "You have 10 new messages"

>> I18n.t(["greetings", "hello"])
=> [{:hello=>"Hello", :hey=>"Hey"}, "Hello world"]

>> I18n.t("hello-you", {locale: :fr, name: "John Doe"})
=> "bonjour John Doe!"

References

http://webdesign.about.com/od/localization/l/blhtmlcodes-cur.htm
https://github.com/fnando/i18n-js
https://github.com/jquery/globalize


Sponsor Ads(Say "Thanks!" by clicking the Ad below)

Thursday, April 11, 2013

What Makes a Single Page Web Application Scalable and Robust?


I'll start off by describing what I consider not scalable and robust.... A monolithic web application, where all of its resources (css, javascript, etc) are loaded and stay loaded from the entire life of the application instance.

So, one thing that would make an enterprise web application scalable and robust is the capability of loading and unloading portions of the application as appropriate to reduce resource, e.g., memory, consumption. It's very possible to a region of the window from the user's view, but have all of it, or portions of it remaining around in memory because there is still a reference that is holding on to it, e.g., a javascript object, html elements, etc.

  • Memory Management

4/12/2013

I'm back with another key element of a scalable/robust application...

The ability of one application component to publish messages to the message buss and for other components to listen/subscribe to those events and subsequently act on them.

  • Messaging Bus


Keeping logic for one area of concern in on module or several submodules, each with their singularly particular purpose.

  • Modules and Sub Modules


Decoupling the responsibility of one component from others.

  • Encapuslation


A dispatcher that directs interactions between the Model and View layers.

  • Controllers


I'll come back to this page to add more later.

Request for Information

In the meantime, what else can you think of? (please post in comments)

Sponsor Ads(Say Thanks! by clicking the Ad below)

Monday, April 8, 2013

Open a File with the Xcode Editor from the Command Line

Add the following alias to your ~/.bashrc (or ~/.bash_profile)


alias xcode='open -a /Applications/Xcode.app'


Run following to make the new alias available in the current shell/terminal window.


$ .  ~/.bashrc


Use it to open a file in iTerm


$ xcode readme.txt

References

http://developer.apple.com/library/mac/#documentation/ToolsLanguages/Conceptual/Xcode_User_Guide/000-About_Xcode/about.html



Sponsor Ads(Please visit one if you liked this article. Thanks!)

Friday, April 5, 2013

Ruby String Interpolation

Use a combination of the eval command and the #{ } idiom to get the values of Logger constants.


>> Logger.constants.each {|i| puts "Logger::#{i} = " + eval("Logger::#{i}").to_s}
Logger::VERSION = 1.2.7
Logger::ProgName = logger.rb/31641
Logger::Error = Logger::Error
Logger::ShiftingError = Logger::ShiftingError
Logger::Severity = Logger::Severity
Logger::SEV_LABEL = ["DEBUG", "INFO", "WARN", "ERROR", "FATAL", "ANY"]
Logger::Formatter = Logger::Formatter
Logger::LogDevice = Logger::LogDevice
Logger::Application = Logger::Application
Logger::SimpleFormatter = Logger::SimpleFormatter
Logger::DEBUG = 0
Logger::INFO = 1
Logger::WARN = 2
Logger::ERROR = 3
Logger::FATAL = 4
Logger::UNKNOWN = 5



References

http://lexsheehan.blogspot.com/2013/04/temporarily-disable-executed-sql.html http://en.wikipedia.org/wiki/String_interpolation



Sponsor Ads(Please visit one if you liked this article. Thanks!)

Temporarily Disable Executed SQL Command Output in Rails Console

When trying to get a nice, clean list of locations to copy/paste, I had the need to temporarily disable SQL command output in the Rails console.

Here's how I did it...

Run command with default ActiveRecord (AR) logger settings


>> Location.where('ancestry is null').size
   (0.6ms)  SELECT COUNT(*) FROM "locations" WHERE (ancestry is null)
=> 8888
>>

Disable AR output to console

Change the ActiveRecord::Base.logger.level setting

>> ActiveRecord::Base.logger.level = Logger::FATAL
=> 4


Now, when you run AR commands, you won't see the SQL commands that AR executed

ActiveRecord::Base.logger.level Options

  • Logger::DEBUG
  • Logger::INFO
  • Logger::WARN
  • Logger::ERROR
  • Logger::FATAL



>> Location.where('ancestry is null').size
=> 8888

Disable AR output to console via Ruby Console Config File

Add the following to your ~/.irbrc (or ~/.pryrc file):

ActiveRecord::Base.logger = nil


References

http://lexsheehan.blogspot.com/2013/04/ruby-string-interpolation.html





Sponsor Ads(Please visit one if you liked this article. Thanks!)

Thursday, April 4, 2013

What is 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 * 0 + 1 ?







Keep Scrolling Down to See the Answer...











Keep Scrolling Down to See the Answer...










 The Interactive Ruby Shell Says the Answer is 12



>> 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 * 0 + 1
=> 12


The Bash Shell Says the Answer is 12



$ let "x = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 * 0 + 1";echo $x
12


Lex's Fancy Calculator App Says the Answer is 12


And my calculator application running in the iPhone Simulator is always right!




Conclusion

It's tempting the to use the old rule from grade school: Anything multiplied by 0 is 0 and add 1 to it to arrive at 1.

However, you'd be forgetting the rule of operator precedence, which says that given a series of addition and multiplication operations, perform the multiplication operation(s) first and then perform the addition. So, multiply this (1 * 0) to get 0. Then add up all the other 1's and you get 12.

References

http://en.wikipedia.org/wiki/Order_of_operations

Sponsor Ads(Please click it if you liked this article. Thanks!)

Rails ActiveRecord + PostgreSQL + Ruby Functional Programming = MAGIC

Let's combine the Postgres SQL length function with ActiveRecord Relation magic to get an array of the lengths of each product name.  Note the the following code is running in the Rails Interactive Ruby (irb) Console.


>> a = Product.select('length(name)').order('name').limit(300).map {|i| i['length'].to_i}
  Product Load (2.5ms)  SELECT length(name) FROM "products" ORDER BY name LIMIT 300
=> [58, 79, 90, 103, 41, 30, 43, 57, 70, 55, 49, 44, 39, 91, 115, 126, 48, 35, 45, 75, 57, 53, 67, 55, 56, 47, 84, 74, 83, 82, 80, 51, 44, 91, 86, 34, 38, 82, 86, 52, 56, 63, 120, 54, 66, 61, 32, 60, 99, 36, 40, 36, 60, 40, 70, 58, 53, 56, 67, 102, 77, 56, 40, 84, 59, 61, 59, 54, 50, 52, 62, 73, 57, 69, 44, 60, 45, 54, 48, 78, 36, 45, 61, 67, 78, 92, 45, 63, 64, 59, 68, 65, 64, 111, 71, 66, 70, 87, 50, 85, 94, 80, 106, 47, 48, 102, 36, 81, 82, 38, 67, 94, 84, 102, 62, 80, 72, 65, 49, 64, 46, 56, 53, 46, 56, 33, 32, 37, 43, 71, 66, 75, 54, 70, 40, 70, 39, 70, 86, 93, 55, 52, 59, 43, 56, 45, 23, 28, 61, 36, 63, 67, 61, 98, 53, 82, 85, 92, 63, 43, 55, 39, 31, 36, 103, 59, 68, 34, 53, 74, 71, 71, 72, 56, 50, 43, 56, 54, 84, 61, 66, 106, 63, 76, 36, 68, 64, 56, 46, 50, 48, 82, 35, 44, 53, 33, 68, 65, 58, 29, 34, 70, 50, 54, 75, 86, 57, 52, 48, 66, 53, 69, 33, 77, 73, 57, 70, 55, 40, 43, 81, 83, 97, 68, 60, 103, 69, 107, 50, 45, 38, 98, 72, 57, 66, 107, 74, 78, 75, 78, 48, 63, 41, 75, 46, 80, 73, 103, 102, 91, 41, 68, 50, 57, 42, 41, 86, 97, 44, 40, 36, 83, 83, 66, 57, 49, 46, 51, 78, 64, 39, 90, 35, 43, 24, 46, 73, 59, 59, 63, 84, 66, 31, 43, 80, 77, 96, 73, 75, 38, 57, 66, 24, 72, 38, 36, 32, 91, 90, 29]


Use Ruby's functional reduce method to find the largest field length value:


>> a.reduce(0) do |max, value|
?>       max = value if value > max
>>       max
>>   end
=> 130
>>



Sponsor Ads(Please visit one if you liked this article. Thanks!)

Wednesday, April 3, 2013

Your Personal Phone Number Exposed by a Simple Google Search?

I just searched for my name on google.com just to see how many matches there would be. To my surprise, the google search results exposed my personal cell phone number.


The good news is that all you have to do is click the <Update your profile> button to remove it.

I checked out a few contacts and found that 25 percent of my contacts have their phone numbers exposed.

I'm fairly certain that when we registered for Google Plus we didn't notice that the default setting was to expose our phone number.

You have been warned.

This is an example of how not to design a registration page.

Registration pages should present users with the option to "Opt In", i.e., users should have to take action to click a checkbox, rather than have to take action to "Opt Out" of sharing personal information.
Sponsor AdsLike it? If so pls. click the Ad.

How to Reference CamelCase Column Names in a Postgres Database

Assuming you have a Postgres database table like the following...

$ psql -d my_postgres_db_name

psql (9.2.1)
Type "help" for help.

my_postgres_db_name=# \d+ products
                                                                 Table "public.products"
          Column           |            Type             |                          Modifiers                           | Storage  | Stats target | Description
---------------------------+-----------------------------+--------------------------------------------------------------+----------+--------------+-------------
 id                        | integer                     | not null default nextval('products_id_seq'::regclass)        | plain    |              |
 title                     | character varying(255)      |                                                              | extended |              |
 primarySupplierId         | integer      


If you try to reference the primarySupplierId through ActiveRecord like following you'll this ERROR:

my_postgres_db_name=# select primarySupplierId from products limit 1;
 ERROR:  column "primarySupplierId" does not exist
 LINE 1: select primarySupplierId from products limit 1;
                ^

ActiveRecord

The same is true if you try to access it via ActiveRecord:

>> Product.select('id, title, primarySupplierId').limit(2)
  Product Load (0.4ms)  SELECT id, title, primarySupplierId FROM "products" LIMIT 2
Hirb Error: PG::Error: ERROR:  column "primarySupplierId" does not exist
LINE 1: SELECT  id, title, primarySupplierId FROM "product...
                           ^
: SELECT  id, title, primarySupplierId FROM "products"  LIMIT 2
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `async_exec'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1153:in `exec_no_cache'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:662:in `block in exec_query'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activesupport-3.2.11/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:661:in `exec_query'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:1248:in `select'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract/database_statements.rb:18:in `select_all'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/querying.rb:38:in `block in find_by_sql'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/explain.rb:40:in `logging_query_plan'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/querying.rb:37:in `find_by_sql'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/relation.rb:171:in `exec_queries'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/relation.rb:160:in `block in to_a'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/explain.rb:33:in `logging_query_plan'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/relation.rb:159:in `to_a'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/activerecord-3.2.11/lib/active_record/relation/delegation.rb:6:in `to_ary'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/formatter.rb:88:in `Array'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/formatter.rb:88:in `determine_output_class'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/formatter.rb:53:in `format_output'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/view.rb:204:in `render_output'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/view.rb:123:in `view_output'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/view.rb:200:in `view_or_page_output'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/hirb-0.7.1/lib/hirb/view.rb:186:in `output_value'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:160:in `block (2 levels) in eval_input'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:273:in `signal_status'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:156:in `block in eval_input'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb/ruby-lex.rb:243:in `block (2 levels) in each_top_level_statement'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:155:in `eval_input'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:70:in `block in start'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:69:in `catch'
    /Volumes/my_volume_name/Users/lex/.rbenv/versions/1.9.3-p194/lib/ruby/1.9.1/irb.rb:69:in `start'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
    /myapps/myapp/vendor/bundle/ruby/1.9.1/gems/railties-3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
    script/rails:6:in 'require'
    script/rails:6:in '<main>'

Solution

Just double quote the CamelCased column name, i.e., "primarySupplierId"

my_postgres_db_name=# select "primarySupplierId" from products limit 1;
primarySupplierId
----------------------
384
(1 row)

ActiveRecord

It works for ActiveRecord, too.

>> Product.select('id, title, "primarySupplierId"').limit(2)
  Product Load (0.8ms)  SELECT id, title, "primarySupplierId" FROM "products" LIMIT 2
+------+--------------------------------------------------+----------------------+
| id   | title                                            | primarySupplierId    |
+------+--------------------------------------------------+----------------------+
| 1791 | Hot Air Baloons                                  | 384                  |
| 1792 | Red Wines                                        | 384                  |
+------+--------------------------------------------------+----------------------+
2 rows in set


Sponsor Ads(Please visit one if you liked this article. Thanks!)

Scala or Ruby - Which Is Most Sexy?

In computer science, the syntax of a programming language is the set of rules that define the combinations of symbols that are considered to be correctly structured programs in that language. The syntax of a language defines its surface form.

So, when we ask, "Which has the best syntax, Scala or Ruby?," we're really asking, "Which code looks better?" Good looking code is Sexy Code.

I'll try to be objective.

I'll add to the collection of examples below over time. So, keep coming back to this blog post to see which language wins the most SEXY Award points.

Your opinions are welcome.

Some people think fat is beautiful, but that's generally not the case when it comes to code.

Let's start off with showing how each language handles converting two arrays into one a hash, i.e., an array of key/value pairs.

Convert Two Arrays to a Hash

Ruby

>> keys = [1, 2, 3] 
=> [1, 2, 3] 
>> vals = ['A', 'B', 'C'] 
=> ["A", "B", "C"] 
>> hash = Hash[keys.zip(vals)] 
=> {1=>"A", 2=>"B", 3=>"C"}

Scala

scala> val keys = Array(1, 2, 3) 
keys: Array[Int] = Array(1, 2, 3) 
scala> val values = Array("A", "B", "C") 
values: Array[java.lang.String] = Array(A, B, C) 
scala> val map = keys.zip(values).toMap 
map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> A, 2 -> B, 3 -> C)

Winner: Ruby

Ruby is the clear winner, based on KISS (Keep It Simple, Stupid). It takes less typing to accomplish the same goal. Less code means less to type and less to maintain.  In this example, Ruby is sexier than Scala.




Find Largest Value in Array

Ruby


[1,2,3].max
=> 3


Ruby, Similar to Scala (not great)

>> [1, 3, 2].reduce(0) {|max, value| max = value if value > max; max}
=> 3


Scala


scala> List(1, 3, 2).reduceLeft ( _ max _ )
res0: Int = 3


Winner: Ruby



Conclusion

Which ever language (Scala or Ruby) has the most, wins.

Totals
Ruby2
Scala0

Most SEXY Award



Winner: Ruby






Sponsor Ads(Please visit one if you liked this article. Thanks!)

Tuesday, April 2, 2013

Which HTML5 Storage Mechanism Should You Use?


The following HTML5 databases live in the user's web browser.  Using one of these options as your application's data storage mechanism will likely eliminate the need for a lot of client/server communications since data can now be stored, searched for and retrieved within the web browser.


HTML5 Storage

LocalStorage


  • Simple name/value pair storage
  • No query language
  • No transaction support (won't scale)

WebSQL


  • Fast, scalable, based on Sqlite database so it supports SQL queries, table joins, etc.
  • W3C Working Group dropped support for Sqlite

IndexedDB


  • Slightly faster than WebSQL
  • NoSQL, ORM syntax (JSON data and JavaScript objects)



Based on the facts above one would assume that IndexedDB is the way to go.

However, you must consider your audience...

HTML5 Storage Support in Desktop, Mobile and Tablet Browsers





not so recent

ie Browsers





Internet Explorer 7


Internet Explorer 8



Internet Explorer 9 


Storage
0
2
2
Session Storage »No Yes Yes 
Local Storage »No Yes Yes 
IndexedDB »No No No 
Web SQL Database »No No No 


Windows mobile

browsers

Windows Phone 6.5

Windows Phone 7


Windows Phone 8 



Storage
0
2
3
Session Storage »No Yes Yes 
Local Storage »No Yes Yes 
IndexedDB »No No Yes 
Web SQL Database »No No No 



middle-aged

browsers


Chrome 20

Firefox 15




 Safari 5.1  


Storage
4
3
3
Session Storage »Yes Yes Yes 
Local Storage »Yes Yes Yes 
IndexedDB »Yes Yes No 
Web SQL Database »Yes No Yes 



most recent most popular browsers

Internet Explorer 10


Chrome Canary


Firefox 19




Storage
3
4
3
Session Storage »Yes Yes Yes 
Local Storage »Yes Yes Yes 
IndexedDB »Yes Yes Yes 
Web SQL Database »No Yes No 








Storage
3
3
3
Session Storage »Yes Yes Yes 
Local Storage »Yes Yes Yes 
IndexedDB »No No No 
Web SQL Database »Yes Yes Yes 




recent mobile

browsers


Android 4.0



BlackBerry 10







iOS 6.0 

Storage
3
4
3
Session Storage »Yes Yes Yes 
Local Storage »Yes Yes Yes 
IndexedDB »Yes Yes No 
Web SQL Database »No Yes Yes 



Analysis


WebSQL is no longer supported in the most recent Android (4.0) mobile browser.
WebSQL has never been supported (and won't) in Windows mobile browsers.
WebSQL has never been supported (and won't) in Firefox browsers.

IndexDB was not supported in a Windows Internet Explorer (IE) device until IE 10
IndexDB is still not supported in Safari 6.0
IndexDB is still not supported in IOS 6.0




Conclusion


So, which HTML5 storage mechanism is the best?

As with most things dealing with application development... It depends.

If you can control your user population, then tell them to use the latest Chrome web browser and the latest Android mobile device and use IndexedDB.

If you have iPhone users, then use WebDB.

If you have a use case that strongly supports HTML5 storage, then you might implement both WebDB and IndexedDB and use device detection along with user profiles to determine local storage device affinity per user.  You can use the Strategy Pattern to indicate to the running application which one to use.

If you have a CEO that won't upgrade his web browser or Windows mobile device or you want to support every old device under the sun, then don't use HTML5 storage.

I'd be interested to hear if anybody thinks otherwise... Thanks!


References

http://lexsheehan.blogspot.com/2013/03/which-html5-features-to-use-in-your.html
http://en.wikipedia.org/wiki/Strategy_pattern


HTML5 Web Storage Tutorials

http://www.html5rocks.com/en/tutorials/webdatabase/todo/ http://www.html5rocks.com/en/tutorials/indexeddb/todo/
Sponsor Ads(Please visit one if you liked this article. Thanks!)