Best ruby questions in February 2011

Lisp and Erlang Atoms, Ruby and Scheme Symbols. How useful are they?

34 votes

How useful is the feature of having an atom data type in a programming language?

A few programming languages have the concept of atom or symbol to represent a constant of sorts. There are a few differences among the languages I have come across (Lisp, Ruby and Erlang), but it seems to me that the general concept is the same. I am interested in programming language design, and I was wondering what value does having an atom type provide in real life. Other languages such as Python, Java, C# seem to be doing quite well without it.

I have no real experience of Lisp or Ruby (I know the syntaxes, but haven't used either in a real project). I have used Erlang enough to be used to the concept there.

A short example that shows how the ability to manipulate symbols leads to cleaner code: (Code is in Scheme, a dialect of Lisp).

(define men '(socrates plato aristotle))

(define (man? x) 
    (contains? men x))

(define (mortal? x) 
    (man? x))

;; test

> (mortal? 'socrates)
=> #t

You can write this program using character strings or integer constants. But the symbolic version has certain advantages. A symbol is guaranteed to be unique in the system. This makes comparing two symbols as fast as comparing two pointers. This is obviously faster than comparing two strings. Using integer constants allows people to write meaningless code like:

(define SOCRATES 1)
;; ...

(mortal? SOCRATES)
(mortal? -1) ;; ??

Probably a detailed answer to this question could be found in the book Common Lisp: A Gentle Introduction to Symbolic Computation.

Ruby craziness: Class vs Object?

12 votes

Hi,

I just started playing with JRuby. This is my first ruby post. I had a hard time understanding classes vs objects in Ruby. It doesnt mean like what classes & objects in other Object oriented laguages. for an example

Class.is_a? Object

returns true and

Object.is_a? Object

too.

so class & Object are both objects

here comes another one

Class.is_a? Class

returns true and

Object.is_a? Class

too.

wait, i am not done yet

 Object.instance_of? Class
 Class.instance_of? Class

Both are true

 Object.instance_of? Object
 Class.instance_of? Object

Both are false. right, nothing can be instance of object.

And

 Class.kind_of? Class
 Object.kind_of? Class

both are true

 Class.kind_of? Object
 Object.kind_of? Object

both are true

So both are exactly same, then why do we have both these.?

After some more digging, i wrote this simple method to return method list supported by both

irb(main):054:0> def print_methods(obj)
irb(main):055:1>    obj.methods.each do |mm|
irb(main):056:2*        puts mm
irb(main):057:2>    end
irb(main):058:1> end

Only method difference between print_methods(Object) and print_methods(Class) is

     Nesting

if Nesting means inheritance, Is Object similar to the sealed class??

Can someone clarify me what is all this?

Update: To Edds comment

Interestingly i see lot of differences in the method list in

c=Class.new
print_methods(c)

&

o=Object.new
print_methods(o)

Now I understand Instance of a class is really an class instance (And this class instance is actually a Object) not an object instance. And even this instance allow me to span another instances

  xx = c.new //works - c is an Object / and xx is a instance of an Object c
  yy = o.new //nope  - o is already a instance of an Object, so it cannot be instantiated again

So Finally, Object is really an instance of a Class. Because

  xx.is_a? Class 

is false, but

  xx.is_a? Object 

returns true

Am i right, ??

Cheers

(This question has been successfully answered already, but since this is an important topic, another answer can't hurt)

Basically the key thing to understand is that every class is an instance of the Class class and every class (in 1.8) is a subclass of Object. So every class is an object in the sense that it is an instance of a subclass of Object, i.e. Class.

Of course this means that Class is an instance of itself. If that makes your brain hurt, just don't think about it too deeply.

Object and Class are is_a? Object

x.is_a? y returns true if x.class == y or x.class < y, i.e. if x's class is y or x's class inherits from y. Since every class inherits from object x.is_a? Object returns true no matter what x is. (In 1.8 anyway, in 1.9 there's also BasicObject which is now the most basic class in the inheritance hierarchy).

They are also is_a? Class

Both Object and Class are indeed classes, so that should not be surprising.

They are also instance_of? Class, but not instance_of? Object.

Unlike is_a?, x.instance_of? y only returns true if x.class == y, not if x.class is a subclass of y. So since both x and y are instance_of? Class, they're not instance_of? Object.

right, nothing can be instance of object.

That's not true. Object.new.instance_of? Object is true.

kind_of?

kind_of? is an alias for is_a?, so see above.

So both are exactly same, then why do we have both these.?

It should be pointed out that everything up to now is true for all classes. E.g. String.is_a? Object, String.is_a? Class and String.instance_of? Class are true and String.instance_of? Object is false for the same reasons as above. (Also String.is_a? String and String.instance_of? String are both false for the same reasons - String is a class, not a string).

You can not conclude from that all the classes are the same. They're just all instances of the same class.

Comparing methods

Since both Object and Class are classes, they both have all the instance methods defined by Class. Class additionally has the singleton method nesting. nesting tells you which module you're currently nested in, it has nothing to do with inheritance.

For any given class TheClass.methods will return the instance methods defined by Class (e.g. superclass which returns the class which TheClass inherits from, and new which creates a new instance of TheClass) plus the singleton methods defined by that class.

Anyway method only tells you which methods can be called directly on a given object. It does not tell you which methods can be called on an instance of a class. For that you can use instance_methods which returns significantly different results for Object and Class.

How to learn TDD with Ruby?

11 votes

I have been using ruby exclusively for about a month and I really love it. However, I am having an incredibly hard time using, or even learning TDD. My brain just doesn't function that way...

I really, really want to learn TDD but to be honest I am a bit confused. All the articles that I find when Googling around are mostly specific to Rails, which is not interesting to me because I want to learn how to do efficient testing for any ruby application, from the simple one-file script to the complicated gem, not for Web apps. Also, there are so many frameworks and so few tutorials to get started.

Could anybody give me any advice on how to learn TDD so that I can at least start to consider myself an aspiring rubyist?

The best way to learn TDD is by just doing it. I suggest you build a new project using TDD. This means don't write any non-testing code unless you have a failing test.

It will make you think about writing tests: I want to write this code, how do I write a test for it so I can write it.

It will show you the layered nature of testing. Instead of want a name that is required and can't contain numbers. you'll first test setting and reading a name, test requiring the name, test it shouldn't contain numbers, than think if it has more constraints and test those.

Remember:

  • Write a test before you write the code
  • Make sure the test fails! It's important to know you're testing logic is correct
  • Before writing the next test make sure all tests succeed
  • You can always clean up your code, if the tests keep working you didn't change the design

Using Sinatra for larger projects via multiple files

10 votes

It seems that in Sinatra all route handlers are being written into a single file, if I understand right it acts as a one large/small controller. Is there any way to split it into separate independent files, so when let's say somebody calls "/" - one action is executed, and if smth like "/posts/2" is received then another action - similar logic that is applied in PHP?

Here is a basic template for Sinatra apps that I use. (My larger apps have 200+ files broken out like this, not counting vendor'd gems, covering 75-100 explicit routes. Some of these routes are Regexp routes covering an additional 50+ route patterns.) When using Thin, you run an app like this using:
thin -R config.ru start

Edit: I'm now maintaining my own Monk skeleton based on the below called Riblits. To use it to copy my template as the basis for your own projects:

# Before creating your project
monk add riblits git://github.com/Phrogz/riblits.git

# Inside your empty project directory
monk init -s riblits

File Layout:

config.ru
app.rb
helpers/
  init.rb
  partials.rb
models/
  init.rb
  user.rb
routes/
  init.rb
  login.rb
  main.rb
views/
  layout.haml
  login.haml
  main.haml

 
config.ru

root = ::File.dirname(__FILE__)
require ::File.join( root, 'app' )
run MyApp.new

 
app.rb

# encoding: utf-8
require 'sinatra'
require 'haml'

class MyApp < Sinatra::Application
  enable :sessions

  configure :production do
    set :haml, { :ugly=>true }
    set :clean_trace, true
  end

  configure :development do
    # ...
  end

  helpers do
    include Rack::Utils
    alias_method :h, :escape_html
  end
end

require_relative 'models/init'
require_relative 'helpers/init'
require_relative 'routes/init'

 
helpers/init.rb

require_relative 'partials'

 
helpers/partials.rb

# encoding: utf-8
require 'sinatra/base'

module Sinatra
  module PartialPartials
    ENV_PATHS = %w[ REQUEST_PATH PATH_INFO REQUEST_URI ] 
    def spoof_request( uri, headers=nil ) 
      new_env = env.dup 
      ENV_PATHS.each{ |k| new_env[k] = uri.to_s } 
      new_env.merge!(headers) if headers
      call( new_env ).last.join 
    end

    def partial( page, variables={} )
      haml page, {layout:false}, variables
    end
  end
  helpers PartialPartials
end

 
models/init.rb

require 'sequel'
DB = Sequel.postgres 'dbname', user:'bduser', password:'dbpass', host:'localhost'
DB << "SET CLIENT_ENCODING TO 'UTF8';"

require_relative 'users'

 
models/user.rb

class User < Sequel::Model
  # ...
end

 
routes/init.rb

require_relative 'login'
require_relative 'main'

 
routes/login.rb

class MyApp < Sinatra::Application
  get "/login" do
    @title  = "Login"
    haml :login
  end

  post "/login" do
    # Define your own check_login
    if user = check_login
      session[ :user ] = user.pk
      redirect '/'
    else
      redirect '/login'
    end
  end

  get "/logout" do
    session[:user] = session[:pass] = nil
    redirect '/'
  end
end

 
routes/main.rb

class MyApp < Sinatra::Application
  get "/" do
    @title = "Welcome to MyApp"        
    haml :main
  end
end

 
views/layout.haml

!!! XML
!!! 1.1
%html(xmlns="http://www.w3.org/1999/xhtml")
  %head
    %title= @title
    %link(rel="icon" type="image/png" href="/favicon.png")
    %meta(http-equiv="X-UA-Compatible" content="IE=8")
    %meta(http-equiv="Content-Script-Type" content="text/javascript" )
    %meta(http-equiv="Content-Style-Type" content="text/css" )
    %meta(http-equiv="Content-Type" content="text/html; charset=utf-8" )
    %meta(http-equiv="expires" content="0" )
    %meta(name="author" content="MeWho")
  %body{id:@action}
    %h1= @title
    #content= yield

What is the most concise Clojure equivalent for Ruby's Dir.glob()?

9 votes

What's the easiest way to do something like this in Clojure?

require 'csv'
Dir["data/*.csv"].each do |file|
  File.readlines(file).each do |line|
    x, y, z = *CSV.parse_line(line)
    # process this data
  end
end

Probably not the most concise possible, but perhaps something like the following?

(use 'clojure-csv.core)

(doseq [file (.listFiles (File. "data/"))]
  (if (.matches (.getName file) ".*[.]CSV$")
    (doseq [[x y z] (parse-csv (slurp file))]
       "... do whatever stuff you want with x, y, z..."))))

N.B. uses the clojure-csv library.

This would be more elegant and shorter if I could find an obvious way to get a filtered directory list without resorting to regexes.... but it eludes me for the moment

UPDATE:

Brian's link to Java support for globbing is also useful and interesting and offers a more general/robust approach than simple regexes - however it depends on Java 1.7 (too cutting edge for some?) and it doesn't really shorten the code much.

Playframework vs Ruby On Rails

9 votes

Yet another LanguageX vs LanguageY question....

Currently I have a bunch of apps built on playframework. For the most part I love it. Moving from PHP a few years ago was almost a religious experience -- an actual functional orm, much less boiler plate code, stuff just worked, etc.

I still have a website running on a a shared hosting service thats built with PHP+CodeIgniter. Recently I've been adding some features to this site and have been thinking about porting it to either Ruby on Rails or Playframework.

So far though, nothing about rails has really blown me away. It seems like it has pretty much the same featureset as playframework. I like ruby's terseness, and things like blocks, but again for the most part there's been nothing about the language itself that has made me go "oh wow this is 1000x better than java/php/c/whatever!" In fact, some parts actually kind of rub me the wrong way -- I prefer strongly-typed languages for example.

My question is, am I likely to find anything in the framework or language that's really going to differentiate it from java+play for me, or are they pretty much the same and primarily just differentiated by things like personal preference about syntax and developer community?

Play framework is gracious enough to acknowledge RoR's inspiration. (Unlike some people who copied an entire platform and give absolutely no credit to the original)

If Play team have done a good job, it's no wonder that a person is not impressed by RoR if he learned Play first. So if you find Play quite comfortable, there's no compelling reason to go RoR.

Error installing gems that use native extensions on Ubuntu, Ruby 1.9.2 via RVM

9 votes

I get an error while trying to install the ffi gem:

~ - 16:54>gem i ffi
Building native extensions.  This could take a while...
ERROR:  Error installing ffi:
        ERROR: Failed to build gem native extension.

        rake RUBYARCHDIR=/home/mdemare/.rvm/gems/ruby-1.9.2-p136/gems/ffi-1.0.6/lib RUBYLIBDIR=/home/mdemare/.rvm/gems/ruby-1.9.2-p136/gems/ffi-1.0.6/lib
/home/mdemare/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/site_ruby/1.9.1/rubygems.rb:370:in `bin_path': can't find gem rake ([">= 0"]) with executable rake (Gem::GemNotFoundException)
        from /home/mdemare/.rvm/gems/ruby-1.9.2-p136/bin/rake:19:in `<main>'

Gem files will remain installed in /home/mdemare/.rvm/gems/ruby-1.9.2-p136/gems/ffi-1.0.6 for inspection.
Results logged to /home/mdemare/.rvm/gems/ruby-1.9.2-p136/gems/ffi-1.0.6/gen/gem_make.out

I'm getting frequent errors of all kinds while installing gems with native extensions, so I assume that there's something broken with my Ubuntu installation, but I've no idea what. I'll post any information you need to diagnose the problem.

EDIT: When I cd to the ffi gem (mentioned in the second but last line), and run the rake line in line 6, I get "Could not find RubyGem rake-compiler".

After gem i rake-compiler, and run rake again, I get this:

configure: error: source directory already configured; run "make distclean" there first
make: *** [/home/mdemare/.rvm/gems/ruby-1.9.2-p136/gems/ffi-1.0.6/build/x86_64-linux/ffi_c/1.9.2/libffi/.libs/libffi_convenience.a] Error 1
rake aborted!
Command failed with status (2): [make...]

Update:

These are my rake gemspecs:

~ - 10:59>find ~/.rvm/ -name 'rake-0.8.7.gemspec'
~/.rvm/gems/ruby-1.9.2-p136/specifications/rake-0.8.7.gemspec
~/.rvm/gems/ruby-1.9.2-p136@global/specifications/rake-0.8.7.gemspec
~/.rvm/rubies/ruby-1.9.2-p136/lib/ruby/gems/1.9.1/specifications/rake-0.8.7.gemspec

The last one is where gem looks, but that gemspec is different from the first one, and doesn't include the executable. Copying the long one doesn't quite solve the problem though - I get a file not found for the rake executable.

This caused me a ton of aggravation at the Boston Hack Day when trying to install Vagrant (for which FFI is a dependency). I ended up wasting so much time that I switched machines to work around the problem.

After the fact, I found a hack that works (although I'm sure there's a better solution). The file that the error message is complaining about

~/.rvm/gems/ruby-1.9.2-p180/bin/rake

differs from other similar copies in that it's missing path setup stuff at the head, so I copied these lines from one of the files that had them:

[genericized per @danv's answer below. Thanks for the improvement!]

ENV['GEM_HOME']=ENV['GEM_HOME'] || '~/.rvm/gems/ruby-1.9.2-p180'
ENV['GEM_PATH']=ENV['GEM_PATH'] || '~/.rvm/gems/ruby-1.9.2-p180:~/.rvm/gems/ruby-1.9.2-p180@global'
ENV['PATH']='~/.rvm/gems/ruby-1.9.2-p180/bin:~/.rvm/gems/ruby-1.9.2-p180@global/bin:~/.rvm/rubies/ruby-1.9.2-p180/bin:' + ENV['PATH']

That fixed it for me. This was a new Ubuntu 10.10 install with no default Ruby installation (which could be part of the problem) and Ruby 1.9.2 installed using RVM. Lots of other gems installed fine, including those requiring native compilation, so the problem is something specific to FFI.

What's the best way to do multiple requires in Ruby?

6 votes

I'm not sure I've seen this addressed, but I am wondering what is the best way to do multiple requires in a ruby script. I have come up with a couple rudimentary examples which I will outline below, but I'm not sure if there is a best practice for this -- my search results have come back with nothing.

0) Bunch of includes & exceptions (I'll leave the rescue out)

require 'rubygems'
require 'builder'

1) String array

torequire = ['rubygems', 'builder']
begin
  torequire.each do |req|
    require req
rescue LoadError => e
  # Not sure if this is great either
  puts "Missing required gem: " + e.message.split[-1]
  exit
end

2) ??

Is there a large problem created from loading them all from a string array? You could specify version requirements or locations similarly, I'm just wondering if there is a problem with doing it this way.

The plain way is the best way.

You could do this, but it trades clarity for cleverness--a poor bargain:

[
  'rubygems',
  'rack',
  'rails'
].each(&method(:require))

Skip the "rescue" with the fancy error message. Everyone knows what it means when a require throws a stack trace.

If you want to make it easier for someone using your program to have the required gems installed, check out bundler.

Rails and partials, is there a more efficent way of writing this...?

6 votes

I've got a partial in a loop like so...

<% things.each do |thing| %><%= render :partial => "thingy", :locals => { :something  => something, :thing  => thing } %><% end %>

This just doesn't seem very railsy, I was wondering if there more efficient way of putting partials in a loop.

Rename your partial from 'thingy' to 'thing' and do this:

<%= render things, :locals => { :something => :goatse } %>

I couldn't think of anything more Railsy.

Initializing class instance variables in Ruby

5 votes

Hello everybody, I am working on a small rails app and have a problem with ruby's OOP model. I have the following simplified class structure.

class Foo
  protected
    @bar = []
    def self.add_bar(val)
      @bar += val
    end
    def self.get_bar
      @bar
    end
end

class Baz < Foo
  add_bar ["a", "b", "c"]
end

My problem is now, that when I call add_bar in the class definition of Baz, @bar is apparently not initialized and I get an error that the + Operator is not available for nil. Calling add_bar on Foo directly does not yield this problem. Why is that and how can I initialize @bar correctly?

To make clear what I want, I will point out the behavior I would expect from these classes.

Foo.add_bar ["a", "b"]
Baz.add_bar ["1", "2"]
Foo.get_bar # => ["a", "b"]
Baz.get_bar # => ["a", "b", "1", "2"]

How could I achieve this?

Short answer: instance variables don't get inherited by subclasses

Longer answer: the problem is that you wrote @bar = [] in the body of the class (outside any method). When you set an instance variable, it is stored on whatever is currently self. When you're in a class body, self is the class object Foo. So, in your example, @foo gets defined on the class object Foo.

Later, when you try to look up an instance variable, Ruby looks in whatever is currently self. When you call add_bar from Baz, self is Baz. Also self is STILL Baz in the body of add_bar (even though that method is in Foo). So, Ruby looks for @bar in Baz and can't find it (because you defined it in Foo).

Here's an example that might make this clearer

class Foo
  @bar = "I'm defined on the class object Foo. self is #{self}"

 def self.get_bar
    puts "In the class method. self is #{self}"    
    @bar
  end

  def get_bar
    puts "In the instance method. self is #{self} (can't see @bar!)"
    @bar
  end
end

>> Foo.get_bar
In the class method. self is Foo
=> "I'm defined on the class object Foo. self is Foo"

>> Foo.new.get_bar
In the instance method. self is #<Foo:0x1056eaea0> (can't see @bar!)
=> nil

This is admittedly a bit confusing, and a common stumbling point for people new to Ruby, so don't feel bad. This concept finally clicked for me when I read the 'Metaprogramming' chapter in Programming Ruby (aka "The Pickaxe").

How I'd solve your problem: Look at Rails' class_attribute method. It allows for the sort of thing you're trying to do (defining an attribute on a parent class that can get inherited (and overidden) in its subclasses).

How can I use Nokogiri to write a HUGE XML file?

5 votes

I have a Rails application that uses delayed_job in a reporting feature to run some very large reports. One of these generates a massive XML file and it can take literally days in the bad, old way the code is written. I thought that, having seen impressive benchmarks on the internet, Nokogiri could afford us some nontrivial performance gains.

However, the only examples I can find involve using the Nokogiri Builder to create an xml object, then using .to_xml to write the whole thing. But there isn't enough memory in my zip code to handle that for a file of this size.

So can I use Nokogiri to stream or write this data out to file?

Nokogiri is designed to build in memory because you build a DOM and it converts it to XML on the fly. It's easy to use, but there are trade-offs, and doing it in memory is one of them.

You might want to look into using Erubis to generate the XML. Rather than gather all the data before processing and keeping the logic in a controller, like we'd do with Rails, to save memory you can put your logic in the template and have it iterate over your data, which should help with the resource demands.

If you need the XML in a file you might need to do that using redirection:

erubis options templatefile.erb > xmlfile

This is a very simple example, but it shows you could easily define a template to generate XML:

<% 
asdf = (1..5).to_a 
%>
<xml>
  <element>
<% asdf.each do |i| %>
    <subelement><%= i %></subelement>
<% end %>
  </element>
</xml>

which, when I call erubis test.erb outputs:

<xml>
  <element>
    <subelement>1</subelement>
    <subelement>2</subelement>
    <subelement>3</subelement>
    <subelement>4</subelement>
    <subelement>5</subelement>
  </element>
</xml>

EDIT:

The string concatenation was taking forever...

Yes, it can simply because of garbage collection. You don't show any code example of how you're building your strings, but Ruby works better when you use << to append one string to another than when using +.

It also might work better to not try to keep everything in a string, but instead to write it immediately to disk, appending to an open file as you go.

Again, without code examples I'm shooting in the dark about what you might be doing or why things run slow.

Decoding Facebook's signed request in Ruby/Sinatra

5 votes

Due to Facebook deprecating new FBML, I'm looking for a new way to create a "reveal" tab (a page tab that shows one version to fans and another to non-fans). Facebook has added data to the signed_request:

When a user selects your app in the left-hand menu, the app will receive the signed_request parameter with one additional parameter, page, a JSON array which contains the ‘id’ of the Facebook Page your Tab is hosted within, a boolean (‘liked’) indicating whether or not a user has liked the Page, and a boolean (‘admin’) indicating whether or not the user is an ‘admin’ of the Page along with the user info array.

I'm able to read the signed_request fine, but then I need to process it with base64url decoding to get the correct JSON. Additionally, I've found in my research that the JSON is improperly formatted for Ruby so needs to be modified prior to decoding it. Here's the current code (I'm just printing the signed request in index.erb for now):

helpers do
  def base64_url_decode str
    encoded_str = str.gsub('-','+').gsub('_','/')
    encoded_str += '=' while !(encoded_str.size % 4).zero?
    Base64.decode64(encoded_str)
  end

  def decode_data str
    encoded_sig, payload = str.split('.')
    data = ActiveSupport::JSON.decode base64_url_decode(payload)
  end
end

get '/' do
  signed_request = params[:signed_request]
  @signed_request = decode_data(signed_request)
  erb :index
end

I'm trying to keep the application as light as possible and avoid using a full Facebook library as this won't be a full application (just a tab) and won't require any additional permissions from users. Any recommendations as to my method for detecting fans are welcome as well.

This is what ended up working for me. The fbgraph library sounds like it might be a good solution but I didn't try it was I wanted to keep things lightweight. I've got the final template I created on github at https://github.com/andershaig/iFrame-Tab-Reveal-Skeleton

In setting up the Facebook application I point the custom tab URL to my-domain-name.com/pathfinder so I could use the base URL as the application canvas page.

# Detect Fan status and redirect
post '/pathfinder' do
  @encoded_request = params[:signed_request]
  @json_request = decode_data(@encoded_request)
  @signed_request = Crack::JSON.parse(@json_request)
  if @signed_request['page']['liked']
    erb :unlocked
  else
    erb :locked
  end
end

Why use Ruby's attr_accessor, attr_reader and attr_writer?

5 votes

So Ruby has this handy and convenient way to "share" instance variables by using keys like

attr_accessor :var
attr_reader :var
attr_writer :var

And I use them quite often, but my question is: Why would I choose attr_reader or attr_writer if I could simply use attr_accessor? Is there something like, dunno, performance (which I doubt)?

I guess there is a reason, otherwise they wouldn't have made such keys, eh?

You may use the different accessors to communicate your intent to someone reading your code, and makes it easier to write classes which will work correctly no matter how their public API is called.

class Person
  attr_accessor :age
  ...
end

Here, I can see that I may both read and write the age.

class Person
  attr_reader :age
  ...
end

Here, I can see that I may only read the age. Presumably, it is set by the constructor of this class and remains constant. If there were a mutator (writer) for age and the class were written assuming that age, once set, does not change, then a bug could result from code calling that mutator.

But what is happening behind the scenes?

If you write:

attr_writer :age

That gets translated into:

def age=(value)
  @age = value
end

If you write:

attr_reader :age

That gets translated into:

def age
  @age
end

If you write:

attr_accessor :age

That gets translated into:

def age=(value)
  @age = value
end

def age
  @age
end

Knowing that, here's another way to think about it: If you did not have the attr_... helpers, and had to write the accessors yourself, would you write any more accessors than your class needed? For example, if age only needed to be read, would you also write a method allowing it to be written?

How do I specify that I want Vim to treat .ru files like .rb files

5 votes

Whenever I use Vim with Ruby files, I get nice coloring and automatic indention on blocks. However, when I am editing a Rack file, I don't get these things. How can I extend my Vim/Ruby configuration with my Rack files?

Put this in your vimrc to tell vim to associate *.ru files with ruby syntax highlighting.

au BufRead,BufNewFile *.ru setfiletype ruby