<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Practical Metaprogramming with Ruby: Storing Preferences</title>
	<atom:link href="http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=practical-metaprogramming-with-ruby-storing-preferences</link>
	<description>Patrick McKenzie (patio11) blogs on software development, marketing, and general business topics</description>
	<lastBuildDate>Sat, 11 Feb 2012 17:02:17 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<item>
		<title>By: pete</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2155</link>
		<dc:creator>pete</dc:creator>
		<pubDate>Sat, 26 Dec 2009 20:28:39 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2155</guid>
		<description>Patrick,

&quot;sensible_defaults! iterates over the DEFAULT_OPTIONS hash rather than using Hash#merge because Hash#merge clobbers things in the destination hash, and the point of the exercise is to set those defaults only when the user hasn’t specified a value.&quot;

Would ActiveSupport&#039;s reverse_merge work better in this case?
http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/ReverseMerge.html</description>
		<content:encoded><![CDATA[<p>Patrick,</p>
<p>&#8220;sensible_defaults! iterates over the DEFAULT_OPTIONS hash rather than using Hash#merge because Hash#merge clobbers things in the destination hash, and the point of the exercise is to set those defaults only when the user hasn’t specified a value.&#8221;</p>
<p>Would ActiveSupport&#8217;s reverse_merge work better in this case?<br />
<a href="http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/ReverseMerge.html" rel="nofollow">http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/ReverseMerge.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ennuyer.net &#187; Blog Archive &#187; Rails Reading - November 24, 2009</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2154</link>
		<dc:creator>Ennuyer.net &#187; Blog Archive &#187; Rails Reading - November 24, 2009</dc:creator>
		<pubDate>Tue, 24 Nov 2009 22:45:13 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2154</guid>
		<description>[...]  Practical Metaprogramming with Ruby: Storing Preferences: MicroISV on a Shoestring  [...]</description>
		<content:encoded><![CDATA[<p>[...]  Practical Metaprogramming with Ruby: Storing Preferences: MicroISV on a Shoestring  [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Sam Stokes</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2153</link>
		<dc:creator>Sam Stokes</dc:creator>
		<pubDate>Sat, 21 Nov 2009 20:12:03 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2153</guid>
		<description>Thanks for this post!  Great to see practical examples of techniques like metaprogramming.  Your code also taught me something new about Ruby regexes: I blogged about it at http://bit.ly/810zXQ.</description>
		<content:encoded><![CDATA[<p>Thanks for this post!  Great to see practical examples of techniques like metaprogramming.  Your code also taught me something new about Ruby regexes: I blogged about it at <a href="http://bit.ly/810zXQ" rel="nofollow">http://bit.ly/810zXQ</a>.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Patrick</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2152</link>
		<dc:creator>Patrick</dc:creator>
		<pubDate>Fri, 20 Nov 2009 07:08:11 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2152</guid>
		<description>Keith, Rails (actually, the Ruby standard library) can merge hashes, but there is a subtlety: sensible_defaults! iterates over the DEFAULT_OPTIONS hash rather than using Hash#merge because Hash#merge clobbers things in the destination hash, and the point of the exercise is to set those defaults only when the user hasn&#039;t specified a value.  (There are boring code-related reasons for not setting them prior to setting the user-defined stuff.)</description>
		<content:encoded><![CDATA[<p>Keith, Rails (actually, the Ruby standard library) can merge hashes, but there is a subtlety: sensible_defaults! iterates over the DEFAULT_OPTIONS hash rather than using Hash#merge because Hash#merge clobbers things in the destination hash, and the point of the exercise is to set those defaults only when the user hasn&#8217;t specified a value.  (There are boring code-related reasons for not setting them prior to setting the user-defined stuff.)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Keith Perhac</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2151</link>
		<dc:creator>Keith Perhac</dc:creator>
		<pubDate>Fri, 20 Nov 2009 03:54:48 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2151</guid>
		<description>Very nice idea.
I&#039;m going to have to try it for my user_settings section on JapaneseTesting.com.
I was dreading having to save all of the data as either a) a separate table or b) cookies (which means I can&#039;t look at them).

I don&#039;t know RoR at all, so the code was only fairly educational, but your explanation was really easy to understand. One thing I was curious about though was when you were reiterating over the Default_options array to set the user prefs. Does RoR not have an array_merge function?</description>
		<content:encoded><![CDATA[<p>Very nice idea.<br />
I&#8217;m going to have to try it for my user_settings section on JapaneseTesting.com.<br />
I was dreading having to save all of the data as either a) a separate table or b) cookies (which means I can&#8217;t look at them).</p>
<p>I don&#8217;t know RoR at all, so the code was only fairly educational, but your explanation was really easy to understand. One thing I was curious about though was when you were reiterating over the Default_options array to set the user prefs. Does RoR not have an array_merge function?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Brady</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2150</link>
		<dc:creator>David Brady</dc:creator>
		<pubDate>Wed, 18 Nov 2009 20:29:04 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2150</guid>
		<description>I call the general pattern for this &quot;reduce relational database to key/value store&quot;. It has pros and cons and can easily be taken too far. Probably 9 times out of 10 that I&#039;ve seen it (or, sigh, USED it) it&#039;s been taken too far. If you&#039;ve considered your use cases and you&#039;re okay, then you&#039;re probably good to go, but do keep in mind that you need to keep an eye on this strategy in the future--if it grows, it&#039;s probably growing out of hand.

For example, if you find yourself needing to interact with one of those properties a lot in the code, you need to ask yourself if that property is starting to emerge as an important part of the design. The magic question is, &quot;if I forget to put this key in the hash stored in the database, will other client code break?&quot; (My rule of thumb: if it requires a change in the view, leave it in the hash; if it requires a change in a model, extract it to its own column.)

Secondly, trading lines of negacode for a general solution is also a +/- proposition. I agree with your position and favor general code over specific (can you tell that I refuse to ever program in Java again?), but the counterarguments go like this: First, 200 lines of repetetive code really only as complex as the 10 lines of boilerplate code that are repeated; second, general code may give you those 20 properties, but it will also open you up to an infinite number of OTHER properties and you cannot guarantee that they will work, or worse, that they cannot be exploited maliciously.&quot; This counterargument almost always comes from somebody who is used to programming in a more &quot;explicitly safe&quot; language like Java or C# or Python.

Third, the maintainer of your code can see that whatever you put in that options hash will get extended onto your model. That&#039;s great! But what the maintainer CAN&#039;T see is what those options are supposed to be. She can&#039;t look at the source and see &quot;def color&quot;. You might say this argument is weak in rails since you&#039;d have to look at the schema anyway, but it&#039;s a stronger argument than you think: the schema can be found in schema.rb. The options hash must be populated by something first before she can look at it. In other words, if she&#039;s got an empty database she can&#039;t save an exemplar because she doesn&#039;t know what properties should be put into the options. She&#039;s stranded.

Okay, enough doom and gloom! I love this technique. It&#039;s powerful, is all I&#039;m saying, and care should be exercised. Powerful tools used ignorantly are merely dangerous. :-)</description>
		<content:encoded><![CDATA[<p>I call the general pattern for this &#8220;reduce relational database to key/value store&#8221;. It has pros and cons and can easily be taken too far. Probably 9 times out of 10 that I&#8217;ve seen it (or, sigh, USED it) it&#8217;s been taken too far. If you&#8217;ve considered your use cases and you&#8217;re okay, then you&#8217;re probably good to go, but do keep in mind that you need to keep an eye on this strategy in the future&#8211;if it grows, it&#8217;s probably growing out of hand.</p>
<p>For example, if you find yourself needing to interact with one of those properties a lot in the code, you need to ask yourself if that property is starting to emerge as an important part of the design. The magic question is, &#8220;if I forget to put this key in the hash stored in the database, will other client code break?&#8221; (My rule of thumb: if it requires a change in the view, leave it in the hash; if it requires a change in a model, extract it to its own column.)</p>
<p>Secondly, trading lines of negacode for a general solution is also a +/- proposition. I agree with your position and favor general code over specific (can you tell that I refuse to ever program in Java again?), but the counterarguments go like this: First, 200 lines of repetetive code really only as complex as the 10 lines of boilerplate code that are repeated; second, general code may give you those 20 properties, but it will also open you up to an infinite number of OTHER properties and you cannot guarantee that they will work, or worse, that they cannot be exploited maliciously.&#8221; This counterargument almost always comes from somebody who is used to programming in a more &#8220;explicitly safe&#8221; language like Java or C# or Python.</p>
<p>Third, the maintainer of your code can see that whatever you put in that options hash will get extended onto your model. That&#8217;s great! But what the maintainer CAN&#8217;T see is what those options are supposed to be. She can&#8217;t look at the source and see &#8220;def color&#8221;. You might say this argument is weak in rails since you&#8217;d have to look at the schema anyway, but it&#8217;s a stronger argument than you think: the schema can be found in schema.rb. The options hash must be populated by something first before she can look at it. In other words, if she&#8217;s got an empty database she can&#8217;t save an exemplar because she doesn&#8217;t know what properties should be put into the options. She&#8217;s stranded.</p>
<p>Okay, enough doom and gloom! I love this technique. It&#8217;s powerful, is all I&#8217;m saying, and care should be exercised. Powerful tools used ignorantly are merely dangerous. <img src='http://www.kalzumeus.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bromley</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2149</link>
		<dc:creator>Bromley</dc:creator>
		<pubDate>Wed, 18 Nov 2009 18:57:10 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2149</guid>
		<description>Patrick it would have been good if you had posted this a couple of months ago...  On a project I&#039;ve been working on recently it took me about 3 major re-designs before I figured out that stuffing parameters into a blob column as JSON made the most sense for what I was trying to achieve.

Boo to &quot;best practices&quot;, hooray for a healthy dose of pragmatism.</description>
		<content:encoded><![CDATA[<p>Patrick it would have been good if you had posted this a couple of months ago&#8230;  On a project I&#8217;ve been working on recently it took me about 3 major re-designs before I figured out that stuffing parameters into a blob column as JSON made the most sense for what I was trying to achieve.</p>
<p>Boo to &#8220;best practices&#8221;, hooray for a healthy dose of pragmatism.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Arya Asemanfar</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2148</link>
		<dc:creator>Arya Asemanfar</dc:creator>
		<pubDate>Wed, 18 Nov 2009 18:09:04 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2148</guid>
		<description>We do something similar for extra attributes on our user model that we never need to use as query conditions. Here&#039;s the gist: http://gist.github.com/238108</description>
		<content:encoded><![CDATA[<p>We do something similar for extra attributes on our user model that we never need to use as query conditions. Here&#8217;s the gist: <a href="http://gist.github.com/238108" rel="nofollow">http://gist.github.com/238108</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jim</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2147</link>
		<dc:creator>Jim</dc:creator>
		<pubDate>Wed, 18 Nov 2009 16:24:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2147</guid>
		<description>Instead of doing:

@print_job.sensible_defaults!

you could also do the initialization of the sensible_defaults in the after_initialize callback method, so you don&#039;t have to do it in the controller ( which matters more if you call this a lot, and are afraid you&#039;ll forget to do it)</description>
		<content:encoded><![CDATA[<p>Instead of doing:</p>
<p>@print_job.sensible_defaults!</p>
<p>you could also do the initialization of the sensible_defaults in the after_initialize callback method, so you don&#8217;t have to do it in the controller ( which matters more if you call this a lot, and are afraid you&#8217;ll forget to do it)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Daily Review #28 &#124; The Queue Blog</title>
		<link>http://www.kalzumeus.com/2009/11/17/practical-metaprogramming-with-ruby-storing-preferences/#comment-2146</link>
		<dc:creator>Daily Review #28 &#124; The Queue Blog</dc:creator>
		<pubDate>Wed, 18 Nov 2009 04:01:54 +0000</pubDate>
		<guid isPermaLink="false">http://www.kalzumeus.com/?p=747#comment-2146</guid>
		<description>[...] MetaProgramming Ruby &#8211; Patrick McKenzie gives a real life example of using Metaprogramming. [...]</description>
		<content:encoded><![CDATA[<p>[...] MetaProgramming Ruby &#8211; Patrick McKenzie gives a real life example of using Metaprogramming. [...]</p>
]]></content:encoded>
	</item>
</channel>
</rss>

