-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
298 lines (200 loc) · 18 KB
/
Copy pathindex.html
File metadata and controls
298 lines (200 loc) · 18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
<!DOCTYPE html>
<!--[if IEMobile 7 ]><html class="no-js iem7"><![endif]-->
<!--[if lt IE 9]><html class="no-js lte-ie8"><![endif]-->
<!--[if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)]><!--><html class="no-js" lang="en"><!--<![endif]-->
<head>
<meta charset="utf-8">
<title>code related ramblings</title>
<meta name="author" content="Joseph">
<meta name="description" content="The Ruby) community was a small one for nearly a decade after its creation in 1995 by Yukihiro “Matz” Matsumoto, until the the Ruby on …">
<!-- http://t.co/dKP3o1e -->
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="http://jvenator.github.com/">
<link href="/favicon.png" rel="icon">
<link href="/stylesheets/screen.css" media="screen, projection" rel="stylesheet" type="text/css">
<script src="/javascripts/modernizr-2.0.js"></script>
<script src="/javascripts/ender.js"></script>
<script src="/javascripts/octopress.js" type="text/javascript"></script>
<link href="/atom.xml" rel="alternate" title="code related ramblings" type="application/atom+xml">
<!--Fonts from Google"s Web font directory at http://google.com/webfonts -->
<link href="http://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
<link href="http://fonts.googleapis.com/css?family=PT+Sans:regular,italic,bold,bolditalic" rel="stylesheet" type="text/css">
</head>
<body >
<header role="banner"><hgroup>
<h1><a href="/">code related ramblings</a></h1>
</hgroup>
</header>
<nav role="navigation"><ul class="subscription" data-subscription="rss">
<li><a href="/atom.xml" rel="subscribe-rss" title="subscribe via RSS">RSS</a></li>
</ul>
<form action="http://google.com/search" method="get">
<fieldset role="search">
<input type="hidden" name="q" value="site:jvenator.github.com" />
<input class="search" type="text" name="q" results="0" placeholder="Search"/>
</fieldset>
</form>
<ul class="main-navigation">
<li><a href="/">Blog</a></li>
<li><a href="/blog/archives">Archives</a></li>
</ul>
</nav>
<div id="main">
<div id="content">
<div class="blog-index">
<article>
<header>
<h1 class="entry-title"><a href="/blog/2012/10/18/attr-accessor-in-ruby-for-dummies/">Knowing Rails Doesn’t Mean You Know Ruby: Part 1 | Attr_accessor</a></h1>
<p class="meta">
<time datetime="2012-10-18T20:48:00-04:00" pubdate data-updated="true">Oct 18<span>th</span>, 2012</time>
</p>
</header>
<div class="entry-content"><p>The <a href="http://en.wikipedia.org/wiki/Ruby_(programming_language">Ruby</a>) community was a small one for nearly a decade after its creation in 1995 by <a href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto">Yukihiro “Matz” Matsumoto</a>, until the the <a href="http://en.wikipedia.org/wiki/Ruby_on_Rails">Ruby on Rails</a> framework was created in 2004 by <a href="http://en.wikipedia.org/wiki/David_Heinemeier_Hansson">David Heinemeier Hansson</a>. Rails’ increasing reputation as the go-to option for rapid prototyping and deployment among fast moving and agile startups, dev shops and internal teams of larger companies has led to exponential growth in both the Ruby and Rails communities.</p>
<p>For better or worse, many people have come to Ruby by way of Rails. It is not uncommon for people new to Rails, especially those that are new to programming in general, to have little or no experience with Ruby as a standalone programming language. While initially these individuals will make encouraging and tangible progress, it quickly plateau’s, not only in terms of their ability to build within the Rails framework, but also in terms of their ability to interact with and learn from more experienced programmers and the online community at large. These are things I’ve experienced in my own efforts to become a competent and productive programmer, and have witnessed in the journeys of many others on similar paths. This series of posts will attempt to share some of the lessons I’ve learned that may be helpful to others in a similar position.</p>
<p>Without further ado I introduce to you <strong>attr_accessor</strong>, a <em>setter</em> and <em>getter</em> method for classes in Ruby. First let’s look at a basic scenario you might encounter in a Rails app. Here I’m creating both a model and a controller for a <em>Dog</em> class, which will have several attributes such as <em>name</em>, <em>age</em> and <em>breed</em>. You can assume a migration was created that added these fields to the Dog class. It is common practice to use <code>attr_accessible</code> to allow for mass-assignment of the various attribute values. For simplicity I’m only including a <em>show</em> method in the controller and setting the @dog instance variable by searching for a specific dog record using it’s id value.</p>
<figure class='code'><figcaption><span>Dog model - dog.rb </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">Dogs</span>
</span><span class='line'> <span class="n">attr_accessible</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:age</span><span class="p">,</span> <span class="ss">:breed</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span>Dog controlloer - dogs_controller.rb </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">DogsController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">show</span>
</span><span class='line'> <span class="vi">@dog</span> <span class="o">=</span> <span class="no">Dogs</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:id</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>As you’d expect, if I wanted to now make a call for this particular age or breed in a ‘show’ page, I might do something like this.</p>
<figure class='code'><figcaption><span>Dog show view - show.html.erb </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='erb'><span class='line'><span class="x"><h1></span><span class="cp"><%=</span> <span class="vi">@dog</span><span class="o">.</span><span class="n">name</span> <span class="cp">%></span><span class="x"></h1></span>
</span><span class='line'><span class="x"><p>Age: </span><span class="cp"><%=</span> <span class="vi">@dog</span><span class="o">.</span><span class="n">age</span> <span class="cp">%></span><span class="x"></p></span>
</span><span class='line'><span class="x"><p>Breed: </span><span class="cp"><%=</span> <span class="vi">@dog</span><span class="o">.</span><span class="n">breed</span> <span class="cp">%></span><span class="x"></p></span>
</span></code></pre></td></tr></table></div></figure>
<p>This view snippet where we are able to so simply reference the @dog instance variable and then tack on the desired attributes (i.e., age, breed, etc.) is something I always took for granted. In fact it never occurred to me that in this example the name, age and breed attributes are actually acting as methods. Consider a few well know string methods that I’ve run here within IRB in the console (using Terminal since I’m on a Mac).</p>
<p><img src="http://f.cl.ly/items/1g3P2x0V0s0l3a1x3E1h/Screen%20Shot%202012-10-22%20at%201.56.24%20AM.png"></p>
<p>Here, there’s no question that <em>upcase</em> and <em>reverse</em> are methods within the Ruby library that perform certain functions on strings. Looking at this syntax and comparing it to our original example of a Dog class, it becomes apparent that when calling something like <code>@dog.name</code> that <em>name</em> is really a method of some sort that returns the stored value for the <em>name</em> attribute.</p>
<p>The hero responsible for this behind-the-scenes magic is <code>attr_accessor</code>, which automatically provides <em>setter</em> and <em>getter</em> methods for attributes that are passed to it. Since Rails performs things like this in the background, let’s try it in pure Ruby. Like before we’re going to create a Dog class and give it certain attributes, only there won’t be a controller. It can look something like this.</p>
<figure class='code'><figcaption><span>Ruby only Dog class dog.rb </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">Dog</span>
</span><span class='line'> <span class="kp">attr_accessor</span> <span class="ss">:name</span><span class="p">,</span> <span class="ss">:age</span><span class="p">,</span> <span class="ss">:breed</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>If I load this simple three lines of code into IRB, I can actually do a lot. You can load a file into IRB calling <code>irb</code> in your console, and then passing it this command <code>load '/directory/location/file_name'</code>. In my case I ran <code>load '~/Desktop/Dog.rb'</code>.</p>
<p><img src="http://f.cl.ly/items/0W1s0d2k05051B400D30/Screen%20Shot%202012-10-22%20at%202.24.12%20AM.png"></p>
<p>You can see that I was able to make a new instance of the Dog class, and then easily assign (<em>set</em>) the values of the attributes as well as call (<em>get</em>) them. Now I’d like to show you what <code>attr_accessor</code> is actually doing behind the scenes.</p>
<figure class='code'><figcaption><span>Ruby Dog class long-form dog.rb </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">Dog</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">name</span><span class="o">=</span><span class="p">(</span><span class="n">string</span><span class="p">)</span> <span class="c1"># setter method for :name</span>
</span><span class='line'> <span class="vi">@name</span> <span class="o">=</span> <span class="n">string</span> <span class="c1"># this sets the instance variable of :name equal to the string provided</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">name</span> <span class="c1"># getter method for :name</span>
</span><span class='line'> <span class="vi">@name</span> <span class="c1"># this allow you to call the name method and get back the assigned value of :name</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">age</span><span class="o">=</span><span class="p">(</span><span class="n">number</span><span class="p">)</span> <span class="c1"># setter method for :age</span>
</span><span class='line'> <span class="vi">@age</span> <span class="o">=</span> <span class="n">number</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">age</span> <span class="c1"># getter method for :age</span>
</span><span class='line'> <span class="vi">@age</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">breed</span><span class="o">=</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</span><span class='line'> <span class="vi">@breed</span> <span class="o">=</span> <span class="n">string</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="k">def</span> <span class="nf">breed</span>
</span><span class='line'> <span class="vi">@breed</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>Let’s look at the <em>setter</em> method for the <em>name</em> attribute on line 3. This allows us to create an instance of the Dog class, and then set the <em>name</em> attribute equal to a string we pass to it. This is exactly what I did in the prior screenshot of my console in IRB when I typed <code>d.name = "fido"</code>. Next we see on line 7 that we are defining a <code>name</code> method that can be called and will spit out the attribute value we stored in the <code>@name</code> instance variable. Again you can see this working the IRB screenshot above when typed in <code>d.name</code> and it spit out <em>“fido”</em>. So, what <code>attr_accessor</code> does behind the scenes in Ruby (even more behind the scenes in Rails) is dynamically create these two methods (<em>setter</em> and <em>getter</em>) for each of the class attributes you pass to it. It’s worth noting that aside from the consistency and likely avoidance of typos in your code it also saves you six lines of code for every single class attribute you have (that’s 18 lines of code in our simple Dog class example).</p>
<p>You might ask why this matters, since it’s remains pretty easy to just keep using <code>attr_accessor</code>? The main reason relates to my comments in the first paragraph. Basically, it’s about stretching your boundaries a little bit, and understanding what’s happening underneath the covers both in Ruby and in Rails. While I will continue to make use of the magic in Rails and <code>attr_accessor</code> in Ruby, knowing how it works has helped me appreciate things more.</p>
<p>For starters, I’ve now been introduced to the <em>setter</em> and <em>getter</em> pattern, which is a fundamental concept in almost every programming language or framework in use today. This means that when I decide to learn other languages or frameworks, or a more experienced programmer references it when offering me assistance, I’ll know what the hell they’re talking about! There’s a long list of additional reasons to learn this I’m sure, but if you’re even halfway serious about learning to code in a competent manner then the one I’ve provided should probably be enough.</p>
<p>Let me know in the comments if any of this doesn’t make sense, or if you have any real world examples of where understanding what <code>attr_accessor</code> and/or the <em>setter/getter</em> pattern is doing has helped you.</p>
</div>
</article>
<div class="pagination">
<a href="/blog/archives">Blog Archives</a>
</div>
</div>
<aside class="sidebar">
<section>
<h1>Recent Posts</h1>
<ul id="recent_posts">
<li class="post">
<a href="/blog/2012/10/18/attr-accessor-in-ruby-for-dummies/">Knowing Rails Doesn’t Mean You Know Ruby: Part 1 | attr_accessor</a>
</li>
</ul>
</section>
</aside>
</div>
</div>
<footer role="contentinfo"><p>
Copyright © 2012 - Joseph -
<span class="credit">Powered by <a href="http://octopress.org">Octopress</a></span>
</p>
</footer>
<script type="text/javascript">
(function(){
var twitterWidgets = document.createElement('script');
twitterWidgets.type = 'text/javascript';
twitterWidgets.async = true;
twitterWidgets.src = 'http://platform.twitter.com/widgets.js';
document.getElementsByTagName('head')[0].appendChild(twitterWidgets);
})();
</script>
</body>
</html>