tag:blog.hasmanythrough.com,2006-02-27:/tag/patchhas_many :through - patch2007-03-14T03:19:00-07:00tag:blog.hasmanythrough.com,2006-02-27:Article/802007-03-14T03:19:00-07:002008-01-24T00:19:35-08:00New on Edge: dynamic finders with hash attributes for creationJosh Susser<p>During the <a href="http://weblog.rubyonrails.org/2007/1/8/hackfest-2007-and-cdbaby-sprint">Hackfest</a> in January I put together a <a href="http://dev.rubyonrails.org/ticket/7368">patch</a> for an enhancement to Rails dynamic finders. It was just <a href="http://dev.rubyonrails.org/changeset/6420">committed</a> today (thanks, Jeremy!), so now's a good time to do a little explanation of it. It's just a little thing, so this should be brief.</p>
<p>Here's a typical situation:</p>
<pre><code>tag = Tag.find_by_name(name)
if tag.nil?
tag = Tag.create(:name => name, :creator => current_user)
end
</code></pre>
<p>You'd think the way to do that would be with the <code>find_or_create_by_name</code> dynamic finder, but that doesn't work since there's no way to search by name only, but create by name <em>and</em> creator. Well, that's just not right. So here's what we'll do:</p>
<pre><code>Tag.find_or_create_by_name(:name => name, :creator => current_user)
</code></pre>
<p>The new feature is that if you pass a hash to the finder, it will still use only the values named in the finder to find the object, but it will create a new object using all the values. </p>
<p>It's not a big deal or something I use every day, but I like it anyway.</p><p>During the <a href="http://weblog.rubyonrails.org/2007/1/8/hackfest-2007-and-cdbaby-sprint">Hackfest</a> in January I put together a <a href="http://dev.rubyonrails.org/ticket/7368">patch</a> for an enhancement to Rails dynamic finders. It was just <a href="http://dev.rubyonrails.org/changeset/6420">committed</a> today (thanks, Jeremy!), so now's a good time to do a little explanation of it. It's just a little thing, so this should be brief.</p>
<p>Here's a typical situation:</p>
<pre><code>tag = Tag.find_by_name(name)
if tag.nil?
tag = Tag.create(:name => name, :creator => current_user)
end
</code></pre>
<p>You'd think the way to do that would be with the <code>find_or_create_by_name</code> dynamic finder, but that doesn't work since there's no way to search by name only, but create by name <em>and</em> creator. Well, that's just not right. So here's what we'll do:</p>
<pre><code>Tag.find_or_create_by_name(:name => name, :creator => current_user)
</code></pre>
<p>The new feature is that if you pass a hash to the finder, it will still use only the values named in the finder to find the object, but it will create a new object using all the values. </p>
<p>It's not a big deal or something I use every day, but I like it anyway.</p>tag:blog.hasmanythrough.com,2006-02-27:Article/542006-07-02T23:07:00-07:002008-01-24T00:19:32-08:00Patch test plugin: dynamic finders with belongs_to namesJosh Susser<p>Dynamic finders are pretty neat, but I've grown tired of having to think in terms of foreign keys instead of the names of belongs_to associations. So I fixed it.</p>
<p>This patch enhances dynamic finders to allow use of a belongs_to association name instead of having to use the foreign key attribute directly. For example, these two lines are equivalent:</p>
<pre><code>posts = Post.find_all_by_author_id(author.id)
posts = Post.find_all_by_author(author)
</code></pre>
<p>Of course, that makes more of a difference when the association name and foreign key name differ more. But I think that makes dynamic finders a bit more transparent and easier to use.</p>
<p>I'll be submitting this as a patch fairly soon, but first I wanted to toss it out into the wild to see how well it works. I've written unit tests, but for something like this I'd feel just slightly better knowing a few people have given it a try first. So I've packaged the patch as a plugin to make it easy for you to try it out.</p>
<p><a href="http://svn.hasmanythrough.com/public/plugins/dynamic_finders_with_belongs_to_names/">dynamic_finders_with_belongs_to_names</a></p>
<p>Give it a shot, and either email me or leave a comment here to let me know if it works or if it breaks something.</p>
<p><strong>UPDATE:</strong> I've fixed the plugin so that the monkey patch loads properly now. If it wasn't working for you before, update to the new version and try it again now. Thanks!</p><p>Dynamic finders are pretty neat, but I've grown tired of having to think in terms of foreign keys instead of the names of belongs_to associations. So I fixed it.</p>
<p>This patch enhances dynamic finders to allow use of a belongs_to association name instead of having to use the foreign key attribute directly. For example, these two lines are equivalent:</p>
<pre><code>posts = Post.find_all_by_author_id(author.id)
posts = Post.find_all_by_author(author)
</code></pre>
<p>Of course, that makes more of a difference when the association name and foreign key name differ more. But I think that makes dynamic finders a bit more transparent and easier to use.</p>
<p>I'll be submitting this as a patch fairly soon, but first I wanted to toss it out into the wild to see how well it works. I've written unit tests, but for something like this I'd feel just slightly better knowing a few people have given it a try first. So I've packaged the patch as a plugin to make it easy for you to try it out.</p>
<p><a href="http://svn.hasmanythrough.com/public/plugins/dynamic_finders_with_belongs_to_names/">dynamic_finders_with_belongs_to_names</a></p>
<p>Give it a shot, and either email me or leave a comment here to let me know if it works or if it breaks something.</p>
<p><strong>UPDATE:</strong> I've fixed the plugin so that the monkey patch loads properly now. If it wasn't working for you before, update to the new version and try it again now. Thanks!</p>tag:blog.hasmanythrough.com,2006-02-27:Article/252006-04-10T19:15:00-07:002008-01-24T00:19:30-08:00My first Ruby on Rails patchJosh Susser<p>My first Ruby on Rails patch was just committed to the trunk. I'm now officially a Rails contributor. Yay me!</p><p>My first Ruby on Rails patch was just committed to the trunk. I'm now officially a Rails contributor. Yay me!</p>
<p><a href="http://dev.rubyonrails.org/changeset/4206">Changeset 4206</a> is my patch for enhancing the <code>:extend</code> option to allow multiple named extension modules on associations.</p>
<p>I've wanted this ever since I started using extension modules. I quickly ran into a situation where I wanted to use two named modules for the same association. Here's the hacked way of doing that:</p>
<pre><code>has_many :friends, do
include PeopleExtension
include FriendsExtension
end
</code></pre>
<p>The change in my patch allows this more compact syntax:</p>
<pre><code>has_many :friends, :extend => [PeopleExtension, FriendsExtension]
</code></pre>
<p>So much better!</p>
<p>This patch was a bit of a trial run for me to learn the whole process for putting a patch together. The actual change was only one line of Ruby code (but don't forget the 20 or so lines of tests and documentation!). Now that I seem to have the process down I can think about doing something a bit bigger.</p>
<p>As I get more confident in the process I'll write up a better description of how to contribute changes to Rails. The description on the Rails Trac is pretty bare-bones and takes a bit of muddling through if you've never worked on an open source project before.</p>