<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	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/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>New Auburn Personal Computer Services LLC</title>
	<atom:link href="http://www.napcsweb.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.napcsweb.com/blog</link>
	<description>professional web development and consulting</description>
	<lastBuildDate>Fri, 12 Mar 2010 06:17:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Basic Authentication in Ruby on Rails &#8211; In Case You Forgot</title>
		<link>http://www.napcsweb.com/blog/2010/03/11/basic-authentication-in-ruby-on-rails-in-case-you-forgot/</link>
		<comments>http://www.napcsweb.com/blog/2010/03/11/basic-authentication-in-ruby-on-rails-in-case-you-forgot/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 05:58:25 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=140</guid>
		<description><![CDATA[There are so many authentication choices in Rails these days, but sometimes the simplest approach is the best approach. I&#8217;m working with a client right now building an application that has a mostly-public interface. Only a handful of people need to log in to the site, and they only need to modify content occasionally. It&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>There are so many authentication choices in Rails these days, but sometimes the simplest approach is the best approach. I&#8217;m working with a client right now building an application that has a mostly-public interface. Only a handful of people need to log in to the site, and they only need to modify content occasionally. It&#8217;s not a complicated project at all, and while my first instinct was to reach for my <a href="http://www.github.com/authlogic_base" class="popup">starter project</a> that I usually use for these kinds of things, I thought again and realized the following:</p>
<ol>
<li>This project doesn&#8217;t need to let people sign up.</li>
<li>There&#8217;s no need to send password recovery instructions</li>
<li>Much of the data entry will be done with a mobile device connecting to the app&#8217;s REST-style XML API.</li>
</ol>
<p>Something like Authlogic, or even Restful Authentication seems like overkill for something this simple.  Many Rails developers are probably used to their solutions because many Rails projects are more complex than this. In the spirit of keeping things simple, I&#8217;m going to show you how to do authentication of users without any plugins, the way we used to do it in 2005. (For those of you that have been working with Rails as long as me, this will be a good refresher for you. When was the last time <b>you</b> hand-rolled your authentication solution?)</p>
<h2>Back To Basic (Authentication, that is)</h2>
<p>Since Rails 2.0, Basic Authentication has been an option, as Ryan Bates explains in <a class="popup" href="http://railscasts.com/episodes/82-http-basic-authentication">Railscast #82</a>. We&#8217;ll use that and a basic user model to authenticate our users.</p>
<p>First, generate a user mode with login and a hashed password fields. I&#8217;m not going to do any salting here, as it&#8217;s not necessary. If you want it, you should be able to add it easily.</p>
<p><pre>ruby script/generate model User login:string hashed_password:string</pre></p>
<p>Now we need to modify the User model to do the password encryption.</p>
<p>First, set up the validations and the attribute accessors for the password and password_confirmation fields.</p>
<p><pre>
&nbsp;&nbsp;validates_presence_of :login
&nbsp;&nbsp;validates_confirmation_of :password
&nbsp;&nbsp;attr_accessor :password
</pre></p>
<p>Next, be a good developer and write a unit test for hashing the password. </p>
<p><pre>
&nbsp;&nbsp;test &quot;should create a user with a hashed password&quot; do
&nbsp;&nbsp;&nbsp;&nbsp;u = User.create(:login =&gt; &quot;homer&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :email =&gt;&quot;homer&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :password =&gt; &quot;1234&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :password_confirmation =&gt; &quot;1234&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;u.reload # (make sure it saved!)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;assert_not_nil u.hashed_password
&nbsp;&nbsp;end
</pre></p>
<p>Prepare your test database<br />
<pre>rake db:test:clone</pre><br />
and run your test</p>
<p><pre>rake test:units</pre></p>
<p>With the test in place, write the code to encrypt the password on save. Add the SHA1 digest library at the top of your class:</p>
<p><pre>
require &#039;digest/sha1&#039;
</pre></p>
<p>Then add the before filter and an encryption method:</p>
<p><pre>
&nbsp;&nbsp;before_save :encrypt_password
 
&nbsp;&nbsp;def encrypt_password
&nbsp;&nbsp;&nbsp;&nbsp;unless self.password.blank?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.hashed_password = Digest::SHA1.hexdigest(self.password.to_s)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.password = nil
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;return true 
&nbsp;&nbsp;end
</pre></p>
<p>Run your test again and everything should pass.<br />
<pre>
rake test:units
</pre></p>
<h3>Authenticating Users</h3>
<p>Now we need to write a class method that we can use to grab a user from the database by looking up their username and hashed password. We&#8217;ll use a simple pattern for this. First, let&#8217;s write a quick test:</p>
<p><pre>
&nbsp;&nbsp;test &quot;given a user named homer with a password of 1234, he should be authenticated with &#039;homer&#039; and &#039;1234&#039; &quot; do
&nbsp;&nbsp;&nbsp;&nbsp;User.create(:login =&gt; &quot;homer&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :email =&gt;&quot;homer&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :password =&gt; &quot;1234&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :password_confirmation =&gt; &quot;1234&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;assert User.authenticated?(&quot;homer&quot;, &quot;1234&quot;)
&nbsp;&nbsp;end
</pre></p>
<p>We create a user and then call User.authenticated?. If its return value evaluates to True, we&#8217;ve got a good set of credentials.  Add this class method to your User model to make your test pass:</p>
<p><pre>
&nbsp;&nbsp;def self.authenticated?(login, password)
&nbsp;&nbsp;&nbsp;&nbsp;pwd = Digest::SHA1.hexdigest(password.to_s)
&nbsp;&nbsp;&nbsp;&nbsp;User.find_by_login_and_hashed_password(login, pwd)
&nbsp;&nbsp;end
</pre></p>
<p>Notice that here, I&#8217;m actually returning the user object, rather than a boolean. If no user is found, <b>nil</b> is returned which evaluates to false. Remember, in Ruby, everything except nil and false evaluates to True.</p>
<p>Our entire user model looks like this:</p>
<p><pre>
require &#039;digest/sha1&#039;
class User &lt; ActiveRecord::Base
&nbsp;&nbsp;
&nbsp;&nbsp;validates_presence_of :login
&nbsp;&nbsp;validates_confirmation_of :password
&nbsp;&nbsp;attr_accessor :password
&nbsp;&nbsp;
&nbsp;&nbsp;before_save :encrypt_password
&nbsp;&nbsp;
&nbsp;&nbsp;def self.authenticated?(login, password)
&nbsp;&nbsp;&nbsp;&nbsp;pwd = Digest::SHA1.hexdigest(password.to_s)
&nbsp;&nbsp;&nbsp;&nbsp;User.find_by_login_and_hashed_password(login, pwd)
&nbsp;&nbsp;end
&nbsp;&nbsp;
&nbsp;&nbsp;private
&nbsp;&nbsp;
&nbsp;&nbsp;def encrypt_password
&nbsp;&nbsp;&nbsp;&nbsp;unless self.password.blank?
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.hashed_password = Digest::SHA1.hexdigest(self.password.to_s)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.password = nil
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;return true 
&nbsp;&nbsp;end
end
</pre></p>
<h3>Creating the Filter</h3>
<p>Let&#8217;s create a simple Projects scaffold. We&#8217;ll use our authentication to protect this scaffolded interface.</p>
<p><pre>ruby script/generate scaffold Project name:string description:text completed:boolean</pre></p>
<p>Now, open <code>app/controllers/application_controller.rb</code> and this code:</p>
<p><pre>
&nbsp;&nbsp;def authenticate_with_basic_auth
&nbsp;&nbsp;&nbsp;&nbsp;authenticate_or_request_with_http_basic do |username, password|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@current_user = User.authenticated?(username, password)
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
</pre></p>
<p>This tiny bit of code will pop up a Basic Authentication credentials box and look the user up in our database using the supplied credentials. If we find our user, we put it in the @current_user instance variable. It&#8217;s common practice in Rails apps to have a current_user helper method, so we can add that to <code>application_controller.rb</code> as well.</p>
<p><pre>
&nbsp;&nbsp;helper_method :current_user

&nbsp;&nbsp;def current_user
&nbsp;&nbsp;&nbsp;&nbsp;@current_user
&nbsp;&nbsp;end
</pre></p>
<p>With that, we simply need to invoke the filter.  Open your <code>projects_controller.rb</code> file and add this to the top:</p>
<p><pre>before_filter :authenticate_with_basic_auth</pre></p>
<p>And that&#8217;s it! You&#8217;ve protected the application. Create a user via the Rails runner, fire up <code>script/server</code> and test it out!</p>
<p><pre>
ruby script/runner &#039;User.create(:login =&gt; &quot;homer&quot;, :password =&gt; &quot;1234&quot;, :password_confirmation =&gt; &quot;1234&quot;)
ruby script/server
</pre></p>
<p>You should also be able to use cURL to play with the XML REST-style API provided by the scaffold generator.</p>
<p>Get projects:<br />
<pre>curl http://localhost:3000/projects.xml -u homer:1234</pre></p>
<p>Create project via XML<br />
<pre>
curl http://localhost:3000/projects.xml \
-u homer:1234 \
-X POST \
-d &quot;&lt;project&gt;&lt;name&gt;Test&lt;/name&gt;&lt;/project&gt;&quot; \
-H &quot;Content-Type: text/xml&quot;
</pre></p>
<h2>Simple is Good</h2>
<p>This simple solution is easy to write, easy to maintain, and easy to extend. It&#8217;s also something that anyone with any practical experience with Rails should be able to write in as much time as it would take to configure Authlogic. </p>
<p>So what&#8217;s left to do with this? First, SHA1 isn&#8217;t great encryption. BCrypt might be better. A salt might be another good idea too. Some more tests would be great. So, go write them, and have fun! As always, I&#8217;d love to hear your comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2010/03/11/basic-authentication-in-ruby-on-rails-in-case-you-forgot/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails and SQL Server &#8211; &#8220;There is no text for object&#8221;</title>
		<link>http://www.napcsweb.com/blog/2010/02/23/rails-and-sql-server-no-text-for-object/</link>
		<comments>http://www.napcsweb.com/blog/2010/02/23/rails-and-sql-server-no-text-for-object/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 18:36:57 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=135</guid>
		<description><![CDATA[I recently moved a Rails application to a new SQL Server 2005 server on a recent project and everything seemed to go smoothly, but when I tried to fire up a connection to the database from my Rails application, I was greeted with

ActiveRecord::StatementInvalid: DBI::DatabaseError: 42000 (15197) [FreeTDS][SQL Server]There is no text for object &#039;people&#039;.: EXEC [...]]]></description>
			<content:encoded><![CDATA[<p>I recently moved a Rails application to a new SQL Server 2005 server on a recent project and everything seemed to go smoothly, but when I tried to fire up a connection to the database from my Rails application, I was greeted with</p>
<p><pre>
ActiveRecord::StatementInvalid: DBI::DatabaseError: 42000 (15197) [FreeTDS][SQL Server]There is no text for object &#039;people&#039;.: EXEC sp_helptext people
</pre></p>
<p>The &#8220;people&#8221; table here is actually a view that gets used all over the place in multiple applications. The DBA had moved the databases from an older SQL Server 2000 database previously.</p>
<p>The solution was to ensure that the application&#8217;s user account had the &#8220;view definition&#8221; permission on the view in question as well as the &#8220;select&#8221; permission.  On the view, in the SQL Server Management Studio, right click and choose &#8220;Properties&#8221;. Then choose Permissions select your user account, and then select the &#8220;View definition&#8221; permission. Checking the box under the &#8220;Grant&#8221; column was enough for me to make it work.</p>
<p> Interestingly enough, the production server (which was upgraded months ago from SQL Server 2000 to 2005), does not have the permission set, but still works fine.</p>
<p>Hopefully someone else finds this useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2010/02/23/rails-and-sql-server-no-text-for-object/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why Rails?</title>
		<link>http://www.napcsweb.com/blog/2010/02/16/why-rail/</link>
		<comments>http://www.napcsweb.com/blog/2010/02/16/why-rail/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 23:13:59 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=132</guid>
		<description><![CDATA[NAPCS was a proud sponsor of the first Chippewa Valley Ruby Camp, a day-long Ruby training camp where 23 students learned how to build and deploy their first Rails application. I taught two of the three sessions and had a great time helping other developers get their hands on what I believe to be the [...]]]></description>
			<content:encoded><![CDATA[<p>NAPCS was a proud sponsor of the first <a href="http://www.ecruby.org/cvrc2010.html">Chippewa Valley Ruby Camp</a>, a day-long Ruby training camp where 23 students learned how to build and deploy their first Rails application. I taught two of the three sessions and had a great time helping other developers get their hands on what I believe to be <strong>the best way to develop scalable, maintainable, and stable web applications</strong> today. That&#8217;s a pretty bold statement, but I believe in it, and it&#8217;s why NAPCS uses Rails on all new client projects. (In fact, every project since 2006 has been a Rails project.)</p>
<h3>Rails projects are quick to launch</h3>
<p>With Rails, we can build and launch a prototype application in an extremely short time. On average, we can have something simple in front of the client in less than a couple of days, which is much faster than our previous projects where we used ASP or PHP.  And that project isn&#8217;t usually a throwaway project; we can tweak it and move forward, from prototype to production.</p>
<h3>Rails applications are easily testable</h3>
<p>Professionals write tests that prove the code works as it should, and since testing is built right in to the Rails framework. testing is an easy natural part of the process. Testing has always been possible regardless of the language used, but with Rails, it&#8217;s so easy to produce well-tested code that you&#8217;d be foolish not to test. For my customers, that means much better products, and less support calls.</p>
<h3>It&#8217;s a standard framework</h3>
<p>I occasionally pick up projects from other developers, and while I can&#8217;t always ensure that the quality of the code will be good, I at least already know my way around the project because, in a Rails application, conventions dictate where things go. This means the learning curve is lower when we transition an application, and the customer doesn&#8217;t get billed extra time for me to figure out what&#8217;s going on.</p>
<h3>The community is incredible</h3>
<p>We rely heavily on open-source projects to get stuff done, and Rails has an <a href="http://railsbridge.org/">amazing community</a> that is always pushing the limits of what Rails applications can do. There is a new solution to a new problem almost every day, and that keeps us all on our toes. Plus, we&#8217;re very proud to be sponsoring the<a href="http://www.railsmentors.org"> Rails Mentors</a> project, which helps other developers get better  at Rails development. We&#8217;re always <a href="http://www.github.com/napcs/">giving back to open source</a>, too. </p>
<h3>It gets out of the way.</h3>
<p>This is the most important point of all; Rails lets me deliver features. Instead of spending hours wiring up database tables to web pages, I can do that in five minutes and spend more time focusing on user experience and new features. And since it isn&#8217;t difficult to build things incrementally,  I don&#8217;t get boxed in. I can make changes without feeling that I&#8217;ll lose days of work. It allows me to respond flexibly to new feature requests.</p>
<p>Rails gives us a competitive advantage. We cannot always compete on price alone, but we can provide better-quality solutions than others because we embrace an open, agile framework that lets us deliver stable, scalable, well-tested, and maintainable web applications. </p>
<h3>Want to learn how you can take advantage of Ruby on Rails?</h3>
<p>Contact us for information on customized training and mentoring services. We offer affordable hourly rates for remote mentoring, as well as custom training classes upon request. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2010/02/16/why-rail/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Moving from Prototype to JQuery</title>
		<link>http://www.napcsweb.com/blog/2009/11/15/moving-from-prototype-to-jquery/</link>
		<comments>http://www.napcsweb.com/blog/2009/11/15/moving-from-prototype-to-jquery/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 06:19:35 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[tips]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=111</guid>
		<description><![CDATA[On a recent project, I converted a ton of Javascript from Prototype to jQuery in order to take advantage of many of the nice UI elements available. As I did the conversion, I took down some notes that I wanted to share with you about the differences between the two libraries.  In some cases, [...]]]></description>
			<content:encoded><![CDATA[<p>On a recent project, I converted a ton of Javascript from Prototype to jQuery in order to take advantage of many of the nice UI elements available. As I did the conversion, I took down some notes that I wanted to share with you about the differences between the two libraries.  In some cases, the differences are insignificant, and in a couple of others, the differences merely come down to a difference of opinion among the developers and supporters of the libraries.</p>
<p>Here are the notes:</p>
<h2>Getting Ready</h2>
<p>Before you can work with elements on the page, those elements must be loaded.</p>
<p>Prototype uses</p>
<p><pre>
document.observe(&quot;dom:loaded&quot;, function() {
&nbsp;&nbsp;// your functions
})
</pre></p>
<p>jQuery uses this:</p>
<p><pre>
$(document).ready(function(){
&nbsp;&nbsp;// your functions
})
</pre></p>
<h2>Finding things</h2>
<p>In Prototype, you use <strong>$(</strong>) or <strong>$$()</strong> to locate elements. With <strong>$()</strong> you use the ID, whereas with <strong>$$()</strong> you use a CSS selector.</p>
<p><pre>
&nbsp;&nbsp;var header = $(&quot;header&quot;);&nbsp;&nbsp;// a single element, &lt;div id=&quot;header&quot;
&nbsp;&nbsp;var popups = $$(&quot;a.popup&quot;); // all elements like &lt;a class=&quot;popup&quot;&gt;
</pre></p>
<p>With JQuery, you do almost all of your element location using <strong>$()</strong>, which works very much like <strong>$$()</strong> in Prototype.</p>
<p><pre>
&nbsp;&nbsp;var header = $(&quot;#header&quot;);&nbsp;&nbsp;// a single element, &lt;div id=&quot;header&quot;
&nbsp;&nbsp;var popups = $(&quot;a.popup&quot;); // all elements like &lt;a class=&quot;popup&quot;&gt;
</pre></p>
<h2>Binding events</h2>
<p>Prototype&#8217;s <strong>Element</strong> class has an <strong>Observe</strong> method. It&#8217;s very easy to use and easy on the eyes.</p>
<p><pre>
&nbsp;&nbsp;$(&quot;header&quot;).observe(&quot;click&quot;, function(event){
&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;Hi there&quot;);
&nbsp;&nbsp;});
</pre></p>
<p>In jQuery, it&#8217;s nearly identical, except that click is a method on the JQuery object.</p>
<p><pre>
&nbsp;&nbsp;$(&quot;#header&quot;).click(function(event){
&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;Hi there&quot;);
&nbsp;&nbsp;});
</pre></p>
<p>At first, the differences look marginal, but let&#8217;s look at a more complicated example:</p>
<p>In Prototype, to find all links on the page with the class &#8220;Popup&#8221; and make them open in a new window, you have to do this:</p>
<p><pre>
function new_window_links(){
&nbsp;&nbsp;links = $$(&quot;a.popup&quot;);
&nbsp;&nbsp;links.each(function(link){
&nbsp;&nbsp;&nbsp;&nbsp;link.observe(&quot;click&quot;, function(event){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.open(link.href);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event.stop();
&nbsp;&nbsp;&nbsp;&nbsp;});
&nbsp;&nbsp;});
}
</pre></p>
<p>The Prototype version makes us find all of the elements, loop over them, and then apply the observer to each one.</p>
<p>jQuery can hide the iteration from you, which results in somewhat cleaner code.</p>
<p><pre>
function new_window_links(){
&nbsp;&nbsp;links = $(&quot;a.popup&quot;).click(function(event){
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;window.open($(this).attr(&#039;href&#039;));
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;event.preventDefault();
&nbsp;&nbsp;});
}
</pre></p>
<h2>Adding Classes</h2>
<p>Prototype:</p>
<p><pre>
&nbsp;&nbsp; $(&quot;.foo&quot;).addClassName(&quot;ninja&quot;);
</pre></p>
<p><pre>
&nbsp;&nbsp;$(&quot;.foo&quot;).addClass(&quot;ninja&quot;);
</pre></p>
<h2>Traversing the DOM</h2>
<p>Prototype:<br />
<pre>
&nbsp;&nbsp;parent_of_foo = $(&quot;foo&quot;).up();
</pre></p>
<p>jQuery<br />
<pre>
&nbsp;&nbsp;parent_of_foo = $(&quot;#foo&quot;).parent();
</pre></p>
<h2>Working with HTML attributes</h2>
<p>This one was the most difficult to get used to. In Prototype, many of the HTML attributes are available as methods on the Element class.</p>
<p><pre>
&nbsp;&nbsp;window.open(link.href);
</pre></p>
<p>In jQuery, you use the <b>attr</b> method to get and set the attributes.</p>
<p><pre>
&nbsp;&nbsp;window.open(link.attr(&quot;http&quot;);
</pre></p>
<p>This illustrates only a few of the differences between the libraries, but as you can see, the differences don&#8217;t realy amount to anything substantial. Both of these libraries greatly simplify cross-browser JavaScript development, so no matter which you choose, you&#8217;ll be in good shape.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/11/15/moving-from-prototype-to-jquery/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Chippewa Valley Code Camp 2009</title>
		<link>http://www.napcsweb.com/blog/2009/11/15/chippewa-valley-code-camp/</link>
		<comments>http://www.napcsweb.com/blog/2009/11/15/chippewa-valley-code-camp/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 15:05:26 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[News]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=126</guid>
		<description><![CDATA[I had the honor of presenting two talks this year at the second annual Chippewa Valley Code Camp.  Code camps are free events where programmers of any skill level come together for a day of sessions and talks that are centered around code. I&#8217;ve only recently become involved with these events and am extremely [...]]]></description>
			<content:encoded><![CDATA[<p>I had the honor of presenting two talks this year at the second annual Chippewa Valley Code Camp.  Code camps are free events where programmers of any skill level come together for a day of sessions and talks that are centered around code. I&#8217;ve only recently become involved with these events and am extremely happy I have. The opportunity to learn from so many experienced developers is incredible. </p>
<p>We held the event at UW-Stout this year, and had a great turnout. I gave two talks, the first on Ruby, and the second on Cucumber. I had wonderful audiences both times, and met some great people that I hope I get to work with in the future.  Here are the slides for my talks. </p>
<p>See the end of the slide decks for links to the demo source code.</p>
<div style="width:425px;text-align:left" id="__ss_2500173"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/napcs/intro-to-ruby-2500173" title="Intro to Ruby">Intro to Ruby</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=tccc7ruby-091114114030-phpapp01&#038;stripped_title=intro-to-ruby-2500173" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=tccc7ruby-091114114030-phpapp01&#038;stripped_title=intro-to-ruby-2500173" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/napcs">Brian Hogan</a>.</div>
</div>
<div style="width:425px;text-align:left" id="__ss_2503410"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/napcs/testing-your-sites-in-english-with-cucumber" title="Testing Your Sites In English with Cucumber">Testing Your Sites In English with Cucumber</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cvcccucumber-091115011413-phpapp02&#038;stripped_title=testing-your-sites-in-english-with-cucumber" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cvcccucumber-091115011413-phpapp02&#038;stripped_title=testing-your-sites-in-english-with-cucumber" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/napcs">Brian Hogan</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/11/15/chippewa-valley-code-camp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8220;Introduction to Ruby&#8221; talk from Twin Cities Code Camp 7</title>
		<link>http://www.napcsweb.com/blog/2009/10/25/introduction-to-ruby-talk-from-twin-cities-code-camp-7/</link>
		<comments>http://www.napcsweb.com/blog/2009/10/25/introduction-to-ruby-talk-from-twin-cities-code-camp-7/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 03:32:42 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=122</guid>
		<description><![CDATA[On Saturday, I had the honor of giving a talk on the Ruby programming language to an exceptional audience. I talked about the simple syntax and powerful libraries available, and then showed how we can use Ruby to maintain static web sites, build web applications, and test web sites.
During the talk, I showed how to [...]]]></description>
			<content:encoded><![CDATA[<p>On Saturday, I had the honor of giving a talk on the Ruby programming language to an exceptional audience. I talked about the simple syntax and powerful libraries available, and then showed how we can use Ruby to maintain static web sites, build web applications, and test web sites.</p>
<p>During the talk, I showed how to use <a href="http://www.sinatrarb.com">Sinatra</a> to create a very simple wiki. I wrote two versions. During the talk, I used SQLite3 and ActiveRecord, but I wrote a version that uses MongoDB. You can grab the <a href="http://www.github.com/napcs/sinatriki">source</a> for those at <a href="http://www.github.com/">Github</a>.</p>
<p>Here are the slides from my talk. You can view the notes too by viewing the slides on Slideshare.</p>
<div style="width:425px;text-align:left" id="__ss_2343598"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/napcs/intro-to-ruby-twin-cities-code-camp-7" title="Intro to Ruby - Twin Cities Code Camp 7">Intro to Ruby &#8211; Twin Cities Code Camp 7</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=tccc7ruby-091025153443-phpapp01&#038;stripped_title=intro-to-ruby-twin-cities-code-camp-7" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=tccc7ruby-091025153443-phpapp01&#038;stripped_title=intro-to-ruby-twin-cities-code-camp-7" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/napcs">Brian Hogan</a>.</div>
</div>
<p>Participating at code camps is something I really enjoy. It gives me a chance to talk about what I love, but it also gives me a chance to learn from other speakers. These events are usually free, and an awful lot of fun.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/10/25/introduction-to-ruby-talk-from-twin-cities-code-camp-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mongodb and Macports</title>
		<link>http://www.napcsweb.com/blog/2009/10/20/mongodb-and-macports/</link>
		<comments>http://www.napcsweb.com/blog/2009/10/20/mongodb-and-macports/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 21:21:39 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[tips]]></category>
		<category><![CDATA[mongodb ruby mac]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=119</guid>
		<description><![CDATA[I just hit a bump in the road with installing MongoDB via Macports 1.8.1. 

sudo port install boost pcre++ spidermonkey
sudo port install mongodb

When I ran mongodb I was greeted with

dyld: Library not loaded: /opt/local/lib/libnspr4.dylib
&#160;&#160;Referenced from: /opt/local/lib/nspr/libplds4.dylib
&#160;&#160;Reason: image not found
Trace/BPT trap

To fix, I simply copied the missing file from its origin to where Mongodb was looking.

 [...]]]></description>
			<content:encoded><![CDATA[<p>I just hit a bump in the road with installing MongoDB via Macports 1.8.1. </p>
<p><pre>
sudo port install boost pcre++ spidermonkey
sudo port install mongodb
</pre></p>
<p>When I ran <pre>mongodb</pre> I was greeted with</p>
<p><pre class="output">
dyld: Library not loaded: /opt/local/lib/libnspr4.dylib
&nbsp;&nbsp;Referenced from: /opt/local/lib/nspr/libplds4.dylib
&nbsp;&nbsp;Reason: image not found
Trace/BPT trap
</pre></p>
<p>To fix, I simply copied the missing file from its origin to where Mongodb was looking.</p>
<p><pre>
 sudo&nbsp;&nbsp;cp /opt/local/lib/nspr/libnspr4.dylib /opt/local/lib
</pre></p>
<p>And all was right.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/10/20/mongodb-and-macports/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autocomplete forms in Rails 2.3.3</title>
		<link>http://www.napcsweb.com/blog/2009/08/28/autocomplete-forms-in-rails-2-3-3/</link>
		<comments>http://www.napcsweb.com/blog/2009/08/28/autocomplete-forms-in-rails-2-3-3/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 02:12:51 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=90</guid>
		<description><![CDATA[When Rails 2 was released, the core team dropped some of the Javascript Ajax helpers like in-place editing and autocompleting, and released them as plugins.  However, if you&#8217;ve ever tried to use them with a modern Rails application, you may have encountered problems with routing and authenticity tokens.  In this brief post, I&#8217;ll [...]]]></description>
			<content:encoded><![CDATA[<p>When Rails 2 was released, the core team dropped some of the Javascript Ajax helpers like in-place editing and autocompleting, and released them as plugins.  However, if you&#8217;ve ever tried to use them with a modern Rails application, you may have encountered problems with routing and authenticity tokens.  In this brief post, I&#8217;ll walk you through a trivial example that shows how to make Autocomplete work, using the advantages that Rails 2.3 has, including format responses.</p>
<p>First, let&#8217;s get a basic Rails app running with a Projects table with a single field, the project&#8217;s name :</p>
<p><pre>
 rails autocomplete
 cd autocomplete
 ruby script/generate model project name:string
 ruby script/generate resource projects
 rake db:migrate
</pre></p>
<p>Next, let&#8217;s load some test data.</p>
<p><pre>
 ruby script/runner &quot;
 [&#039;The Ninja project&#039;, &#039;The Top Secret project&#039;, &#039;World Domination&#039;].each do |p|
&nbsp;&nbsp;&nbsp;&nbsp;Project.create(:name =&gt; p)
 end
 &quot;
</pre></p>
<p>Grab the autocomplete plugin from Rails&#8217; Github repository and install it as a plugin:</p>
<p><pre>
 ruby script/plugin install git://github.com/rails/auto_complete.git
</pre></p>
<p>Our basic app is installed, but we need to implement a controller action to display projects.</p>
<p>Open <b>app/controllers/projects_controller.rb</b> and add this method:</p>
<p><pre>
&nbsp;&nbsp;def index
&nbsp;&nbsp;&nbsp;&nbsp;@projects = Project.all :limit =&gt; 10
&nbsp;&nbsp;&nbsp;&nbsp;respond_to do |format|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;format.html
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
</pre></p>
<p>When the user requests HTML, we&#8217;ll show the last 10 projects created. Good enough for now. Let&#8217;s implement the layout and the view.</p>
<p>Open <b>app/views/layouts/application.html.erb</b> and build a very simple layout:</p>
<p><pre>
&lt;html&gt;
&nbsp;&nbsp;&lt;head&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;Autocomplete&lt;/title&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;% =javascript_include_tag :defaults %&gt;
&nbsp;&nbsp;&lt;/head&gt;
&nbsp;&nbsp;
&nbsp;&nbsp;&lt;body&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;%= yield %&gt;
&nbsp;&nbsp;&lt;/body&gt;
&lt;/html&gt;

</pre></p>
<p>This <em>very</em> basic layout loads the default Javascript fiels for Rails and yields the template.</p>
<p>Now open <b>app/views/projects/index.html</b> and add this code:</p>
<p><pre>
&lt;div id=&quot;search&quot;&gt;
&nbsp;&nbsp;&lt;% form_tag(projects_path(), {:method =&gt; :get, :class =&gt; &quot;form&quot;}) do %&gt;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;%=text_field_tag &quot;query&quot;%&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;%=submit_tag &quot;Search&quot;%&gt;
&nbsp;&nbsp;&lt;% end -%&gt;
&lt;/div&gt;
&lt;div id=&quot;projects&quot;&gt;
&nbsp;&nbsp;&lt;% if @projects.any? %&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;ul&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;%=render @projects %&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ul&gt;
&nbsp;&nbsp;&lt;% else %&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;There are no projects to show.&lt;/p&gt;
&nbsp;&nbsp;&lt;% end %&gt;
&lt;/div&gt;
</pre></p>
<p>Here we have a list of projects, and when we click the submit button, we&#8217;ll filter the results.  We&#8217;re using <b>render</b> here, and when you pass the <b>render</b> helper a collection, it looks for a partial that it can use render each of the elements in the collection.</p>
<p>Create <b>app/views/projects/_project.erb</b> and add this line:</p>
<p><pre>
&lt;li&gt;&lt;%=h(project.name)%&gt;&lt;/li&gt;
</pre></p>
<p>Now we have to do the filtering in the controller. Since the search box is simply applying a filter to the list of projects, it makes sense for us to use the <b>index</b> action for the request. This means changing the controller&#8217;s index action slightly.</p>
<p><pre>
def index
&nbsp;&nbsp;keyword = params[:query]
&nbsp;&nbsp;if keyword.present?
&nbsp;&nbsp;&nbsp;&nbsp;keyword = &quot;%#{keyword}%&quot;
&nbsp;&nbsp;&nbsp;&nbsp;@projects = Project.all :conditions =&gt; [&quot;name like ?&quot;, keyword], :order =&gt; &quot;name asc&quot;, :limit =&gt; 10
&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;@projects = Project.all :limit =&gt; 10, :order =&gt; &quot;created_at desc&quot;
&nbsp;&nbsp;end
&nbsp;&nbsp;
&nbsp;&nbsp;respond_to do |format|
&nbsp;&nbsp;&nbsp;&nbsp;format.html
&nbsp;&nbsp;&nbsp;&nbsp;format.js do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render :inline =&gt; &quot;&lt;%= auto_complete_result(@projects, &#039;name&#039;) %&gt;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
end
</pre></p>
<p>If the <b>query</b> parameter comes in, then we want to filter. We build up a LIKE query and get the results. If no query parameter is present, we just get the top ten recent projects.</p>
<p>However, this is really messy.  Let&#8217;s get that search logic out of the controller.</p>
<p>Open app/models/project.rb. Move the search logic into a new method:</p>
<p><pre>
def self.find_all_by_keyword(keyword)
&nbsp;&nbsp;if keyword.present?
&nbsp;&nbsp;&nbsp;&nbsp;keyword = &quot;%#{keyword}%&quot;
&nbsp;&nbsp;&nbsp;&nbsp;@projects = Project.all :conditions =&gt; [&quot;name like ?&quot;, keyword], :order =&gt; &quot;name asc&quot;, :limit =&gt; 10
&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;@projects = Project.all :limit =&gt; 10, :order =&gt; &quot;created_at desc&quot;
&nbsp;&nbsp;end
end
</pre></p>
<p>Now change <b>app/controllers/projects_controller.rb</b> to call the method instead of doing the search:</p>
<p><pre>
def index
&nbsp;&nbsp;@projects = Project.find_by_keyword(params[:query])
&nbsp;&nbsp;respond_to do |format|
&nbsp;&nbsp;&nbsp;&nbsp;format.html
&nbsp;&nbsp;&nbsp;&nbsp;format.js do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render :inline =&gt; &quot;&lt;%= auto_complete_result(@projects, &#039;name&#039;) %&gt;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
end
</pre></p>
<p>Much better. At this point you have a non-Javascript search for your projects in a very short time.</p>
<p>Let&#8217;s add the autocomplete functionality. First, in the view, change the text field to this:</p>
<p><pre>
&lt;%= text_field_with_auto_complete :project, :name, 
&nbsp;&nbsp;&nbsp;&nbsp;{ :name =&gt; &quot;query&quot; },
&nbsp;&nbsp;&nbsp;&nbsp;{:method =&gt; :get, :url =&gt; projects_path(:format =&gt; :js) } %&gt;
</pre></p>
<p>This sets up the autocomplete field to send its queries to our index action, but specifies that we should use the &#8220;js&#8221; format, perfectly appropriate for this, as it&#8217;s a Javascript-only request, so we should provide our response with Javascript.</p>
<p>Open the controller and modify the controller&#8217;s code so it looks like this:</p>
<p><pre>
def index
&nbsp;&nbsp;@projects = Project.find_all_by_keyword(params[:query])
&nbsp;&nbsp;respond_to do |format|
&nbsp;&nbsp;&nbsp;&nbsp;format.html
&nbsp;&nbsp;&nbsp;&nbsp;format.js do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;render :inline =&gt; &quot;&lt;%= auto_complete_result(@projects, &#039;name&#039;) %&gt;&quot;
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
end
</pre></p>
<p>The only real change is adding the <b>format.js</b> block of code. Here, we&#8217;re using Rails&#8217; inline renderer which renders ERb code. Within that ERB, we&#8217;re calling the <b>auto_complete_response</b> helper provided by the autocomplete plugin to render the specially formatted list that the auto compelte text field expects.  We&#8217;re using inline rendering here, but you could use a view with the .js extension. Since it&#8217;s one line, I&#8217;ll save the file I/O.</p>
<p>With the responder in place, the autocomplete should start working.  This is a pretty simple example, but it does illustrate how to make the autocomplete plugin work in a current Rails application, without working about </p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/08/28/autocomplete-forms-in-rails-2-3-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Saving without callbacks</title>
		<link>http://www.napcsweb.com/blog/2009/08/19/saving-without-callbacks/</link>
		<comments>http://www.napcsweb.com/blog/2009/08/19/saving-without-callbacks/#comments</comments>
		<pubDate>Wed, 19 Aug 2009 21:56:13 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=85</guid>
		<description><![CDATA[Occasionally, you need to do something to a model without invoking callbacks. This is especially necessary for instances where you need to modify the record you just saved in an after_save callback. For example, say you want to create a hash based on the record&#8217;s ID. You won&#8217;t have the ID until after it&#8217;s been [...]]]></description>
			<content:encoded><![CDATA[<p>Occasionally, you need to do something to a model without invoking callbacks. This is especially necessary for instances where you need to modify the record you just saved in an after_save callback. For example, say you want to create a hash based on the record&#8217;s ID. You won&#8217;t have the ID until after it&#8217;s been saved, and if you call self.save in an after_save callback, you&#8217;re going to end up in an endless loop.</p>
<p>It turns out that ActiveRecord has two private methods.</p>
<p><pre>create_without_callbacks</pre></p>
<p>and</p>
<p><pre>update_without_callbacks</pre></p>
<p>Remember that <b>private</b> in Ruby is less about keeping you from calling the methods and more about letting you know that you shouldn&#8217;t depend on them.  With Ruby&#8217;s <b>send</b> method, using either of these in your application is easy.</p>
<p><em>Note that in Ruby 1.9, <b>send</b> doesn&#8217;t allow calling private methods, but <b>send!</b> does.</em></p>
<p><pre>
&nbsp;&nbsp;class Project &lt; ActiveRecord::Base
&nbsp;&nbsp;&nbsp;&nbsp;after_save :create_hash_from_name_and_id

&nbsp;&nbsp;&nbsp;&nbsp;private
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def create_hash_from_name_and_id
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.hash = Digest::SHA1.hexdigest(&quot;#{self.id}#{Time.now.to_s}#{self.name}&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send :update_without_callbacks
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
</pre></p>
<p>It&#8217;s my opinion that these methods should not be private. If I can skip validations with <b>save(false)</b>, then I should be able to skip callbacks as well.</p>
<p>There are other patterns you can use to skip callbacks.</p>
<p><pre>
&nbsp;&nbsp;class Project &lt; ActiveRecord::Base
&nbsp;&nbsp;&nbsp;&nbsp;attr_accessor :skip_callbacks

&nbsp;&nbsp;&nbsp;&nbsp;with_options :unless =&gt; :skip_callbacks do |project|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;project.after_save :create_hash_from_name_and_id
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;project.after_save :do_more_stuff
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;private
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def create_hash_from_name_and_id
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.skip_callbacks = true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.hash = Digest::SHA1.hexdigest(&quot;#{self.id}#{Time.now.to_s}#{self.name}&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.save
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;end
</pre></p>
<p>So there you go. Go forth and skip callbacks at will.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/08/19/saving-without-callbacks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using a class method with or without named scopes</title>
		<link>http://www.napcsweb.com/blog/2009/08/17/using-a-class-method-with-or-without-named-scopes/</link>
		<comments>http://www.napcsweb.com/blog/2009/08/17/using-a-class-method-with-or-without-named-scopes/#comments</comments>
		<pubDate>Tue, 18 Aug 2009 05:30:48 +0000</pubDate>
		<dc:creator>Brian</dc:creator>
				<category><![CDATA[Howto]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.napcsweb.com/blog/?p=83</guid>
		<description><![CDATA[Here&#8217;s a quick one, building off of the previous post on Geokit and Named Scopes.
If you have defined a class method you want to run which operates on a collection of records, you can share it with named scopes.

class Project &#60; ActiveRecord::Base
&#160;&#160;validates_presence_of :name
&#160;&#160;named_scope :completed, :conditions =&#62; {:completed =&#62; true}

&#160;&#160;# returns array of names for projects
&#160;&#160;def [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick one, building off of the previous post on <a href="http://www.napcsweb.com/blog/2009/08/11/geokit-and-named_scope/">Geokit and Named Scopes</a>.</p>
<p>If you have defined a class method you want to run which operates on a collection of records, you can share it with named scopes.</p>
<p><pre>
class Project &lt; ActiveRecord::Base
&nbsp;&nbsp;validates_presence_of :name
&nbsp;&nbsp;named_scope :completed, :conditions =&gt; {:completed =&gt; true}

&nbsp;&nbsp;# returns array of names for projects
&nbsp;&nbsp;def self.names
&nbsp;&nbsp;&nbsp;&nbsp;scope = self.scoped({})
&nbsp;&nbsp;&nbsp;&nbsp;scope.all.collect{|record| record.name}
&nbsp;&nbsp;end
end
</pre></p>
<p>This allows you to do<br />
<pre>
@project_names = Project.names
</pre></p>
<p>Or<br />
<pre>
@project_names = Project.completed.names
</pre></p>
<p>If you return the scope, you can continue chaining. If you don&#8217;t return the scope, then you can&#8217;t. This comes in handy though for creating a method that returns other objects than the object you&#8217;re working with. Here&#8217;s a completely contrived example:</p>
<p>Say you want to find the actual hours you&#8217;ve spent on all your completed projects:<br />
<pre>
class Project &lt; ActiveRecord::Base
&nbsp;&nbsp;named_scope :completed, :conditions =&gt; {:completed =&gt; true}
&nbsp;&nbsp;
&nbsp;&nbsp;def self.tasks
&nbsp;&nbsp;&nbsp;&nbsp;tasks = []
&nbsp;&nbsp;&nbsp;&nbsp;self.scoped({}).all.each do |project|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tasks += (project.tasks)
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;tasks
&nbsp;&nbsp;end
&nbsp;&nbsp;
&nbsp;&nbsp;def self.actual_hours
&nbsp;&nbsp;&nbsp;&nbsp;hours = 0
&nbsp;&nbsp;&nbsp;&nbsp;tasks.each do |task|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hours += task.hours
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;hours
&nbsp;&nbsp;end
</pre></p>
<p>Grab the value like this:<br />
<pre>
actual_hours = Project.completed.actual_hours
</pre></p>
<p>Now, of course there are other ways to do this, and this particular method will result in a lot of queries. If you were doing this hours counting in a real app, you&#8217;d be better off using SQL. This example illustrates the point though. Now go build something more awesome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.napcsweb.com/blog/2009/08/17/using-a-class-method-with-or-without-named-scopes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
