Web – BetterExplained https://betterexplained.com Math lessons that click Mon, 14 Dec 2020 04:40:35 +0000 en-US hourly 1 How To Make a Bookmarklet For Your Web Application https://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/ https://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/#comments Wed, 16 Apr 2008 18:49:59 +0000 http://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/ Browser buttons (bookmarklets) are shortcuts that act like a simple browser plugin. Their advantages include:

  • Fast installation: Just add a link to your bookmarks
  • Convenient: Use features while on your current page
  • Easy to write: Bookmarklets are just like making a webpage; there’s no need to write a whole browser plugin
  • Cross-browser: The same bookmarklet can work in IE, Firefox, Opera and Safari.

Here’s a few bookmarklets I use regularly:

How easy is it?

Only one way to find out. Try the instacalc bookmarklet right here:

How To Make a Bookmarklet For Your Web Application

  • Click this link: instacalc bookmarklet.
  • A calculator opens in the corner of the page. Type 1 + 1 to see the result.
  • Select this text 15 mph in fps and click the link again. Voila! The text is automatically inserted.
  • Close the window by clicking the red “x”

Neat, eh? No install, just click and go. To save the bookmarklet, right click the link and “add to favorites/bookmarks”. Now you can open the calculator on any page.

Today we’ll walk through the anatomy of a bookmarklet, dissect a few, and give you the tools to build your own.

Bookmarklets 101

Regular bookmarks (aka favorites) are just locations to visit, like “http://gmail.com”. Bookmarklets are javascript code that the browser runs on the current page, and they’re marked by “javascript:” instead of “http://”.

When clicking a bookmarklet, imagine the page author wrote <script>bookmarklet code here</script> — it can do almost anything. There are a few restrictions:

  • Restricted length: Most URLs have a limit around 2000 characters, which limits the amount of code you can run. There’s a way around this.
  • No spaces allowed: Some browsers choke on spaces in a URL, so yourcodelookslikethis. We have a trick for this too.

A simple bookmarklet looks like this:

<a href="javascript:alert('hi');">my link</a>

Click this link to see it in action. This example isn’t too wild, but the key is that bookmarklets let you run code on an existing page.

What do you want to do?

Your bookmarklet should do something useful. Ideas include:

  • Transform the current page. Do find/replace, highlight certain words or images, change CSS styles…
  • Open/overlay a new page. Open a new page or draw a window on the current one, like a sidebar
  • Send data to another site. Post, share, or upload the current URL or selected text (like Google translate).
  • Look at the bookmarklet directories for more inspiration.

People spend most of their time on other sites. Web application authors, think creatively: how can people use your service when away from your site?

Javascript for Bookmarklets

A bookmarklet can use any javascript command, but certain ones are helpful:

Get current page title: document.title Get the current URL: location.href Get the currently selected text:

  // get the currently selected text
  var t;
  try {
    t= ((window.getSelection && window.getSelection()) ||
(document.getSelection && document.getSelection()) ||
(document.selection &&
document.selection.createRange &&
document.selection.createRange().text));
  }
  catch(e){ // access denied on https sites
    t = "";
  }

Make text url-safe: encodeURIComponent(text) (and corresponding decodeURIComponent()). The page title or URL may have invalid characters (spaces, slashes, etc.) so it’s a good habit to encode them before sending them over (spaces become %20, etc.).

Dissecting the Delicious Bookmarklet

Here’s the code for the delicious bookmarklet (spaces added for readability):

javascript:location.href='http://del.icio.us/post?v=4;
url='+encodeURIComponent(location.href)+';
title='+encodeURIComponent(document.title)

And here’s what’s happening:

  • Change to a new URL (to post the item)
  • Specify query parameters for the current document’s url (location.href) and title (document.title)
  • Make the paramaters url-safe with encodeURIComponent

Once you tag and save the post, delicious sends you to the original page. How do they know where? Because it was sent along in the original request!

Bookmarklet Interface Ideas

Imagine this: Your users are browsing for cat photos (or the journals of the American Chemical Society, but probably lolcats) when they click your killer Web 2.0 bookmarklet. What happens?

Bookmarklet interface ideas

Common techniques are:

  • Take the user to a new page. Hopefully, you can use some data from the current page, otherwise it’s a regular bookmark.
  • Frame the current page, like Google translate or Stumbleupon. This is similar to the first technique, but your site displays the old page inside the window.
  • Overlay a new interface. Use CSS absolute positioning to make a window in a set place, or fixed positioning to have the window follow you as you scroll. Beware the CSS bugs.

Overlaid windows are great, but won’t that be hard to cram into a single line?

The Big Trick: Dynamic Javascript

Direct javascript works fine if you just want to redirect the user to another page, like the delicious bookmarklet. The no spaces, 2000 character limit really hurts when you want a more complicated interface.

There’s a fix: Our bookmarklet becomes a stub to load another (regular) javascript file. Here’s the code (spaces added for readability):

javascript:(function(){
  _my_script=document.createElement('SCRIPT');
  _my_script.type='text/javascript';
  _my_script.src='http://mysite.com/script.js?';
  document.getElementsByTagName('head')[0].appendChild(_my_script);
})();

Here’s how it works:

  • Define an anonymous function to download the script
  • Create a script element, type text/javascript. We can’t use var _my_script because of the spaces, so choose a unique name.
  • Set the src of the script to our real javascript file. This file could pull down more javascript also.
  • Add the script element to the current page

And that’s it! Our bookmarklet can now load any javascript we please, without the annoying restrictions. An added bonus: see how many people are using your tool, and you we can change our script (fix bugs or add features) on the server.

Dissecting the Instacalc Bookmarklet

Here’s the steps I went through to make the instacalc bookmarklet

Create a bookmarklet interface

I made a trimmed-down page designed for the bookmarklet. If you click the page it appears fullscreen, but it resizes to the parent container. I planned on hosting this page inside a smaller iframe.

Create a stub bookmarklet

Because I wanted to get the currently selected text and overlay an interface, I knew I couldn’t fit my javascript into 2000 characters. So I used the dynamic javascript technique above to get the real javascript file.

Careful caching

I didn’t want to cache the bookmarklet javascript in case I wanted to change its behavior (but I did cache the other files). I added a dummy query parameter using Math.random(), which forces the browser to download the file each time. Since the script is small, this wasn’t too much of an issue.

instacalc_script.src='http://static.instacalc.com/gadget/instacalc.bookmarklet.js?x='+(Math.random());

Build the interface

The script to build the interface is pretty straightforward. There’s some helper functions for encoding (instacalc stores data using base64). The script gets the selected text, constructs the URL for the iframe, and loads it up. It generates the CSS to have a fixed window on the top right of the screen, and a button to hide the window.

As a slight trick, if the bookmarklet is run again on the same page, it just shows the existing window instead of creating a new iframe.

Tips & Tricks

Keep this in mind when making your bookmarklet:

Make it friendly. Don’t interrupt the user’s flow. Bring up the window on the same page, or a new page that closes. If you must redirect the user to their original page.

This is important: the user was nice enough to use your service, so put ‘em back where they were!

Make it fast. After you’ve got it working, tweak your bookmarklet’s speed using the following techniques

Give people instructions. Bookmarklets aren’t that common, so help people understand your tool. A few instructions (“right click this link and add to bookmarks/favorites”) and a screenshot go a long way.

The gotcha: cross-domain communication

Because of cross-domain security restrictions, your bookmarklets can’t use fancy-pants Ajax techniques to communicate with your site. The easiest way to communicate is through query parameters in a URL.

Debugging

What’s programming without bugs? Use firefox to debug your javascript and CSS. Instead of clicking a bookmarklet each time, just make a page that runs the javascript file directly: <script src="...">. This is what the bookmarklet does.

Once the dummy page is working, try your bookmarklet on other sites. You’d be surprised how other CSS rules can mess up your carefully positioned elements (remember, you’re running in the context of another site).

Links & Resources

I’m sure you’ll come up with crazy ways to use your newfound toy. The main benefits are simple installation, compatibility, and being able to interact with the current page.

  • There are crunching tools to make your javascript bookmarklet-friendly. But it’s nice to just dynamically load the real script and be done with it.

  • People have put the delicious bookmarklet on steroids, such as letting you type the tags in the url before hitting the button.

  • Taking this to the extreme, Greasemonkey is a firefox plugin letting you run really powerful scripts. For example, there was a script to add a “delete” button to Gmail before it was available.

Have fun.

]]>
https://betterexplained.com/articles/how-to-make-a-bookmarklet-for-your-web-application/feed/ 100
Intermediate Rails: Understanding Models, Views and Controllers https://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/ https://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/#comments Sun, 12 Aug 2007 00:47:05 +0000 http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/ I’m glad people liked the introduction to Rails; now you scallawags get to avoid my headaches with the model-view-controller (MVC) pattern. This isn’t quite an intro to MVC, it’s a list of gotchas as you plod through MVC the first few times.

Here’s the big picture as I understand it:

rails mvc

  • The browser makes a request, such as http://mysite.com/video/show/15

  • The web server (mongrel, WEBrick, etc.) receives the request. It uses routes to find out which controller to use: the default route pattern is “/controller/action/id” as defined in config/routes.rb. In our case, it’s the “video” controller, method “show”, with the id parameter set to “15″. The web server then uses the dispatcher to create a new controller, call the action and pass the parameters.

  • Controllers do the work of parsing user requests, data submissions, cookies, sessions and the “browser stuff”. They’re the pointy-haired manager that orders employees around. The best controller is Dilbert-esque: It gives orders without knowing (or caring) how it gets done. In our case, the show method in the video controller knows it needs to lookup a video. It asks the model to get video 15, and will eventually display it to the user.

  • Models are Ruby classes. They talk to the database, store and validate data, perform the business logic and otherwise do the heavy lifting. They’re the chubby guy in the back room crunching the numbers. In this case, the model retrieves video 15 from the database.

  • Views are what the user sees: HTML, CSS, XML, Javascript, JSON. They’re the sales rep putting up flyers and collecting surveys, at the manager’s direction. Views are merely puppets reading what the controller gives them. They don’t know what happens in the back room. In our example, the controller gives video 15 to the “show” view. The show view generates the HTML: divs, tables, text, descriptions, footers, etc.

  • The controller returns the response body (HTML, XML, etc.) & metadata (caching headers, redirects) to the server. The server combines the raw data into a proper HTTP response and sends it to the user.

It’s more fun to imagine a story with “fat model, skinny controller” instead of a sterile “3-tiered architecture”. Models do the grunt work, views are the happy face, and controllers are the masterminds behind it all.

Many MVC discussions ignore the role of the web server. However, it’s important to mention how the controller magically gets created and passed user information. The web server is the invisible gateway, shuttling data back and forth: users never interact with the controller directly.

SuperModels

Models are fat in Railsville: they do the heavy lifting so the controller stays lean, mean, and ignorant of the details. Here’s a few model tips:

Using ActiveRecord

class User < ActiveRecord::Base
end

The code < ActiveRecord::Base means your lowly User model inherits from class ActiveRecord::Base, and gets Rails magic to query and save to a database.

Ruby can also handle “undefined” methods with ease. ActiveRecord allows methods like “find_by_login”, which don’t actually exist. When you call “find_by_login”, Rails handles the “undefined method” call and searches for the “login” field. Assuming the field is in your database, the model will do a query based on the “login” field. There’s no configuration glue required.


Defining Class and Instance Methods

 def self.foo
    "Class method"    # User.foo
  end

  def bar
   "instance method"  # user.bar
  end

Class and instance methods can cause confusion.

user (lowercase u) is an object, and you call instance methods like user.save.

User (capital U) is a class method – you don’t need an object to call it (like User.find). ActiveRecord adds both instance and class methods to your model.

As a tip, define class methods like User.find_latest rather than explicitly passing search conditions to User.find (thin controllers are better).


Using Attributes

Regular Ruby objects can define attributes like this:

  # attribute in regular Ruby
  attr_accessor :name        # like @name
  def name=(val)             # custom setter method
    @name = val.capitalize   # clean it up before saving
  end

  def name                   # custom getter
   "Dearest " + @name        # make it nice
  end

Here’s the deal:

  • attr_accessor :name creates get and set methods (name= and name) on your model. It’s like having a public instance variable @name.
  • Define method name=(val) to change how @name is saved (such as validating input).
  • Define method name to control how the variable is output (such as changing formatting).

In Rails, attributes can be confusing because of the database magic. Here’s the deal:

  • ActiveRecord grabs the database fields and throws them in an attributes array. It makes default getters and setters, but you need to call user.save to save them.
  • If you want to override the default getter and setter, use this:

    # ActiveRecord: override how we access field
    def length=(minutes)
      self[:length] = minutes * 60
    end
    
    def length
      self[:length] / 60
    end
    

ActiveRecord defines a “[]” method to access the raw attributes (wraps the write_attribute and read_attribute). This is how you change the raw data. You can’t redefine length using

def length          # this is bad
  length / 60
end

because it’s an infinite loop (and that’s no fun). So self[] it is. This was a particularly frustrating Rails headache of mine – when in doubt, use self[:field].


Never forget you’re using a database

Rails is clean. So clean, you forget you’re using a database. Don’t.

Save your models. If you make a change, save it. It’s very easy to forget this critical step. You can also use update_attributes(params) and pass a hash of key -> value pairs.

Reload your models after changes. Suppose a user has_many videos. You create a new video, point it at the right user, and call user.videos to get a list. Will it work?

Probably not. If you already queried for videos, user.videos may have stale data. You need to call user.reload to get a fresh query. Be careful — the model in memory acts like a cache that can get stale.


Making New Models

There’s two ways to create new objects:

joe = User.new( :name => "Sad Joe" )        # not saved
bob = User.create ( :name => "Happy Bob" )  # saved
  • User.new makes a new object, setting attributes with a hash. new does not save to the database: you must call user.save explicitly. Method save can fail if the model is not valid.
  • User.create makes a new model and saves it to the database. Validation can fail; user.errors is a hash of the fields with errors and the detailed message.

Notice how the hash is passed. With Ruby’s brace magic, {} is not explicitly needed so

user = User.new( :name => "kalid", :site => "instacalc.com" )

becomes

User.new( {:name => "kalid", :site => "instacalc.com"} )

The arrow (=>) implies that a hash is being passed.


Using Associations

Quick quiz, hotshot: suppose users have a “status”: active, inactive, pensive, etc. What’s the right association?

class User < ActiveRecord::Base
  belongs_to :status  # this?
  has_one :status     # or this?
end

Hrm. Most likely, you want belongs_to :status. Yeah, it sounds weird. Don’t think about the phrase “has_one” and “belongs_to”, consider the meaning:

  • belongs_to: links_to another table. Each user references (links to) a status.
  • has_one: linked_from another table. A status is linked_from a user. In fact, statuses don’t even know about users – there’s no mention of a “user” in the statuses table at all. Inside class Status we’d write has_many :users (has_one and has_many are the same thing – has_one only returns 1 object that links_to this one).

A mnemonic:

  • “belongs_to” rhymes with “links_to”
  • “has_one” rhymes with “linked_from”

Well, they sort of rhyme. Work with me here, I’m trying to help.

These associations actually define methods used to lookup items of the other class. For example, “user belongs_to status” means that user.status queries the Status for the proper status_id. Also, “status has_many :users” means that status.users queries the user table for everyone with the current status_id. ActiveRecord handles the magic once we declare the relationship.


Using Custom Associations

Suppose I need two statuses, primary and secondary? Use this:

belongs_to :primary_status, :model => 'Status', :foreign_key => 'primary_status_id'
belongs_to :secondary_status, :model => 'Status', :foreign_key => 'secondary_status_id'

You define a new field, and explicitly reference the model and foreign key to use for lookups. For example, user.primary_status returns a Status object with the id of “primary_status_id”. Very nice.

Quick Controllers

This section is short, because controllers shouldn’t do much besides boss the model and view around. They typically:

  • Handle things like sessions, logins/authorization, filters, redirection, and errors.
  • Have default methods (added by ActionController). Visiting http://localhost:3000/user/show will attempt to call the “show” action if there is one, or automatically render show.rhtml if the action is not defined.
  • Pass instance variables like @user get passed to the view. Local variables (those without @) don’t get passed.
  • Are hard to debug. Use render :text => "Error found" and return to do printf-style debugging in your page. This is another good reason to put code in models, which are easy to debug from the console.
  • Use sessions to store data between requests: session[:variable] = “data”.

I’ll say it again because it’s burned me before: use @foo (not “foo”) to pass data to the view.

Using Views

Views are straightforward. The basics:

  • Controller actions use views with the same name (method show loads show.rhtml by default)
  • Controller instance variables (@foo) are available in all views and partials (wow!)

Run code in a view using ERB:

  • <% ... %>: Run the code, but don’t print anything. Used for if/then/else/end and array.each loops. You can comment out sections of HTML using <% if false %> Hi there <% end %>. You get a free blank line, since you probably have a newline after the closing %>.

  • <%- ... %>: Run the code, and don’t print the trailing newline. Use this when generating XML or JSON when breaking up .rhtml code blocks for your readability, but don’t want newlines in the output.

  • <%= ... %>: Run the code and print the return value, for example: <%= @foo %> (You did remember the @ sign for controller variables passed to the view, right?). Don’t put if statements inside the <%=, you’ll get an error.

  • <%= h ... %>: Print the code and html escape the output: > becomes >. h() is actually a Ruby function, but called without parens, as Rubyists are apt to do.

It’s a bit confusing when you start out — run some experiments in a dummy view page.

Take a breather

The MVC pattern is a lot to digest in one sitting. As you become familiar with it, any Rails program becomes easy to dissect: it’s clear how the pieces fit together. MVC keeps your code nice and modular, great for debugging and maintenance.

In future articles I’ll discuss the inner details of MVC and how Rails forms work (another headache of mine). If you want a jumpstart on the nitty gritty, browse the Rails source and try to follow the path of a request:

  • WEBrick server modified to call the Rails routing library and dispatcher.
  • Rails Dispatcher actually creates the controller and passes it data.
  • ActionController Base defines many functions, including those to call a controller action (using appropriate defaults), render text, and return a response.

But all in good time my friends — I’ll explain it as I understand it. And if you had any forehead-slapping moments with MVC, drop me a note below.

]]>
https://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/feed/ 69
Build a site you (and your readers) will love https://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/ https://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/#comments Sun, 05 Aug 2007 00:05:48 +0000 http://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/ I’m thrilled by the recent attention and your feedback. Seeing your “Aha!” moments motivates me to write — though I’ve been neglectful lately. I’m busy, the dog ate my browser, the draft’s in the email… you know the drill. If you need an explanation fix, check out my old site from college:

http://www.cs.princeton.edu/~kazad/resources.htm

It has many posts I’ll be revising and importing over time.

This post is for betterexplained newcomers and old-timers: the how and why of the site. If you like my approach, it’s a guide to writing. Otherwise it’s your own list of advice to avoid.

Find your purpose

Blogging is introspective. I’ve realized my interests after much thought:

  • I like math, writing, computers, business, personal development, communication, and learning.
  • I cringe when ideas are explained poorly. Jargon and complicated explanations discourage the beginner. It shows you don’t really know the material. I get upset thinking that a poor explanation may turn someone away from a field forever, and want to fix that.
  • I have many beliefs about education. Insight beats memorization. Any subject (anything!) can be explained simply if you understand it well enough. Curiosity and passion are enough to conquer a subject.

I’ve always wanted to share hard-won ideas and save other people mental anguish — Better Explained has been a nagging thought in my mind. Today it’s alive with a purpose:

To explain topics clearly, intuitively, and share the “a-ha!” moments that make learning fun. Any subject can be better explained; today it’s just me writing, but I want to catalog insights from everyone.

This vision excites me — find the one that motivates you.

Be yourself (it’s harder than you think)

Writing naturally is hard. When you put pen to paper, fingers to keyboard, or stand before an audience, you stiffen. You get self conscious. You don’t act like yourself.

Fortunately this feeling disappears with practice. You stop pontificating; you explain. You don’t “write an article”; you have a conversation. You use humor, stories, and personal examples instead of abstract generalities. You write even if people won’t agree with everything you say.

Use your talents in whatever combination you can.

But if you want something extraordinary, you have two paths:

1. Become the best at one specific thing.

2. Become very good (top 25%) at two or more things.

Scott Adams

I feel my greatest talents are being curious, having enthusiasm and wanting things to be simple. I’m no expert. But I’m going to learn what I can and share it in the most intuitive way possible. Someone I admire feels similarly:

I have no special talents. I am only passionately curious.

–Albert Einstein

Write what you know; link what you don’t

You may not be an expert (I’m not), but you’ve collected nuggets of information and personal insights that nobody else has. Share them in your own style.

Then link to wikipedia, delicious, and the detailed articles so readers can learn the nitty gritty. Eventually you’ll learn the nitty gritty too, have your own insights, and simplify them into a new article.

Write well

Writing well is hard. Really hard. My definition means:

  • Timeless content that is still relevant in a year.
  • Original thought and deep insights that aren’t immediately obvious. If sharing details, organize them in a clever way.
  • Fun to read. Write for people. Use humor, quotes, stories. Remember: I’m Kalid, you’re you, and we’re having a conversation. This is no textbook.
  • Succinct, clear, and organized. I want to pump ideas into your head as fast as possible (I hope you don’t mind). Fewer words = faster intake = happier user.

That’s the goal, not that I always reach it.

Why write quality, not quantity? In my experience, an outstanding post trumps a dozen average ones. Top posts create traffic, links, diggs, and get people talking. You receive emails and comments which make your day and motivate you to write more, and better. Sub-par posts dilute your site and waste time.

Astound visitors with the quality of your content. Define your own quality bar and run towards it. Be merciless when revising. Don’t be afraid to fix up old posts — streamlining previous articles is good practice.

Just write

Blogging has no holy book. This is a non-fiction site about math and programming topics; a poetry blog has different goals. I don’t know your goals, so just write and push your own bar. You can be top-quality in your field.

I think I have above-average interest in math, science, simplicity, education, curiosity, and passion. The combination lead to my style and the focus of this site. I’m thrilled that others seem to like it too. Find your style; someone will like it.

Pace yourself

Writing on a consistent schedule is hard — if you’ve mastered the secret, let me know. I have dozens of posts in various draft forms, and it seems I need a Herculean effort to go back and revise them. Some posts stream out of my head and I’m done in a few hours. Others weigh over me for days or weeks, requiring a flurry of energy to finish and clean up.

I suggest an “articles” folder to collect your thoughts, in whatever stage. Sometimes you just have a sentence or two, but it can grow into a whole post over time.

I’ve learned writing isn’t all fun, even on topics you enjoy. Editing can be painful — push yourself through.

Keep learning

My opinions were shaped by these authors:

Good luck in your writing. Now that you know my passions, I’m interested in what you care about. Drop me a note anytime.

]]>
https://betterexplained.com/articles/build-a-site-you-and-your-readers-will-love/feed/ 41
Starting Ruby on Rails: What I Wish I Knew https://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/ https://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/#comments Sun, 17 Jun 2007 04:10:58 +0000 http://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/ Ruby on Rails is an elegant, compact and fun way to build web applications. Unfortunately, many gotchas await the new programmer. Now that I have a few rails projects under my belt, here’s my shot at sparing you the suffering I experienced when first getting started.

Tools: Just Get Them

Here’s the tools you’ll need. Don’t read endless reviews trying to decide on the best one; start somewhere and get going.

But What Does It All Mean?

“Ruby on Rails” is catchy but confusing. Is Rails some type of magical drug that Ruby is on? (Depending on who you ask, yes.)

Ruby is a programming language, similar to Python and Perl. It is dynamically typed (no need for “int i”), interpreted, and can be modified at runtime (such as adding new methods to classes). It has dozens of shortcuts that make it very clean; methods are rarely over 10 lines. It has good RegEx support and works well for shell scripting.

Rails is a gem, or a Ruby library. Some gems let you use the Win32 API. Others handle networking. Rails helps make web applications, providing classes for saving to the database, handling URLs and displaying html (along with a webserver, maintenance tasks, a debugging console and much more).

IRB is the interactive Ruby console (type “irb” to use). Rails has a special IRB console to access your web app as it is running (excellent for live debugging).

Rake is Ruby’s version of Make. Define and run maintenance tasks like setting up databases, reloading data, backing up, or even deploying an app to your website.

Erb is embedded Ruby, which is like PHP. It lets you mix Ruby with HTML (for example):

<div>Hello there, <%= get_user_name() %></div>

YAML (or YML) means “YAML Ain’t a Markup Language” — it’s a simple way to specify data:

{name: John Smith, age: 33}

It’s like JSON, much leaner than XML, and used by Rails for setting configuration options (like setting the database name and password).

Phew! Once Ruby is installed and in your path, you can add the rails gem using:

gem install rails

In general, use gem install “gem_name”, which searches online sources for that library. Although Rails is “just another gem”, it is the killer library that brought Ruby into the limelight.

Understanding Ruby-Isms

It’s daunting to learn a new library and a new language at the same time. Here are some of the biggest Ruby gotchas for those with a C/C++/Java background.

Ruby removes unnecessary cruft: (){};

  • Parenthesis on method calls are optional; use print "hi".
  • Semicolons aren’t needed after each line (crazy, I know).
  • Use “if then else end” rather than braces.
  • Parens aren’t needed around the conditions in if-then statements.
  • Methods automatically return the last line (call return explicitly if needed)

Ruby scraps the annoying, ubiquitous punctuation that distracts from the program logic. Why put parens ((around),(everything))? Again, if you want parens, put ‘em in there. But you’ll take off the training wheels soon enough.

The line noise (er, “punctuation”) we use in C and Java is for the compiler’s benefit, not ours. Be warned: after weeks with Ruby, other languages become a bit painful to read.

def greet(name)              # simple method
   "Hello, " + name          # returned automatically
end

greet "world"                # ==> "Hello, world"

Those Funny Ruby Variables

  • x = 3 is a local variable for a method or block (gone when the method is done)
  • @x = 3 is a instance variable owned by each object (it sticks around)
  • @@x = 3 is a class variable shared by all objects (it sticks around, too).
  • :hello is a symbol, like a constant string. Useful for indexing hashes. Speaking of which…
  • dictionary = { :cat => "Goes meow", :dog => "Barks loud."} is a hash of key/value pairs. Access elements with dictionary[:cat].

Those Funny Ruby Assignments

Ruby has the || operator which is a bit funky. When put in a chain

x = a || b || c || "default"

it means “test each value and return the first that’s not false.” So if a is false, it tries b. If b is false, it tries c. Otherwise, it returns the string “default”.

If you write x = x || "default" it means “set x to itself (if it has a value), otherwise use the default.” An easier way to write this is

x ||= "default"

which means the same: set x to the default value unless it has some other value. You’ll see this a lot in Ruby programs.

Those Funny Ruby Blocks

Ruby has “blocks”, which are like anonymous functions passed to a loop or another function. These blocks can specify a parameter using |param| and then take actions, call functions of their own, and so on. Blocks are useful when applying some function to each element of an array. It helps to think of them as a type of anonymous function that can, but doesn’t have to, take a parameter.

3.times do |i|
   print i*i
end

In this example, the numbers 0,1 and 2 are passed to a block (do… end) that takes a single parameter (i) and prints i squared. The output would be 0, followed by 1 followed by 4 (and looks like “014″ since we didn’t include spaces). Blocks are common in Ruby but take some getting used to, so be forewarned.

These are the Ruby lessons that were tricky when starting out. Try Why’s Poignant Guide To Ruby for more info (“Why” is the name of the author… it confused me too).

Understanding Rails-isms

Rails has its own peculiarities. “Trust us, it’s good for you.” say the programmers. It’s true – the features/quirks make Rails stand out, but they’re confusing until they click. Remember:

  • Class and table names are important. Rails has certain naming conventions; it expects objects from the class Person to be saved to a database table named people. Yes, Rails has a pluralization engine to figure out what object maps to what table (I kid you not). This magic is great, but scary at first when you’re not sure how classes and tables are getting linked together.
  • Many methods take an “options” hash as a parameter, rather than having dozens of individual parameters. When you see

    link_to “View Post”, :action => ‘show’, :controller => ‘article’, :id => @article

The call is really doing this:

link_to("View Post", {:action => 'show', :controller => 'article', :id => @article})

There are only two parameters: the name (“View Post”) and a hash with 3 key/value pairs. Ruby lets us remove the extra parens and braces, leaving the stripped-down function call above.

Understanding The Model-View-Controller Pattern

Rails is built around the model-view-controller pattern. It’s a simple concept: separate the data, logic, and display layers of your program. This lets you split functionality cleanly, just like having separate HTML, CSS and Javascript files prevents your code from mushing together. Here’s the MVC breakdown:

  • Models are classes that talk to the databse. You find, create and save models, so you don’t (usually) have to write SQL. Rails has a class to handle the magic of saving to a database when a model is updated.
  • Controllers take user input (like a URL) and decide what to do (show a page, order an item, post a comment). They may initially have business logic, like finding the right models or changing data. As your rails ninjitsu improves, constantly refactor and move business logic into the model (fat model, skinny controller). Ideally, controllers just take inputs, call model methods, and pass outputs to the view (including error messages).
  • Views display the output, usually HTML. They use ERB and this part of Rails is like PHP – you use HTML templates with some Ruby variables thrown in. Rails also makes it easy to create views as XML (for web services/RSS feeds) or JSON (for AJAX calls).

The MVC pattern is key to building a readable, maintainable and easily-updateable web app.

Understanding Rails’ Directory Structure

When you create your first rails app, the directories are laid out for you. The structure is well-organized: Models are in app/models, controllers in app/controllers, and views in app/my_local_views (just kidding).

The naming conventions are important – it lets rails applications “find their parts” easily, without additional configuration. Also, it’s very easy for another programmer to understand and learn from any rails app. I can take a look at Typo, the rails blogging software, and have a good idea of how it works in minutes. Consistency creates comprehension.

Understanding Rails’ Scaffolding

Scaffolding gives you default controller actions (URLs to visit) and a view (forms to fill out) to interact with your data — you don’t need to build an interface yourself. You do need to define the Model and create a database table.

Think of scaffolds as the “default” interface you can use to interact with your app – you’ll slowly override parts of the default as your app is built. You specify scaffolds in the controller with a single line:

scaffold :person

and it adds default actions and views for showing, editing, and creating your “Person” object. Rails forms take some getting used to, so scaffolding helps a lot in the initial stages.

More Tips and Tricks

I originally planned on a list of tips & tricks I found helpful when learning rails. It quickly struck me that Ruby on Rails actually requires a lot of background knowledge, and despite (or because of) its “magic”, it can still be confusing. I’ll get into my favorite tricks in an upcoming article.

As you dive further into web development, these guides may be helpful:

Until next time, enjoy these amusing videos:

]]>
https://betterexplained.com/articles/starting-ruby-on-rails-what-i-wish-i-knew/feed/ 117