Posts tagged as:

Ruby

This semester I’m going to have my Ruby and PHP classes build a form driven, AJAX-y web application as the final project. This is a bread-and-butter assignment that performs the basic task of storing form data in a database then displaying it. We’ll deal with the ever present Persistence Problem by using a SQLite3 database to store user input, and the AJAX/Javascript layer will be all JQuery.

I’ve created the PHP proof of concept site at http://www.istoasisto.com, and it looks like this:

A classroom project of this size can be completed in four to six weeks, depending on the programming and web skills a student brings to the class. More is always better.

The PHP course will be starting from scratch (no cakePHP, no Drupal, no Joomla), while my Ruby course will be using Rails. I’ll be doing the project in Seaside. When all is said and done, we will count the lines of PHP, Ruby, and Smalltalk to see who get bragging rights for writing the fewest lines of code.

If you want to work along wtih us, your project should have these features:

  • An HTML form.
  • JQuery form manipulation.
  • AJAX via JQuery.
  • Validated form input.
  • Form data stored in a SQLite database.
  • A Recaptcha form.
  • User data safely displayed (potentially harmful characters sanitized).

There are dozens of features we could hang on this skeleton: pagination, search, social features (Twitter, Facebook, Buzz, etc), as well as polls, voting, thumbs-up/down, email, XML export, RSS feeds, Section 508 compliance, and more. I’ll be satisfied if most of my students can achieve basic functionality before semester burnout sets in.

And about that Seaside course—there isn’t one yet. But it is on my TODO list for future courses at CCSF. For the time being, as part of my own Smalltalk education, I’ll take this opportunity to complete the class project using Seaside. Since Smalltalk and Seaside are new to me, I’ll be starting on the same page as my PHP and Ruby students. This will be fun. I’ll be doing this project with Cincom Visualworks Non-Commercial which is free for non-commercial use on Windows, Linux, and Mac OS X.

OK. I’d better get to work on the Ruby part of this project before the Rails team unleashes another new product release just to confuse me.

Happy hacking…

{ 4 comments }

A reserved word in a programming language is a word that is off limits to the programmer. For example, in PHP print is a reserved word. This means that you, as the programmer, cannot create a function named print because PHP owns that word.

Most languages have reserved words, some a few, and some very, very many. Usually the fewer reserved words a language has, the more flexible it is. For example, in the list below, you will see that Lisp has no reserved words. We all know that Lisp is very flexible and powerful.

As you look at the table below, do not think unkind thoughts about PHP—it’s different from the other languages. It is not designed to be a general purpose programming language, though it can certainly do almost anything you want it to do. It is intended for web programming, which explains the existence of so many of the predefined functions and constants. Those are exactly the kinds of items that other languages must implement individually if they want to be as handy with web development as PHP. This is no small task, kids. Just take a look around try to find a web site implemented in C++.

Reserved Words

Language Count Reserved Words
Lisp 0 Lisp has no reserved words. Lisp is written in Lisp. Alan Kay, the creator of Smalltalk, said: “Lisp isn’t a language, it’s a building material.”
Smalltalk 5 self super nil true false
C 32 auto break case chart const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while
C++ ~62 and and_eq asm auto bitand bitor bool break case catch char class compl const const_cast continue default delete do double dynamic_cast else enum explicit export extern false float for friend goto if inline int long mutable namespace new not not_eq operator or or_eq private protected public register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename union unsigned using virtual void volatile wchar_t while xor xor_eq
Ruby 38 alias and BEGIN begin break case class def defined? do else elsif END end ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield
Python 31 and del from not while as elif global or with assert else if pass yield break except import print class exec in raise continue finally is return def for lambda try
Java 47 abstract do if package synchronized boolean double implements private this break else import protected throw byte extends instanceof public throws case false int return transient catch final interface short true char finally long static try class float native strictfp void const for new super volatile continue goto null switch while default assert
PHP 418 __CLASS__ __COMPILER_HALT_OFFSET__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __PHP_INCOMPLETE_CLASS ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5 ABDAY_6 ABDAY_7 ABMON_1 ABMON_10 ABMON_11 ABMON_12 ABMON_2 ABMON_3 ABMON_4 ABMON_5 ABMON_6 ABMON_7 ABMON_8 ABMON_9 ABSTRACT ALT_DIGITS AM_STR AND ARGC ARGV ARRAY AS ASSERT_ACTIVE ASSERT_BAIL ASSERT_CALLBACK  ASSERT_QUIET_EVAL ASSERT_WARNING AUTH_TYPE BREAK CASE CASE_LOWER CASE_UPPER CATCH CFUNCTION CHAR_MAX CLASS CLONE CODESET CONNECTION_ABORTED CONNECTION_NORMAL CONNECTION_TIMEOUT CONST CONTINUE COUNT_NORMAL COUNT_RECURSIVE CREDITS_ALL CREDITS_DOCS CREDITS_FULLPAGE CREDITS_GENERAL CREDITS_GROUP CREDITS_MODULES CREDITS_QA CREDITS_SAPI CRNCYSTR CRYPT_BLOWFISH CRYPT_EXT_DES CRYPT_MD5 CRYPT_SALT_LENGTH CRYPT_STD_DES CURRENCY_SYMBOL D_FMT D_T_FMT DAY_1 DAY_2 DAY_3 DAY_4 DAY_5 DAY_6 DAY_7 DECIMAL_POINT DECLARE DEFAULT DEFAULT_INCLUDE_PATH DIE DIRECTORY_SEPARATOR DO DOCUMENT_ROOT E_ALL E_COMPILE_ERROR E_COMPILE_WARNING E_CORE_ERROR E_CORE_WARNING E_ERROR E_NOTICE E_PARSE E_STRICT E_USER_ERROR E_USER_NOTICE E_USER_WARNING E_WARNING ECHO ELSE ELSEIF EMPTY ENDDECLARE ENDFOR ENDFOREACH ENDIF ENDSWITCH ENDWHILE  ENT_COMPAT ENT_NOQUOTES ENT_QUOTES ERA ERA_D_FMT ERA_D_T_FMT ERA_T_FMT ERA_YEAR EVAL EXCEPTION EXIT EXTENDS EXTR_IF_EXISTS EXTR_OVERWRITE EXTR_PREFIX_ALL EXTR_PREFIX_IF_EXISTS EXTR_PREFIX_INVALID EXTR_PREFIX_SAME EXTR_SKIP FINAL FOR FOREACH FRAC_DIGITS FUNCTION GATEWAY_INTERFACE GLOBAL GROUPING HTML_ENTITIES HTML_SPECIALCHARS HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING HTTP_ACCEPT_LANGUAGE HTTP_CONNECTION HTTP_HOST HTTP_REFERER HTTP_USER_AGENT HTTPS IF IMPLEMENTS INCLUDE INCLUDE_ONCE INFO_ALL INFO_CONFIGURATION INFO_CREDITS INFO_ENVIRONMENT INFO_GENERAL INFO_LICENSE INFO_MODULES INFO_VARIABLES INI_ALL INI_PERDIR INI_SYSTEM INI_USER INT_CURR_SYMBOL INT_FRAC_DIGITS INTERFACE ISSET LC_ALL LC_COLLATE LC_CTYPE LC_MESSAGES LC_MONETARY LC_NUMERIC LC_TIME LIST LOCK_EX LOCK_NB LOCK_SH LOCK_UN LOG_ALERT LOG_AUTH LOG_AUTHPRIV LOG_CONS LOG_CRIT LOG_CRON LOG_DAEMON LOG_DEBUG LOG_EMERG LOG_ERR LOG_INFO LOG_KERN LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 LOG_LOCAL5 LOG_LOCAL6 LOG_LOCAL7 LOG_LPR LOG_MAIL LOG_NDELAY LOG_NEWS LOG_NOTICE LOG_NOWAIT LOG_ODELAY LOG_PERROR LOG_PID LOG_SYSLOG LOG_USER LOG_UUCP LOG_WARNING M_1_PI M_2_PI M_2_SQRTPI M_E M_LN10 M_LN2 M_LOG10E M_LOG2E M_PI M_PI_2 M_PI_4 M_SQRT1_2 M_SQRT2 MON_1 MON_10 MON_11 MON_12 MON_2 MON_3 MON_4 MON_5 MON_6 MON_7 MON_8 MON_9 MON_DECIMAL_POINT MON_GROUPING MON_THOUSANDS_SEP N_CS_PRECEDES N_SEP_BY_SPACE N_SIGN_POSN NEGATIVE_SIGN NEW NOEXPR NOSTR OLD_FUNCTION OR P_CS_PRECEDES P_SEP_BY_SPACE P_SIGN_POSN PATH_SEPARATOR PATH_TRANSLATED PATHINFO_BASENAME PATHINFO_DIR NAME PATHINFO_EXTENSION PEAR_EXTENSION_DIR PEAR_INSTALL_DIR PHP_AUTH_DIGEST PHP_AUTH_PW PHP_AUTH_USER PHP_BINDIR PHP_CONFIG_FILE_PATH PHP_CONFIG_FILE_SCAN_DIR PHP_DATADIR PHP_EOL PHP_EXTENSION_DIR PHP_INT_MAX PHP_INT_SIZE PHP_LIBDIR PHP_LOCALSTATEDIR PHP_OS PHP_OUTPUT_HANDLER_CONT PHP_OUTPUT_HANDLER_END PHP_OUTPUT_HANDLER_START PHP_PREFIX PHP_SAPI PHP_SELF PHP_SHLIB_SUFFIX PHP_SYSCONFDIR PHP_USER_FILTER PHP_USER_FILTER PHP_VERSION PM_STR POSITIVE_SIGN PRINT PRIVATE PROTECTED PUBLIC QUERY_STRING RADIXCHAR REMOTE_ADDR REMOTE_HOST REMOTE_PORT REQUEST_METHOD REQUEST_TIME REQUEST_URI REQUIRE REQUIRE_ONCE RETURN SCRIPT_FILENAME SCRIPT_NAME SEEK_CUR SEEK_END SEEK_SET SERVER_ADDR SERVER_ADMIN SERVER_NAME SERVER_PORT SERVER_PROTOCOL SERVER_SIGNATURE SERVER_SOFTWARE SORT_ASC SORT_DESC SORT_NUMERIC SORT_REGULAR SORT_STRING STATIC STDCLASS STR_PAD_BOTH STR_PAD_LEFT STR_PAD_RIGHT SWITCH T_FMT T_FMT_AMPM THIS THOUSANDS_SEP THOUSEP THROW TRY UNSET USE VAR WHILE XOR YESEXPR YESSTR LASS__ __COMPILER_HALT_OFFSET__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __PHP_INCOMPLETE_CLASS ABDAY_1 ABDAY_2 ABDAY_3 ABDAY_4 ABDAY_5 ABDAY_6 ABDAY_7 ABMON_1 ABMON_10 ABMON_11 ABMON_12 ABMON_2 ABMON_3 ABMON_4 ABMON_5 ABMON_6 ABMON_7 ABMON_8 ABMON_9 ABSTRACT ALT_DIGITS AM_STR AND ARGC ARGV ARRAY AS ASSERT_ACTIVE ASSERT_BAIL ASSERT_CALLBACK ASSERT_QUIET_EVAL ASSERT_WARNING AUTH_TYPE BREAK CASE CASE_LOWER CASE_UPPER CATCH CFUNCTION CHAR_MAX CLASS CLONE CODESET CONNECTION_ABORTED CONNECTION_NORMAL CONNECTION_TIMEOUT CONST CONTINUE COUNT_NORMAL COUNT_RECURSIVE CREDITS_ALL CREDITS_DOCS CREDITS_FULLPAGE CREDITS_GENERAL CREDITS_GROUP CREDITS_MODULES CREDITS_QA CREDITS_SAPI CRNCYSTR CRYPT_BLOWFISH CRYPT_EXT_DES CRYPT_MD5 CRYPT_SALT_LENGTH CRYPT_STD_DES CURRENCY_SYMBOL D_FMT D_T_FMT DAY_1 DAY_2 DAY_3

{ 11 comments }

irb Screencast (Interactive Ruby)

by doug on January 27, 2010

in Editorial

If you need to see irb in action, check out this screencast.

Whenever I see a smooth, well-written, organized screencast I have a deep sense of appreciation. That’s my goal: be smooth, well-spoken, and organized. :)

Keep hacking Ruby…

{ 1 comment }

My current technology preoccupations are PHP, Ruby, and Smalltalk. Over the last month I’ve been putting together blog sites for each of them: PHP: The Good Parts, Ruby: The Good Parts, and Smalltalk: The Good Parts.

I spend most of my time with PHP and Ruby because I teach classes in these languages at CCSF and CSM. After years of teaching both beginning students and experienced professionals I have an accurate sense of what they need to get off to a good start. I’ve written a ton of content for these courses—screencasts, pdfs, projects, exercises, etc. I plan to use the PHP and Ruby blogs to share some of the material I’ve created for my courses.

Smalltalk is a different matter: I’m a complete newbie and I’m climbing the same learning curve that my PHP and Ruby students climb. As I learn Smalltalk I’ll use the blog to document the process. My plan is to turn my experience (blood, sweat, and tears) into a Smalltalk course. I’ve seen Smalltalk in action, and now I want to do it for myself, then show others how insanely great it is.

I’ll be adding content to the blogs as I as fast as I can proof read it and test the code. If you are on the front end of your PHP career, you will find some pearls of wisdom here. I suggest that you subscribe to these blogs to keep informed of new posts as I update these blogs.

It’s going to take time to fill in these pages, and I expect that I’ll make many errors along the way. I appreciate all feedback; if you see something that needs fixing—code errors, spelling errors, or something that’s just plain wrong—please let me know. Feedback is golden.

Keep hacking…

Respect

My good parts blogs are inspired by Javascript: The Good Parts by Douglas Crockford. His cogent little book has taught me to scrutinize programming languages with a pragmatic eye: embrace what works and find a way to deal with the rest.

{ 0 comments }

SliceHost vs Dreamhost: a Simple Benchmark

by doug on January 17, 2010

in Editorial

I recently rented a 256MB slice from Slicehost for my SmalltalkTheGoodParts.com work. I have a Wordpress blog running there, and I’ll be installing Smalltalk and Seaside as part of my self-taught Smalltalk course.

Bad-mouthing Dreamhost
I hear a lot of bad-mouthing about Dreamhost. I have several domains on DH, and I’ve done some of that bad-mouthing myself. However, I’m here to tell you that all is not gloom and doom at Dreamhost. Nor is Slicehost always perfect.

Server Down at Slicehost
Slicehost is subject to the same laws of physics as Dreamhost. Within 24 hours of starting my slice I got an email informing me my server would be out of action for an hour or two. The Slice guys gave me a specific time and did their thing at the appointed hour. Sure, the server was down, but the nice thing about this “negative” experieince was that Slicehost noticed the problem before I did and let me know in advance that things were going South.

Server Down at Dreamhost
That same week my Dreamhost server was out of action every morning at 1AM and had to be rebooted by the Dreamhost sys admins. I noticed this because I work late. The cause of the problem, I am told, was a faulty RAID subsytem. The unannounced outages were so common that I became discouraged and decided to move the newest of my domains (my Smalltalk site) to Slicehost. To Dreamhost’s credit the faulty hardware was replaced and I haven’t had any further problems.

My main gripe with Dreamhost is the poor communication when these problems arise. When I’m warned in advance, I’m quite tolerant. I’ve worked on large systems and I understand that things break. Just let me know that your team is on top of it, and don’t try to BS me.

A 256MB Slicehost Slice vs Dreamhost Shared Host
Now that all of my servers are running fine and dandy, I ran a few tests to get a general idea of the relative speeds of my Dreamhost shared host and my Slicehost slice. To make it more interesting, I ran the same test on my i7 iMac.

The Test
I usually run a Ruby Fibonacci generator to see what level of processing speed I’m dealing with. This test puts a 100% load on the CPU, so it’s a good idea to keep it brief. On a shared host it’s a good idea to fly under the radar.

# fib.rb
require ‘profile’
def fib(n)
return n if n < 2
return fib(n-2)+fib(n-1)
end

1.upto(22) do |n|
puts(fib(n));
end


Slicehost 256MB Slice
%   cumulative   self              self     total
time   seconds   seconds    calls  ms/call  ms/call  name
77.51    20.89     20.89   150024     0.14     2.48  Object#fib
9.87    23.55      2.66   150024     0.02     0.02  Fixnum#<
8.53    25.85      2.30   150002     0.02     0.02  Fixnum#-
4.08    26.95      1.10    75001     0.01     0.01  Fixnum#+
0.00    26.95      0.00       22     0.00     0.00  Kernel.puts
0.00    26.95      0.00       44     0.00     0.00  IO#write
0.00    26.95      0.00       22     0.00     0.00  Fixnum#to_s
0.00    26.95      0.00        1     0.00 26950.00  Integer#upto
0.00    26.95      0.00        1     0.00     0.00  Module#method_added
0.00    26.95      0.00        1     0.00 26950.00 #toplevel

Dreamhost
%   cumulative   self              self     total
time   seconds   seconds    calls  ms/call  ms/call  name
77.87    16.68     16.68   150024     0.11     1.96  Object#fib
9.24    18.66      1.98   150024     0.01     0.01  Fixnum#<
8.50    20.48      1.82   150002     0.01     0.01  Fixnum#-
4.39    21.42      0.94    75001     0.01     0.01  Fixnum#+
0.00    21.42      0.00       22     0.00     0.00  Kernel.puts
0.00    21.42      0.00       44     0.00     0.00  IO#write
0.00    21.42      0.00        1     0.00 21420.00  Integer#upto
0.00    21.42      0.00        1     0.00     0.00  Module#method_added
0.00    21.42      0.00       22     0.00     0.00  Fixnum#to_s
0.00    21.42      0.00        1     0.00 21420.00 #toplevel

iMac i7
%   cumulative   self              self     total
time   seconds   seconds    calls  ms/call  ms/call  name
76.73     9.10      9.10   150024     0.06     1.09  Object#fib
10.46    10.34      1.24   150024     0.01     0.01  Fixnum#<
8.35    11.33      0.99   150002     0.01     0.01  Fixnum#-
4.38    11.85      0.52    75001     0.01     0.01  Fixnum#+
0.08    11.86      0.01       44     0.23     0.23  IO#write
0.00    11.86      0.00        1     0.00 11860.00  Integer#upto
0.00    11.86      0.00       22     0.00     0.00  Fixnum#to_s
0.00    11.86      0.00        1     0.00     0.00  Module#method_added
0.00    11.86      0.00       22     0.00     0.45  Kernel.puts
0.00    11.86      0.00        1     0.00 11860.00 #toplevel

Dreamhost Edges out the Little Slice
You can see that Dreamhost runs this test a little quicker than the Slice. This jibes with my gut feeling that the little slice is slightly underpowered. The Really Nice Thing thing about Slicehost is that I can turn up the juice if I need it. I can’t do that at Dreamhost. Where Slicehost really wins is that I can run my own Linux box for cheap.

Conclusion
If I could have only one account I would probably stick with Dreamhost. I’m lazy enough to appreciate all the goodies DH provides, along with infinite bandwidth and storage. However, I’d rather not choose. Dreamhost and the Tiny Slice are affordable enough that I can have Dreamhost for the cheap goodies, and Slicehost for the complete freedom to do whatever I want with my Linux server, including running Smalltalk.

Happy hacking…

{ 0 comments }

My Spring 2010 students are pounding at the door. At CCSF my Ruby and PHP courses start January 19th. I’ll also be teaching the Ruby course at the College of San Mateo.

PHP and Ruby are where the job action is, especially in the Bay Area, where startups are using lots of PHP and Rails. You can see in this table from the Tiobe Index that PHP and Ruby are high on the jobs list.

But they are obviously not at the top of the list. You might think “Why bother with PHP or Ruby? Why not go directly to Java or C/C++, since those languages comprise almost 43% of the job market?  The answer is that there is a higher demand for PHP and Ruby programmers than for Java programmers.

The oDesk.com Blog discusses the supply and demand effect. When looking at this chart, keep in mind that a low fill rate means a higher demand for qualified applicants, and a high fill rate means a higher supply of qualified applicants.

Today’s Jobs with the Least Competition and Greatest Opportunity

PHP resides in the sweet spot: lots of jobs with a low fill rate; out of 731 jobs, only 33.8% (248) were filled.

I should point out that there were not enough Ruby jobs to break in oDesks Top 25 list. And notice that oDesk lists only 75 Java jobs, which indicates few opportunities.

If you are a PHP programmer, don’t think these jobs will just fall into your lap. The bar is set high these days. The PHP jobs in question are not entry level jobs. Employers are looking for experienced programmers (also called “PHP rock star ninjas” in Silicon Valley). My advice to all of you looking for PHP work is that you build a PHP and MySQL driven MVC web application to show as a resume project. If you go into an interview without your own PHP/MySQL web site, you are dead in the water.

Conclusion: PHP is a good place to be. There are PHP jobs out there and not nearly enough good PHP programmers to fill them. In fact, several of my students have taken PHP positions with companies who are willing to train them on the job.

As for Ruby, it’s all about Rails. San Francisco is the Rails Hub of the Universe and there are great Rails jobs with great companies…if your programming chops are awesome. By awesome I mean comprehensive, deep, and mature. Though Rails is this week’s flavor, real Rails programming is a high art. Rails programmers are self-taught, and many of the best have moved from productive (if unfulfilling) Java or PHP careers to Rails. If you are a good programmer, and you’re also a Ruby programmer, your future is bright.

If you’re a Ruby Newbie, I suggest you put your shoulder to the wheel and push—hard. And lest you be discouraged, take heart because there is hope. In fact there is a well known algorithm for turning a mere mortal into a fabulous programmer, and I’ll give it to you for free. Check out Teach Yourself Programming in Ten Years.

Keep hacking…

{ 2 comments }

Welcome to Ruby The Good Parts

by doug on January 8, 2010

in Ruby

Welcome to Ruby The Good Parts. This blog is part of the HackingtheValley.com empire of Good Parts blogs for PHP, Ruby, and Smalltalk. As we create Ruby content, we will post it here.

In the meantime, check out Hacking The Valley and PHP The Good Parts.

TTYL,

Douglas Putnam

{ 0 comments }