Permalink
Browse files

Add a post about dot syntax

  • Loading branch information...
1 parent 9acaf52 commit 489ead2b2523bad19d8659e7c0dc9f5dbb5f6ae9 @robdodson committed May 1, 2012
@@ -3,7 +3,7 @@ layout: post
title: "A Basic RVM Tutorial for Rails 3"
date: 2011-09-23 07:33
comments: true
-categories: rvm rails rails3 ruby chain
+categories: [RVM, Rails, Rails 3, Ruby]
---
###What is RVM?
@@ -3,7 +3,7 @@ layout: post
title: "How to setup PostgreSQL for Rails and Heroku"
date: 2012-04-27 07:33
comments: true
-categories: ruby rails rails3 postgresql heroku chain
+categories: [Ruby, Rails, Rails 3, PostgreSQL, Heroku, Chain]
---
###Install PostgreSQL Locally
@@ -3,7 +3,7 @@ layout: post
title: "Playing with Ruby Dates"
date: 2012-04-28 07:20
comments: true
-categories: ruby date chronic active_support chain
+categories: [Ruby, Date, Chronic, Active Support, Chain]
---
One of [my previous projects](https://vimeo.com/40633070) involved a ton of work using Flash's built in Date object. We ended up rolling our own Calendar library which was both tedious and time consuming to debug. Now that I'm digging into Ruby for my newest project, I wanted to see what features the language has to offer. So far I'm *really* impressed and that's after only a few hours of exploration. I'll detail some of the tricks I've learned along the way so hopefully other newcomers can benefit.
@@ -3,7 +3,7 @@ layout: post
title: "How to Run Tests in Sublime Text"
date: 2012-04-29 09:26
comments: true
-categories: sublime tdd ruby rspec chain
+categories: [Sublime, TDD, Ruby, RSpec, Chain]
---
If you're lazy like me then you love to automate as much of your process as possible. Running tests from within your IDE is one of those tasks that screams for a keyboard shortcut. In full featured tools like RubyMine or Eclipse this is usually pretty straightforward. However many developers in the Ruby community seem to prefer more lightweight tools like TextMate, Vim and Sublime. Today we'll look at how to setup RubyTest in Sublime Text 2 so we can easily run tests with just a few hotkeys. The tests will be written in [Rspec](http://rspec.info/) which should be familiar to most Rubyists.
@@ -3,7 +3,7 @@ layout: post
title: "Custom Domain with Octopress and Github Pages"
date: 2012-04-30 06:52
comments: true
-categories: octopress blogging chain
+categories: [Octopress, Writing, Chain]
---
*I'm going to try to write this as a bit of a lightening post to see if I can bring down the time it takes me to produce something.*
@@ -0,0 +1,167 @@
+---
+layout: post
+title: "Ruby Objects and Dot Syntax"
+date: 2012-05-01 07:37
+comments: true
+categories: [Chain, Ruby, Data Structures]
+---
+
+Coming from JavaScript I'm very accustomed to doing something like this:
+
+``` javascript Javascript
+var person = { name: 'Rob', city: 'San Francisco' }
+
+console.log( person.city ); // 'San Francisco'
+
+```
+
+Using dot syntax to access a `Hash` is second nature to me. That's why I was surprised when I ran into the following error yesterday while writing some Ruby.
+
+``` ruby Ruby
+person = {name: 'Rob', city: 'San Francisco'}
+ => {:name=>"Rob", :city=>"San Francisco"}
+
+puts person.city
+
+NoMethodError: undefined method `city' for {:name=>"Rob", :city=>"San Francisco"}:Hash
+```
+
+"Hmm, weird," I thought. I know I've seen dot syntax used in Ruby before..what gives?
+
+### Dot Syntax and the Ruby Hash Object
+As it turns out Ruby does not support dot syntax for the `Hash` object. If I had wanted to access the `city` property from my previous example I should have done it using the symbol key like so:
+
+``` ruby
+person[:city]
+ => "San Francisco"
+```
+
+There are a few data structures that are very similar to `Hashes` and seeing those used in the wild perhaps threw me off. So I figured I'd write a post about the do's and dont's of dot syntax and how different object types react to it.
+
+#### Class
+The first and most obvious one is the `Class` object. Really I'm talking about instances of a `Class` here, for example an instance of class `Person` might have a `city` attribute. Here's what that would look like.
+
+```ruby Person: Long Version
+class Person
+ def initialize(name, city)
+ @name = name
+ @city = city
+ end
+
+ def name
+ @name
+ end
+
+ def city
+ @city
+ end
+end
+
+person = Person.new('Rob', 'San Francisco')
+ => #<Person:0x007ff15412a8c0 @name="Rob", @city="San Francisco">
+
+person.city
+ => "San Francisco"
+```
+Since I've defined methods for both `name` and `city`, using dot syntax to access those properties basically means we're calling those methods. The methods just return the instance variables, acting as getters. You can shorten this by using `attr_reader` or `attr_accessor`.
+
+```ruby Person: Short Version
+class Person
+ attr_accessor :name, :city
+ def initialize(name, city)
+ @name = name
+ @city = city
+ end
+end
+
+person = Person.new('Rob', 'San Francisco')
+ => #<Person:0x007ff15412a8c0 @name="Rob", @city="San Francisco">
+
+person.city
+ => "San Francisco"
+```
+
+#### Struct
+The `Struct` object is another commonly used element which allows dot access to its attributes. Quoting from [the documentation](http://www.ruby-doc.org/core-1.9.3/Struct.html):
+>A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.
+
+Examples speak louder than words so here's our `Person` again.
+
+```ruby Person Struct
+Person = Struct.new(:name, :city)
+ => Person
+
+person = Person.new('Rob', 'San Francisco')
+ => #<struct Person name="Rob", city="San Francisco">
+
+person.city
+ => "San Francisco"
+```
+As I understand it a `Struct` is basically sealed after you've given it an initial definition. This means that you can't keep tacking on properties like you can with a `Hash`
+
+```ruby
+# Continuing from above...
+
+person.age = 28
+NoMethodError: undefined method `age=' for #<struct Person name="Rob", city="San Francisco">
+
+person[:age] = 28
+NameError: no member 'age' in struct
+```
+
+#### OpenStruct
+Finally we come to the `OpenStruct` which has both dynamic attributes and dot syntax. [The documentation describes it like so](http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html):
+>An OpenStruct is a data structure, similar to a Hash, that allows the definition of arbitrary attributes with their accompanying values.
+
+And again here is our `Person` from before. Note that `OpenStruct` needs you to `require` it.
+```ruby Person OpenStruct
+require 'ostruct'
+
+person = OpenStruct.new
+ => #<OpenStruct>
+
+person.name = 'Rob'
+ => "Rob"
+
+person.city = 'San Francisco'
+ => "San Francisco"
+
+person.city
+ => "San Francisco"
+```
+
+If you noticed, we didn't need to define the attributes of our `Person` before creating an instance of it. This means we could keep adding attributes indefinitely. Want your person to respond to `age`? Just tack it on.
+
+```ruby
+person.age = 28
+ => 28
+
+person.age
+ => 28
+```
+
+For the sake of brevity you can pass in a `Hash` and `OpenStruct` will covert it for you.
+```ruby
+require 'ostruct'
+
+person = OpenStruct.new(name: 'Rob', city: 'San Francisco')
+ => #<OpenStruct name="Rob", city="San Francisco">
+
+person.city
+ => "San Francisco"
+```
+This all seems wonderful but there's one huge caveat which comes from the way `OpenStruct` finds all of these dynamic attributes. As [the documentation describes it](http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html):
+
+>An OpenStruct utilizes Ruby’s method lookup structure to and find and define the necessary methods for properties. This is accomplished through the method method_missing and define_method.
+
+>This should be a consideration if there is a concern about the performance of the objects that are created, as there is much more overhead in the setting of these properties compared to using a Hash or a Struct.
+
+Definitely keep that in mind if you're writing time sensitive code. In those situations you'll want to use a `Hash` or a `Struct` instead.
+
+<small>Source:<br />
+[http://www.ruby-doc.org/core-1.9.3/Class.html](http://www.ruby-doc.org/core-1.9.3/Class.html)<br />
+[http://www.ruby-doc.org/core-1.9.3/Struct.html](http://www.ruby-doc.org/core-1.9.3/Struct.html)<br />
+[http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html](http://ruby-doc.org/stdlib-1.9.3/libdoc/ostruct/rdoc/OpenStruct.html)<br />
+[http://stackoverflow.com/questions/9356704/unable-to-use-dot-syntax-for-ruby-hash](http://stackoverflow.com/questions/9356704/unable-to-use-dot-syntax-for-ruby-hash)<br />
+[http://www.rubyist.net/~slagell/ruby/accessors.html](http://www.rubyist.net/~slagell/ruby/accessors.html)
+</small>

0 comments on commit 489ead2

Please sign in to comment.