<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<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/"
	>

<channel>
	<title>ruby-on-rails &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/ruby-on-rails/</link>
	<description>Feed of posts on WordPress.com tagged "ruby-on-rails"</description>
	<pubDate>Thu, 26 Nov 2009 15:04:24 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Url Shortener gem - bit.ly api wrapper in ruby]]></title>
<link>http://nasir.wordpress.com/2009/11/26/url-shortener-gem-bitly-api-wrapper-in-ruby/</link>
<pubDate>Thu, 26 Nov 2009 02:22:22 +0000</pubDate>
<dc:creator>nasir</dc:creator>
<guid>http://nasir.wordpress.com/2009/11/26/url-shortener-gem-bitly-api-wrapper-in-ruby/</guid>
<description><![CDATA[Url shortener gem came out of my need to tweet rss feeds to twitter every 5 minutes and shortening t]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://github.com/nas/url_shortener">Url shortener</a> gem came out of my need to tweet rss feeds to twitter every 5 minutes and shortening the url is the first thing required to do that. I looked at different url shortening services and decided to use <a href="http://bit.ly">bit.ly</a>&#8217;s api as it appeared to be mature, comprehensive and more stable compared to other url shortening services. </p>
<p>The <a href="http://github.com/nas/url_shortener">url_shortener</a> gem allows to shorten/expand urls, retrieve stats and other information about them.</p>
<p><strong>How to use</strong></p>
<p>Since it is an API wrapper hence an account with <a href="http://bit.ly">bit.ly</a> i.e. login and api key is required to use the <a href="http://github.com/nas/url_shortener">url_shortener</a> gem. bit.ly gives an API key to every user so if you have an account with bit.ly then you already have the key otherwise you can get it easily by signing up with <a href="http://bit.ly">bit.ly</a></p>
<p>Then the usual drill to install the gem<br />
<code><br />
gem sources -a http://gemcutter.org<br />
sudo gem install url_shortener<br />
</code></p>
<p>For a quick test, start an irb session and</p>
<p><code><br />
require 'rubygems'<br />
require 'url_shortener'<br />
</code></p>
<p>Before sending any request to bit.ly you need to initialize the Authorize and Client classes with bit.ly credentials:<br />
<code><br />
authorize = UrlShortener::Authorize.new 'your_bitly_login', 'your_bitly_api_key'<br />
</code><br />
If you don&#8217;t have a bit.ly account then you can use the bitlyapidemo key to try this<br />
<code><br />
authorize = UrlShortener::Authorize.new 'bitlyapidemo', 'R_0da49e0a9118ff35f52f629d2d71bf07'<br />
client = UrlShortener::Client.new(authorize)<br />
</code><br />
bit.ly provides following four main end points or resources:</p>
<ul>
<li><a href="http://api.bit.ly/shorten?version=2.0.1&#38;longUrl=http://cnn.com&#38;login=bitlyapidemo&#38;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&#38;format=xml">shorten</a></li>
<li><a href="http://api.bit.ly/expand?version=2.0.1&#38;hash=31IqMl&#38;login=bitlyapidemo&#38;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&#38;format=xml">expand</a></li>
<li><a href="http://api.bit.ly/stats?version=2.0.1&#38;shortUrl=http://bit.ly/1RmnUT&#38;login=bitlyapidemo&#38;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&#38;format=xml">stats</a></li>
<li><a href="http://api.bit.ly/info?version=2.0.1&#38;hash=31IqMl&#38;login=bitlyapidemo&#38;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&#38;format=xml">info</a></li>
</ul>
<p>I suggest to check the xml outputs by clicking on the above end points to familiarize with the results returned.</p>
<p><strong>Shorten Urls</strong><br />
Once you have the client object then call the shorten method on it with the url as the parameter.<br />
<code><br />
shorten = client.shorten('http://www.yahoo.com') # =&#62; UrlShortener::Response::Shorten object<br />
</code><br />
 This will return a UrlShortener::Response::Shorten object which has several useful methods to parse results and access xml elements<br />
<code><br />
shorten.result # =&#62; returns a hash of all data returned from bitly<br />
shorten.urls # =&#62; returns the short url<br />
</code><br />
The shorten method accepts a single or multiple url as parameters to shorten the urls<br />
<code><br />
shorten = client.shorten('http://www.yahoo.com', 'http://www.google.com', 'http://github.com')<br />
</code><br />
apart from the #urls and #result method you can also pass<br />
#urls_with_long_url_keys, #hashes_with_long_url_keys, #hash and any xml element name within results-&#62;nodeKeyVal element<br />
<code><br />
shorten.urls_with_long_url_keys<br />
#etc<br />
</code></p>
<p><strong>Expand Urls</strong><br />
To expand urls, either the hash or short url hash can be passed to the expand method which returns UrlShortener::Response::Expand object<br />
<code><br />
expand = client.expand(:shortUrl =&#62; 'http://bit.ly/1RmnUT') # =&#62; UrlShortener::Response::Expand object<br />
#OR<br />
expand = client.expand(:hash =&#62; '1RmnUT') # =&#62; UrlShortener::Response::Expand object<br />
</code><br />
Similar to the shorten method, you can call #result method to get a hash of xml or #url/#long_url to get the expanded long url<br />
<code><br />
expand.result # =&#62; returns a hash of all data returned from bitly<br />
expand.url # =&#62; returns a long url string<br />
</code></p>
<p><strong>Stats</strong><br />
<code><br />
stats = client.stats(:shortUrl =&#62; 'http://bit.ly/1RmnUT')  # =&#62; UrlShortener::Response::Stat object<br />
#OR<br />
stats = client.stats(:hash =&#62; '1RmnUT') # =&#62; UrlShortener::Response::Stat object<br />
stats.result # =&#62; returns a hash of all data returned from bitly<br />
</code><br />
There is a #referrers and #user_referrers method in the UrlShortener::Response::Stat class that does the xml parsing to return all referrers and as usual any xml element name can be passed as the method name to the stats response object like<br />
<code><br />
stats.hash # =&#62; returns url hash<br />
stats.referrers # =&#62; returns an array of referrers<br />
stats.user_referrers # =&#62; returns an arrays of referrers<br />
stats.clicks # =&#62; returns number of clicks<br />
</code></p>
<p><strong>Info</strong><br />
<code><br />
info = client.info(:shortUrl =&#62; 'http://bit.ly/1RmnUT') # =&#62; UrlShortener::Response::Info object<br />
#OR<br />
info = client.info(:hash =&#62; '1RmnUT') # =&#62; UrlShortener::Response::Info object<br />
info.result # =&#62; returns a hash of all data returned from bitly<br />
</code><br />
All elements within <a href="http://api.bit.ly/info?version=2.0.1&#38;hash=31IqMl&#38;login=bitlyapidemo&#38;apiKey=R_0da49e0a9118ff35f52f629d2d71bf07&#38;format=xml">doc element</a> are available as methods to the info response object.<br />
If you are a ruby purist and don&#8217;t want to use camelized method calls then you can use the underscore, for e.g.<br />
<code><br />
info.htmlMetaDescription<br />
#OR<br />
info.html_meta_description<br />
</code><br />
will work seamlessly and give the same results. Checkout the results return by bitly&#8217;s info resource to see what other methods are available to info response object.</p>
<p><a href="http://github.com/nas/url_shortener">url_shortener gem is available on github.</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Task G: One Last Wafer-Thin Change]]></title>
<link>http://pedromtavares.wordpress.com/2009/11/25/task-g-one-last-wafer-thin-change/</link>
<pubDate>Wed, 25 Nov 2009 14:52:30 +0000</pubDate>
<dc:creator>pedromtavares</dc:creator>
<guid>http://pedromtavares.wordpress.com/2009/11/25/task-g-one-last-wafer-thin-change/</guid>
<description><![CDATA[In this task we&#8217;ll take a peek at how to genereate XML feed from our application. We&#8217;ll ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In this task we&#8217;ll take a peek at how to genereate XML feed from our application. We&#8217;ll start by generating a link that will tell us who bought a certain product, so it would be something link http://mystore.com/info/who_bought/product_id<br />
Notice that&#8217;s the opposite direction of our application structure, you can&#8217;t access a line item from a product, but you can acess a product from a line item, so how do we tell Rails to do it both ways? By adding one line of code to the product model:</p>
<pre class="brush: ruby;">
class Product &#60; ActiveRecord::Base
  has_many:orders, :through=&#62;:line_items
  has_many:line_items
#rest of the code
</pre>
<p>Now it knows that a product has orders, but it has to go through the line items database table first to get to those orders. We&#8217;re all set to generate the info controller with the who_bought action now (look back at the link mentioned). To the command propmt we go:</p>
<pre class="brush: plain;">
ruby script/generate controller info who_bought
</pre>
<p>With all files created, time to edit that who_bought action (and override the authorize method):</p>
<pre class="brush: ruby;">
class InfoController &#60; ApplicationController

  def who_bought
    @product=Product.find(params[:id])
    @orders=@product.orders
    respond_to do &#124;format&#124;
      format.xml{ render :layout =&#62; false }
    end
  end

  protected

  def authorize
  end
end
</pre>
<p>Who_bought is basically returning the orders from a given product ID. Notice it will format XML requests with no layout, so it will just be pure XML. Now we&#8217;ll need to implement a template that will return XML data to XML requests, and we can do that by creating an XML builder. Create a who_bought.xml.builder file in the info view directory and code this in:</p>
<pre class="brush: ruby;">
xml.order_list(:for_product =&#62; @product.title) do
  for o in @orders
    xml.order do
	    xml.name(o.name)
	    xml.email(o.email)
    end
  end
end
</pre>
<p>This builder will render whenever a XML request is made to the who_bought action, so, as a view file, it can use all the instance variables from the info controller. As you can see, that&#8217;s just pure Ruby code that&#8217;s telling the XML object to do a few things:<br />
- Create an orderlist tag with a for_product attribute filled in with the product title data.<br />
- Create an order tag (with no data in) with 2 other tags embedded in it: name (with the order name data in it) and email (with the order email data in it).</p>
<p>To add an attribute all you do is add a hash collection to the tag you want, to add data you just pass it as a parameter and to nest other tags within a tag you just put them in a block inside the outer tag. To check this format out, just access the method and pass an ID with a .xml extension in the end, such as: http://localhost:3000/info/who_bought/1.xml</p>
<p>It&#8217;d be nice to render HTML case somebody accesses the page normally, with a GET request, so let&#8217;s create a simple view file that will supply mailing links to all the people who ordered a specific product (e-mail marketing is one of the reasons you should add XML feed to your applications, and that&#8217;s why we&#8217;re mentioning mail_to here). Edit your who_bought.html.erb file with this:</p>
<pre class="brush: ruby;">
&#60;h3&#62;People Who Bought &#60;%= @product.title %&#62;&#60;/h3&#62;
&#60;ul&#62;
  &#60;% for order in @orders -%&#62;
  &#60;li&#62;
    &#60;%= mail_to order.email, order.name %&#62;
  &#60;/li&#62;
  &#60;% end -%&#62;
&#60;/ul&#62;
</pre>
<p>Since now we have some HTML to render, we need to tell the controller that he should render HTML case that&#8217;s what the HTTP request wants:</p>
<pre class="brush: ruby;">
def who_bought
    @product=Product.find(params[:id])
    @orders=@product.orders
    respond_to do &#124;format&#124;
      format.html
      format.xml{ render :layout =&#62; false }
    end
  end
</pre>
<p>We have 2 ways of generating XML, one is through the builder which we already did, and another one is through the to_xml method that every model object has, which is easier to implement but not easy to maintain, edit the who_bought method again so that it will generate XML automatically:</p>
<pre class="brush: ruby;">
def who_bought
    @product=Product.find(params[:id])
    @orders=@product.orders
    respond_to do &#124;format&#124;
      format.html
      format.xml{ render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml=&#62; @product.to_xml(:include =&#62; <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rders) }
    end
  end
</pre>
<p>Now all the product information will be dumped and rendered when a XML request comes. As said, this is hard to maintain because you can&#8217;t really set the XML the way you want, for that we use the builder template, but it&#8217;s always nice to know an easier way to do it cause you don&#8217;t mind just dumping everything.</p>
<p>Before finishing off our application, let&#8217;s generate its documentation. Rails turns the hassle of documenting everything into one single line of code in the command propmt, but before you do that, edit the README_FOR_APP file in the &#8216;doc&#8217; directory with some description about this application, because it will show on the first page of the generated documentation. Now, to the code:</p>
<pre class="brush: plain;">
rake doc:app
</pre>
<p>And we&#8217;re done coding the application. But don&#8217;t think it&#8217;s over, on the next task and last task we&#8217;ll be doing one of the most important things in application development: testing. See you then.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[De la Servidumbre Moderna - Eres un esclavo moderno]]></title>
<link>http://mdm84.wordpress.com/2009/11/25/de-la-servidumbre-moderna-eres-un-esclavo-moderno/</link>
<pubDate>Wed, 25 Nov 2009 09:40:41 +0000</pubDate>
<dc:creator>mdm84</dc:creator>
<guid>http://mdm84.wordpress.com/2009/11/25/de-la-servidumbre-moderna-eres-un-esclavo-moderno/</guid>
<description><![CDATA[Para todxs aquellos que aun no se han dado cuenta de que viven en un estado de esclavitud, donde mil]]></description>
<content:encoded><![CDATA[Para todxs aquellos que aun no se han dado cuenta de que viven en un estado de esclavitud, donde mil]]></content:encoded>
</item>
<item>
<title><![CDATA[Task F: Administration]]></title>
<link>http://pedromtavares.wordpress.com/2009/11/24/task-f-administration/</link>
<pubDate>Tue, 24 Nov 2009 17:44:38 +0000</pubDate>
<dc:creator>pedromtavares</dc:creator>
<guid>http://pedromtavares.wordpress.com/2009/11/24/task-f-administration/</guid>
<description><![CDATA[In this task we&#8217;ll learn how to create a simple administration system that will allow restrict]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In this task we&#8217;ll learn how to create a simple administration system that will allow restricted access to product maintenance (what we created in task A), orders (task E) and a new user management system.</p>
<p>Let&#8217;s start with the user management system that will allow us to create, edit, view and delete users in our online shop. These users will have only a login and a password, which will be hashed by the SH1 digest and then saved into the database. We&#8217;ll use a generator and specify the fields we need, and by doing that the migration will be already filled with the columns we specified. At your application directory, open your command prompt and type this in:</p>
<pre class="brush: plain;">
ruby script/generate scaffold user name:string hashed_password:string salt:string
</pre>
<p>And to make the database base changes happen:</p>
<pre class="brush: plain;">
rake db:migrate
</pre>
<p>Open your database and checkout the new users table with all the fields we specified. As we move on to the user model, notice that this will get a little more complicated due to the fact that we need to work with a plain text password in the application, but with a hashed version in the database, and knowing that complication, it&#8217;s better to work out the model step by step, so first, let&#8217;s put in some validation:</p>
<pre class="brush: ruby;">
require 'digest/sha1'

class User &#60; ActiveRecord::Base

  validates_presence_of :name
  validates_uniqueness_of :name

  attr_accessor :password_confirmation
  validates_confirmation_of :password

  validate :password_non_blank

  private

  def password_non_blank
    errors.add_to_base(&#34;Missing password&#34;) if hashed_password.blank?
  end
end
</pre>
<p>You should be familiar with the presence and uniqueness validation, we&#8217;ve used before, but there&#8217;s a new one named validates_confirmation_of that will basically check if 2 fields are matching, in this case, the password field with a &#8216;Confirm Password&#8217; field (this is pretty common). Lastly we validate the existence of a password, but notice we check for its hashed version, not itself, this is because the hashed version is the one being stored in the database, thus, what matters to validation. The require method includes the SHA1 digest library, allowing us to use all its methods, so let&#8217;s get to that by adding a new private class method to the user model that will encrypt the plain text password into a hashed result:</p>
<pre class="brush: ruby;">
def self.encrypted_password(password,salt)
  string_to_hash = password + &#34;secretkey&#34; + salt
  Digest::SHA1.hexdigest(string_to_hash)
end
</pre>
<p>The method above is taking a plain text password (which the user inputs) and a random value named salt, which is used to concatenate to the password and stored in the database making the hashed value even more unpredictable. Notice the &#8220;secretkey&#8221;, which makes the hashed value even richer, and is only available to people who have access to the Rails code. A digest is then applied to that whole string, turning it into a 160-bit hash such as &#8220;588aa91d21e71d0e2e3f6febfe8e90e1819ae97f&#8221;.<br />
The salt was mentioned but a way to create it wasn&#8217;t, so we&#8217;ll be doing that by adding another private class method:</p>
<pre class="brush: ruby;">
def create_new_salt
  self.salt = self.object_id.to_s + rand.to_s
end
</pre>
<p>Notice that by writing self.salt, we&#8217;re avoiding that Ruby treats salt as a local variable, which would be of no effect to us since it would just get discarded and collected by the garbage collector, by doing this we&#8217;re telling it to use the salt= accessor method instead, which updates its value, in this case, we&#8217;re updating with the object&#8217;s id (by using an accessor method that returns the object&#8217;s current id) concatenated with a random string.</p>
<p>Now that we have the hashing process all set up, we need to make it so a plain text password sent by an user input will be treated and sent into the database, to do that, we&#8217;ll use a so called &#8216;virtual attribute&#8217;, which is something we can manipulate but doesn&#8217;t go into the database. Of course we can&#8217;t use Rails&#8217; built-in accessor methods for that virtual attribute, because that would make it go into the database, instead, we&#8217;ll hard code our own accessors into the user model:</p>
<pre class="brush: ruby;">
def password
  @password
end

def password=(pwd)
  @password = pwd
  return if pwd.blank?
  create_new_salt
  self.hashed_password = User.encrypted_password(self.password,self.salt)
end
</pre>
<p>Last thing we need to is create a User class method that checks if the right login/password combination has been supplied and returns that object if it has.</p>
<pre class="brush: ruby;">
def self.authenticate(name,password)
  user = self.find_by_name(name)
  if user
    expected_password = encrypted_password(password,user.salt)
    if user.hashed_password != expected_password
      user = nil
    end
  end
  user
end
</pre>
<p>Notice the find_by_name method, whenever an undefined method that starts with find_by_ is called, Rails looks for the last part of the string, in this case, name, and begins a search on the class database table using that part as a string, in this case, it searches all users by their name using the name passed as a parameter.</p>
<p>Let&#8217;s put everything we did to the user model so far in a single chunk of code:</p>
<pre class="brush: ruby;">
require 'digest/sha1'

class User &#60; ActiveRecord::Base

  validates_presence_of :name
  validates_uniqueness_of :name

  attr_accessor :password_confirmation
  validates_confirmation_of :password

  validate :password_non_blank

  # 'password' is a virtual attribute

  def password
    @password
  end

  def password=(pwd)
    @password = pwd
    return if pwd.blank?
    create_new_salt
    self.hashed_password = User.encrypted_password(self.password,self.salt)
  end

  def self.authenticate(name,password)
    user = self.find_by_name(name)
    if user
      expected_password = encrypted_password(password,user.salt)
      if user.hashed_password != expected_password
        user = nil
      end
    end
    user
  end

  private

  def password_non_blank
    errors.add_to_base(&#34;Missing password&#34;) if hashed_password.blank?
  end

  def self.encrypted_password(password,salt)
    string_to_hash = password + &#34;wibble&#34; + salt
    Digest::SHA1.hexdigest(string_to_hash)
  end

  def create_new_salt
    self.salt = self.object_id.to_s + rand.to_s
  end

end
</pre>
<p>Moving on to the administration itself, let&#8217;s edit the user controller file that was generated by scaffold, first, the index method:</p>
<pre class="brush: ruby;">
def index
    @users = User.find(:all, <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder =&#62; :name)

    respond_to do &#124;format&#124;
      format.html # index.html.erb
      format.xml  { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @users }
    end
  end
</pre>
<p>All we did was alter the first second line of code to return all users to the @users instance variable. Moving on to the create method:</p>
<pre class="brush: ruby;">
def create
    @user = User.new(params[:user])

    respond_to do &#124;format&#124;
      if @user.save
        flash[:notice] = &#34;User #{@user.name} was successfully created.&#34;
        format.html { redirect_to(:action =&#62; :index) }
        format.xml  { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @user, :status =&#62; :created, :location =&#62; @user }
      else
        format.html { render :action =&#62; &#34;new&#34; }
        format.xml  { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @user.errors, :status =&#62; :unprocessable_entity }
      end
    end
  end
</pre>
<p>This time we added a flash notice and an index redirection, because it really doesn&#8217;t make sense to redirect to the edit page. Finally, the update method:</p>
<pre class="brush: ruby;">
def update
    @user = User.find(params[:id])

    respond_to do &#124;format&#124;
      if @user.update_attributes(params[:user])
        flash[:notice] = &#34;User #{@user.name} was successfully updated.&#34;
        format.html { redirect_to(:action =&#62; :index) }
        format.xml  { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> k }
      else
        format.html { render :action =&#62; &#34;edit&#34; }
        format.xml  { render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @user.errors, :status =&#62; :unprocessable_entity }
      end
    end
  end
</pre>
<p>Same flash notice and redirection as the create method.</p>
<p>We have our model and our controller ready, now we did to edit some view files, let&#8217;s start by the index.html.erb (inside the user folder, of course)</p>
<pre class="brush: ruby;">
&#60;h1&#62;Listing users&#60;/h1&#62;

&#60;table&#62;
  &#60;tr&#62;
    &#60;th&#62;Name&#60;/th&#62;
  &#60;/tr&#62;

&#60;% @users.each do &#124;user&#124; %&#62;
  &#60;tr&#62;
    &#60;td&#62;&#60;%=h user.name %&#62;&#60;/td&#62;
    &#60;td&#62;&#60;%= link_to 'Show', user %&#62;&#60;/td&#62;
    &#60;td&#62;&#60;%= link_to 'Edit', edit_user_path(user) %&#62;&#60;/td&#62;
    &#60;td&#62;&#60;%= link_to 'Destroy', user, :confirm =&#62; 'Are you sure?', :method =&#62; :delete %&#62;&#60;/td&#62;
  &#60;/tr&#62;
&#60;% end %&#62;
&#60;/table&#62;

&#60;br /&#62;

&#60;%= link_to 'New user', new_user_path %&#62;
</pre>
<p>The scaffold generates viewing of all the table&#8217;s attributes, which in this case is a bad thing because the password and salt information do not need to show, so we removed all the data related to that in the code above, and with that same line of though, we&#8217;ll now edit the new.html.erb file:</p>
<pre class="brush: ruby;">
&#60;div class=&#34;depot-form&#34;&#62;
  &#60;%= error_messages_for :user%&#62;
  &#60;% form_for(@user) do &#124;f&#124; %&#62;
  &#60;fieldset&#62;
    &#60;legend&#62;Enter User Details&#60;/legend&#62;
    &#60;p&#62;
      &#60;label for=&#34;user_name&#34;&#62;Name:&#60;/label&#62;
      &#60;%=  f.text_field:name, :size=&#62;40 %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;label for=&#34;user_password&#34;&#62;Password:&#60;/label&#62;
      &#60;%=  f.password_field :password, :size=&#62;40%&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;label for=&#34;user_password_confirmation&#34;&#62;Confirm:&#60;/label&#62;
      &#60;%=  f.password_field :password_confirmation, :size=&#62;40 %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;%=f.submit &#34;Add User&#34;, :class =&#62; &#34;submit&#34; %&#62;
    &#60;/p&#62;
  &#60;/fieldset&#62;
  &#60;% end %&#62;
&#60;/div&#62;

&#60;%= link_to 'Back', users_path %&#62;
</pre>
<p>Notice we removed the salt and hashed password information again and replaced it with a common password field and a confirmation field. As seen on Task A, we need to add our custom stylesheet to the stylesheet helper on the user layout file (it comes with the default scaffold stylesheet):</p>
<pre class="brush: ruby;">
&#60;!DOCTYPE htmlPUBLIC &#34;-//W3C//DTDXHTML1.0Transitional//EN&#34; &#34;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&#34;&#62;
&#60;html xmlns=&#34;http://www.w3.org/1999/xhtml&#34; xml:lang=&#34;en&#34; lang=&#34;en&#34;&#62;
&#60;head&#62;
&#60;meta http-equiv=&#34;content-type&#34; content=&#34;text/html;charset=UTF-8&#34;/&#62;
&#60;title&#62;Users:&#60;%= controller.action_name %&#62;&#60;/title&#62;
&#60;%= stylesheet_link_tag'scaffold','depot' %&#62;
&#60;/head&#62;
</pre>
<p>All done, now we have a user management system with some design on it, you should add a user now, we will need it for the next step which will be the creation of a login system, which will be the primal basis for our administration system, so let&#8217;s get to it. First thing we need to do is generate a controller with some specific actions (at the command propmt in your application directory):</p>
<pre class="brush: plain;">
rubyscript/generate controller admin login logout index
</pre>
<p>With all files created, let&#8217;s edit the login method in the recently created admin controller:</p>
<pre class="brush: ruby;">
def login
    session[:user_id] = nil
    if request.post?
      user = User.authenticate(params[:name], params[:password])
      if user
        session[:user_id] = user.id;
        redirect_to(:action =&#62; &#34;index&#34;)
      else
        flash.now[:notice] = &#34;Invalid user/password combination&#34;
      end
    end
  end
</pre>
<p>Notice the request.post? condition, this is a way to know whether the page is being executed through a GET request (by some URL) or through a POST request (through a form), this way the action knows that it should only execute the login logic case the user has already submitted the form, if he hasn&#8217;t, the login view file will be parsed. The login logic is pretty simple, the authenticate method is called using the name and password passed into the request by the login form and returns a user case there is one (or nil case there isn&#8217;t), then a session variable is set using the user id and a redirection is made.<br />
Having the controller all set, it&#8217;s time to edit the login view file (that will get parsed case the login action is accessed by some URL or redirection):</p>
<pre class="brush: ruby;">
&#60;div class=&#34;depot-form&#34;&#62;
  &#60;% form_tag do %&#62;
  &#60;fieldset&#62;
    &#60;legend&#62;Please Log In&#60;/legend&#62;
    &#60;p&#62;
      &#60;label for=&#34;name&#34;&#62;Name:&#60;/label&#62;
      &#60;%= text_field_tag :name, params[:name] %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;label for=&#34;password&#34;&#62;Password:&#60;/label&#62;
      &#60;%= password_field_tag :password, params[:password]%&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;%= submit_tag &#34;Login&#34; %&#62;
    &#60;/p&#62;
  &#60;/fieldset&#62;
  &#60;% end %&#62;
&#60;/div&#62;
</pre>
<p>Since there is no &#8216;admin&#8217; model, we have to hard code the form using different helpers. This time, instead of form_for, we&#8217;re using form_tag, which creates a simple form tag that envelops the Ruby block. Then we use field_tags, which need a name and a value, which, in this case, are being filled in directly with parameters passed by the params hash. Okay, so the user logs in, then what? Then an index page shows, one which we will edit right now: (index.html.erb in the admin controller)</p>
<pre class="brush: ruby;">
&#60;h1&#62;Welcome&#60;/h1&#62;
It's &#60;%= Time.now %&#62;
We have&#60;%= pluralize(@total_orders, &#34;order&#34;) %&#62;.
</pre>
<p>Pluralize helper just checks if it should say &#8216;order&#8217; or &#8216;orders&#8217;, and its using a instance variable which we didn&#8217;t define yet. Going back to the controller, let&#8217;s add the until-now undefined @total_orders variable to the index method:</p>
<pre class="brush: ruby;">
def index
  @total_orders = Order.count
end
</pre>
<p>Order.count returns the number of rows in the orders table. Now that we have our first administration page working with our login system, it&#8217;s time to actually make logging in necessary to anyone who tries to access administrating pages (which is the whole point). This sounds much, but it&#8217;s just one line of code (and a method). But what would be the perfect place to put that in, no use putting in the admin controller because the product maintenance would be accessible, and what about everything else related to administration that isn&#8217;t in the admin controller? As you can see, this requires global attention, and when it comes to globalizing actions, the best way to do it is by editing the application controller, which is the &#8216;mother&#8217; of all controllers (all controllers heir all methods from the application controller). Knowing the right place to mess with (application_controller.rb), code this in:</p>
<pre class="brush: ruby;">
class ApplicationController &#60; ActionController::Base

  before_filter :authorize, :except =&#62; :login

  helper :all
  protect_from_forgery

  protected

  def authorize
    unless User.find_by_id(session[:user_id])
      flash[:notice] = &#34;Please log in&#34;
      redirect_to :controller =&#62; :admin, :action =&#62; :login
    end
  end

end
</pre>
<p>We&#8217;re telling Rails that we want to execute the authorize method before rendering any page, with the exception of the login action, obviously (you don&#8217;t have to be authorized to access the login page), redirecting the user to the login page and flashing a message pointing that he needs to log in first. But we don&#8217;t want the log in page to be forced on the user in the store page, for example, so what do we do? We could just add a bunch of exceptions, but that wouldn&#8217;t look nice and would need maintenance every time something new was added to the application, so it&#8217;s better to just override the authorize method on every controller that doesn&#8217;t need authorization, an example of this can be shown by adding few lines of code to the store controller:</p>
<pre class="brush: ruby;">
protected

def authorize
end
</pre>
<p>Now we have our logic all set for the administration system, so we need to make the layout a little bit more consistant, and we&#8217;ll do that by adding the same sidebar as the one in the store layout to all pages, with a few options added for logged in administrators. This way, we will have a single layout for the whole application, needo, huh? Although a big change, this requires only a single line of coded added to the mother of controllers, the application controller:</p>
<pre class="brush: ruby;">
class ApplicationController &#60; ActionController::Base

  layout &#34;store&#34;

  before_filter :authorize, :except =&#62; :login

  helper :all
  protect_from_forgery

  protected

  def authorize
    unless User.find_by_id(session[:user_id])
      flash[:notice] = &#34;Please log in&#34;
      redirect_to :controller =&#62; :admin, :action =&#62; :login
    end
  end

end
</pre>
<p>With one line of code we made the whole application include the store layout, which is prettier than anything we&#8217;ve done so far. Make sure you delete the &#8216;users&#8217; and the &#8216;products&#8217; layout, by simple file deletion or by the command prompt: (rm command for Linux users, erase command for Windows users)</p>
<pre class="brush: plain;">
rm app/views/layouts/products.html.erb
rm app/views/layouts/users.html.erb
</pre>
<p>Now that the store layout is global, we need to make a few changes to it. First, a condition is needed to check if there is a @cart instance variable before executing the code relative to the shopping cart, we didn&#8217;t need this before because all the store actions instantiated the @cart object, but other controllers won&#8217;t. Next we will add a condition to check if there is someone logged in (an administrator, of course) and show some administrative options on the sidebar. All this can be done with this code (in the store layout file):</p>
<pre class="brush: ruby;">
&#60;!DOCTYPE html PUBLIC &#34;-//W3C//DTD XHTML 1.0 Transitional//EN&#34;
&#34;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&#34; &#62;
&#60;html&#62;
&#60;head&#62;
&#60;title&#62;Pragprog Books Online Store&#60;/title&#62;
&#60;%= stylesheet_link_tag &#34;depot&#34; , :media =&#62; &#34;all&#34; %&#62;
&#60;%= javascript_include_tag :defaults %&#62;
&#60;/head&#62;
&#60;body id=&#34;store&#34;&#62;
&#60;div id=&#34;banner&#34;&#62;
&#60;%= image_tag(&#34;logo.png&#34; ) %&#62;
&#60;%= @page_title &#124;&#124; &#34;Pragmatic Bookshelf&#34; %&#62;
&#60;/div&#62;
&#60;div id=&#34;columns&#34;&#62; &#60;/div&#62;
&#60;div id=&#34;side&#34;&#62;
  &#60;div id=&#34;cart&#34;&#62;
    &#60;% if @cart %&#62;
      &#60;% hidden_div_if(@cart.items.empty?, :id =&#62; &#34;cart&#34; ) do %&#62;
      &#60;%= render(:partial =&#62; &#34;cart&#34;, <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> bject =&#62; @cart) %&#62;
      &#60;% end %&#62;
    &#60;% end %&#62;
  &#60;/div&#62;
  &#60;a href=&#34;http://www....&#34;&#62;Home&#60;/a&#62;&#60;br /&#62;
  &#60;a href=&#34;http://www..../faq&#34;&#62;Questions&#60;/a&#62;&#60;br /&#62;
  &#60;a href=&#34;http://www..../news&#34;&#62;News&#60;/a&#62;&#60;br /&#62;
  &#60;a href=&#34;http://www..../contact&#34;&#62;Contact&#60;/a&#62;&#60;br /&#62;
  &#60;%if session[:user_id]%&#62;
    &#60;br/&#62;
    &#60;%= link_to 'Orders',  :controller =&#62; 'orders' %&#62;&#60;br/&#62;
    &#60;%= link_to 'Products',:controller =&#62; 'products' %&#62;&#60;br/&#62;
    &#60;%= link_to 'Users',   :controller =&#62; 'users' %&#62;&#60;br/&#62;
    &#60;br/&#62;
    &#60;%=link_to 'Logout',   :controller =&#62; :admin, :action =&#62; 'logout'%&#62;
  &#60;% end %&#62;
&#60;/div&#62;
&#60;div id=&#34;main&#34;&#62;
  &#60;% if flash[:notice] -%&#62;
  &#60;div id=&#34;notice&#34;&#62; &#60;%=flash[:notice]%&#62; &#60;/div&#62;
  &#60;%  end -%&#62;
&#60;%= yield :layout %&#62;
&#60;/div&#62;
&#60;/body&#62;
&#60;/html&#62;
</pre>
<p>Next we&#8217;ll be adding a few security measures so that the last administrator cannot be deleted making the administration panel unaccessible. Rails has methods called &#8216;hook&#8217; methods, we already used the &#8216;validate&#8217; hook that validates an object state, and now it&#8217;s time to use a hook that will raise an exception on a database line deletion, making it rollback case the hook returns true. To do this we only need to add a method to the user model:</p>
<pre class="brush: ruby;">
def after_destroy
  if User.count.zero?
    raise &#34;Can't delete last user&#34;
  end
end
</pre>
<p>Now we need to rescue that exception and show it to the user, and since it is risen when we order the deletion of a user, we&#8217;ll need to rescue in on the destroy action of the user controller:</p>
<pre class="brush: ruby;">
def destroy
  @user = User.find(params[:id])
  begin
    flash[:notice] = &#34;User #{@user.name} deleted&#34;
    @user.destroy
  rescue Exception =&#62; e
    flash[:notice] = e.message
  end

  respond_to do &#124;format&#124;
    format.html { redirect_to(users_url) }
    format.xml  { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> k }
  end
end
</pre>
<p>There we go, now an error message will pop case the last user is issued to deletion. Wait, we almost forgot about one thing: the log out action, we created a link to it on the sidebar but didn&#8217;t set the action itself, so let&#8217;s get to that (on the admin controller):</p>
<pre class="brush: ruby;">
def logout
  session[:user_id] = nil
  flash[:notice] = &#34;Logged out&#34;
  redirect_to(:action=&#62; &#34;login&#34;)
end
</pre>
<p>Session clearing, flash notice and a redirection, nothing we haven&#8217;t mastered already.</p>
<p><strong>Now</strong> we&#8217;re all set on the administration system, the user can log in and out, add users, and know that it is all being restricted. But, before we finish this task, let&#8217;s apply the filter concept we learned in the store controller. Remember all those @cart = find_cart assignments? They&#8217;re almost in every store action, which is ugly because it&#8217;s duplicated code, and thanks to filters, we can avoid that by making use of one. First we need to change the find_cart method to assign an instance variable (instead of returning something that would get assigned to an instance variable):</p>
<pre class="brush: ruby;">
def find_cart
  @cart=(session[:cart]&#124;&#124;=Cart.new)
end
</pre>
<p>And lastly, add the filter to the beggining of the controller (with an exception of the empty_cart method which clears out the instance variable):</p>
<pre class="brush: ruby;">
before_filter:find_cart,:except=&#62;:empty_cart
</pre>
<p>Now the find_cart method is executed everywhere in the store controller and you can remove all the @cart = find_cart assignments from it.</p>
<p>Our application is coming together, we&#8217;re almost done! See you next task.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Renaming Session in Authlogic]]></title>
<link>http://bobbyprabowo.wordpress.com/2009/11/24/renaming-session-in-authlogic/</link>
<pubDate>Tue, 24 Nov 2009 17:19:13 +0000</pubDate>
<dc:creator>Bobby Prabowo</dc:creator>
<guid>http://bobbyprabowo.wordpress.com/2009/11/24/renaming-session-in-authlogic/</guid>
<description><![CDATA[saya rada jenuh menggunakan nama user_session sebagai nama model untuk authlogic, yah saya iseng aja]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>saya rada jenuh menggunakan nama user_session sebagai nama model untuk authlogic, yah saya iseng aja ganti namanya menggunakan nama session.</p>
<p>dan <strong>voilla</strong> error pun terjadi.</p>
<p>permasalahannya authlogic menggunakan teknik pembacaan parameter untuk session secara default seperti ini =&#62; {nama_model_yang_divalidasi}_session, contoh user_session. makanya dia muncul dengan error interning string.</p>
<p>nah solusinya kalau mau tetap mempertahankan nama model tetap session cukup tambahkan</p>
<p><code>authenticate_with User</code></p>
<p>dalam isi class session tersebut.</p>
<p>semoga bermanfaat.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Curriculum advice for journalism schools]]></title>
<link>http://stevebuttry.wordpress.com/2009/11/24/curriculum-advice-for-journalism-schools/</link>
<pubDate>Tue, 24 Nov 2009 15:29:36 +0000</pubDate>
<dc:creator>Steve Buttry</dc:creator>
<guid>http://stevebuttry.wordpress.com/2009/11/24/curriculum-advice-for-journalism-schools/</guid>
<description><![CDATA[I haven&#8217;t spent this much time talking to journalism professors and students since I graduated]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I haven&#8217;t spent this much time talking to journalism professors and students since I graduated from Texas Christian University (let&#8217;s just say some time ago).</p>
<p>I visited TCU last week to present seminars on the <a title="Follow  my C3 seminar at TCU today" href="http://stevebuttry.wordpress.com/2009/11/18/follow-my-c3-seminar-at-tcu-today/" target="_blank">Complete Community Connection</a> and <a title="Follow the liveblog of my ethics seminar" href="http://stevebuttry.wordpress.com/2009/11/19/follow-the-liveblog-of-my-ethics-seminar-at-tcu-today/" target="_blank">journalism ethics in the digital age</a>. And since I was sticking around for some memory-lane time, the curriculum committee at TCU&#8217;s <a title="Schieffer School of Journalism" href="http://www.schiefferschool.tcu.edu/" target="_blank">Schieffer School of Journalism</a> asked me to meet with them and tell them what I think journalism schools should be teaching about our swiftly changing field.</p>
<p>I shared my views with them and will share them with you here shortly. The TCU meetings continued a heavy fall schedule of consultations with journalism faculty and students on a variety of related topics:<!--more--></p>
<ul>
<li>In late August, I was a panelist for the <a title="Accreditation Council on Education in Jouranlism and Mass Communication" href="http://www2.ku.edu/~acejmc/" target="_blank">Accreditation Council on Education in Journalism and Mass Communication</a>, sharing my views on how journalism schools should be teaching today and what sort of standards the council should require. Afterward, I shared some <a title="Resources for journalism educators" href="http://stevebuttry.wordpress.com/2009/08/29/resources-for-journalism-educators-on-digital-ethics-new-business-models-journalism/" target="_blank">resources for journalism educators</a> on this blog.</li>
<li>In mid-September, I met with University of Missouri faculty to advise on plans for <a title="Follow live coverate of APME convention" href="http://stevebuttry.wordpress.com/2009/10/28/follow-live-digital-coverage-of-apme-convention-this-week/" target="_blank">digital-only coverage of the Associated Press Managing Editors convention in St. Louis</a>.</li>
<li>Later in September, I presented an ethics seminar at the University of Kentucky. The visit included an informal discussion over pizza with students about what editors are seeking in interns and journalism graduates. I developed a post of <a title="Elevate your journalism career" href="http://stevebuttry.wordpress.com/2009/09/20/elevate-your-journalism-career/" target="_blank">career advice for journalism students</a> and called their attention to an earlier post on the importance of your <a title="Your digital profile tells people a lot" href="http://stevebuttry.wordpress.com/2009/07/10/your-digital-profile-tells-people-a-lot/" target="_blank">digital profile</a>.</li>
<li>The next week, I met with faculty advisers and editors of the Iowa State Daily, who came to Cedar Rapids to brainstorm issues such as digital coverage, C3 and organizational changes we&#8217;ve made at Gazette Communications.</li>
<li>In November, I led another <a title="Journalism ethics blog " href="http://jrnethics.wordpress.com/" target="_blank">ethics seminar at the University of Nebraska-Lincoln</a> and critiqued the senior portfolios of three UNL seniors (part of the UNL accreditation process, as well as providing advice to the seniors).</li>
<li>Before visiting TCU, I returned to the University of Missouri for an American Society of News Editors/Reynolds Journalism Institute <a title="Public Trust through Public Engagement" href="http://asne.org/key_initiatives/ethics/ethics_forum/live_coverage.aspx" target="_blank">Ethics and Values Forum</a>. Participants included journalism faculty from four other universities, in addition to Missouri. After dinner one night, we had an interesting discussion with several Missouri students, many of whom are already looking for jobs.</li>
<li>I have had frequent discussions with David Perlmutter, new director of the School of Journalism and Mass Communication at the University of Iowa, including plans to team-teach a course with Jim Cremer on <a title="What do you like best about your favorite mobile applications" href="http://stevebuttry.wordpress.com/2009/11/16/what-do-you-like-best-about-your-favorite-mobile-applications/" target="_blank">creating an iPhone application</a>.</li>
</ul>
<p>In various ways in formal events and private conversations, similar concerns about how to teach journalism today came up again and again. If I could summarize the concerns (admitting that I am drawing conclusions that weren&#8217;t always stated explicitly), I would say this: Lots of journalism educators worry how they can and should teach to prepare students for a world that has changed vastly since professors practiced and/or earned graduate degrees and is changing so swiftly that even if professors were current in all respects, their lessons may be outdated by the time their students graduate. While <a title="Journalism Bust, J-School Boom" href="http://www.forbes.com/2009/04/06/journalism-media-jobs-business-media-jobs.html" target="_blank">journalism school enrollment</a> is stronger than the businesses that support journalism, educators are keenly aware that they need to update their curriculum and knowledge or they could face the same sort of crash that news media companies are experiencing.</p>
<p>My response focuses heavily on what journalism schools should be doing to address new needs and challenges. I have not looked at closely at what they should not be doing. But I would suggest that in the current environment, every requirement and every course needs to be re-examined and face demanding questions:</p>
<ul>
<li>Does the course need to be updated?</li>
<li>Should the course be dropped?</li>
<li>Should the course be taught less frequently?</li>
<li>Should the course be combined with another?</li>
<li>Should a required course become an elective?</li>
</ul>
<p>Journalism schools also need to examine their tracks, sequences and structures. If your school offers a &#8220;print sequence,&#8221; you might as well call it an &#8220;outdated sequence.&#8221; While newspapers still command large audiences and generate large revenues, newspaper companies are diversifying and journalism schools need to be educating multi-platform journalists, not print journalists.</p>
<p>As I go through topics that journalism schools might not be covering adequately, I would argue that many of these issues don’t need to be addressed in a standalone class, required or elective. Rather, they should be integrated throughout the curriculum. For instance, if you offer an elective course in Twitter but don’t teach students in your basic reporting course how reporters should use Twitter, you aren’t teaching what you need to teach. I would advise requiring students in their first media writing course to spend at least a couple weeks taking their class notes in Twitter, so they get an early practical exposure and see it as a tool for journalism from the start. And each course should decide the appropriate way to use Twitter in that course.</p>
<p>In other cases, a required or elective course – or perhaps a course combining a few of these topics – might be exactly what a journalism curriculum needs. I will make specific recommendations about how digital skills should be infused throughout the curriculum and about specific courses a journalism school should consider. But as curriculum committees and J-school leaders consider these issues, they will need to consider other factors. As j-schools weigh such factors as course loads, total hours students can take and so on, I would usually err on the side of incorporating digital skills throughout the curriculum, rather than addressing them in specific courses.</p>
<p>These are the topics I think journalism schools need to address:</p>
<p><strong>Social media.</strong> Journalism schools today need to educate students about how social media are changing professional media and society. Twitter is the social platform that needs the most attention right now, but professors need to stay abreast of how society and journalists are using social tools and update their courses appropriately. If Twitter goes the way of MySpace, you need to adjust swiftly to address the next hot social tool. Students are already active in using Facebook, so Facebook is less urgent. Professors also should consider how to use Facebook in courses, such as using a fan page for assignments and exchanges about a course. My primary recommendation here is that social media need to be incorporated throughout the curriculum: Twitter in media writing, reporting, ethics, specialized reporting courses, appropriate strategic communication courses, etc.; visual journalism courses should cover such social tools as YouTube, Flickr, Twitpic and Qik. <a title="Journalism ethics in social networks" href="http://stevebuttry.wordpress.com/2009/02/17/journalism-ethics-in-social-networks/" target="_blank">Ethics courses</a> certainly need to incorporate social media, including Facebook. I also would recommend an advanced course on social media strategy. This would focus on how media organizations need to use social tools to engage the community and serve business customers. This course also would cover potential uses of emerging social tools. This should be an advanced or graduate-level course, serving journalism and strategic communication sequences.</p>
<p><strong>Interactive databases and computer-assisted reporting.</strong> I have been critical before of the use of the term <a title="Computer-assisted reporting: An essential skill, an outdated term" href="http://www.americanpressinstitute.org/pages/resources/2007/02/computerassisted_reporting_an/" target="_blank">computer-assisted reporting</a>. You might as well refer to notebook-assisted reporting or telephone-assisted reporting. This is 2009 and computers have been an essential tool for reporters for a couple decades now. Journalism schools should take the lead in breaking down the data ghettos that have emerged in our profession. Basic reporting courses should cover use of basic spreadsheet, database and mapping programs. These are essential journalism tools and skills and their use should start in basic courses and be required throughout the curriculum. An advanced course should cover development of interactive databases using such tools as Caspio, Django and Ruby on Rails. Again, these skills are as valuable to strategic communication students as to journalism majors.</p>
<p><strong>Programming. </strong>As I mentioned to the TCU curriculum committee, I encourage working with a computer science department to develop cross-disciplinary courses such as my iPhone app course at Iowa. I also encourage working with the computer science department to develop double-major or major-minor combos to help “<a title="&#34;Hacker journalist&#34; finds job, seeks more coders for journalism" href="http://www.pbs.org/idealab/2009/05/hacker-journalist-finds-job-seeks-more-coders-for-journalism130.html" target="_blank">hacker journalists</a>” get the appropriate education in journalism and programming. (I&#8217;m delighted that two students in the iPhone class will be double majors in journalism and informatics.</p>
<p><strong>Mobile journalism. </strong>Basic reporting courses should introduce students to the multitasking skills and demands of <a title="Mobile journalism is changing the news business" href="http://www.editorsweblog.org/newsrooms_and_journalism/2008/05/us_mobile_journalism_is_changing_the_new.php" target="_blank">mobile journalism</a>. The University of Missouri is requiring journalism students to buy iPhones. I don&#8217;t know how important it is to specify a brand (I do use an iPhone), but I think requiring students to use smart phones as journalism tools is an excellent idea. If I were teaching a reporting or multimedia course now, I would require that some specific assignments be carried out entirely with a mobile device. This would require writing on the phone, shooting still photos and video and providing geocoding metadata. An advanced course(s) could focus specifically on mobile journalism, such as developing mobile applications or a <a title="News organizations need mobile-first strategy" href="http://stevebuttry.wordpress.com/2009/11/20/news-organizations-need-mobile-first-strategy/" target="_blank">mobile-first strategy</a>.</p>
<p><strong>The business of journalism. </strong>Journalism students need a more thorough introduction to the business of journalism than I received as a student (almost none) or than students receive today. They need to learn about traditional business models for print and broadcast. They should understand the disruption that is causing the collapse of the business models. They should understand why and how some organizations are seeking to try <a title="PaidContent.org" href="http://paidcontent.org/" target="_blank">paid-content digital models</a> (and they should understand how paid content has been tried before and that it <a title="Newspapers demand: &#34;Gimme another ball!&#34;" href="http://stevebuttry.wordpress.com/2009/07/25/newspapers-demand-gimme-another-ball/" target="_blank">hasn’t worked</a>). They should examine and understand efforts to develop new business models (such as my own <a title="A blueprint for the Complete Community Connection" href="http://stevebuttry.wordpress.com/2009/04/27/a-blueprint-for-the-complete-community-connection/" target="_self">Complete Community Connection</a> model). They should learn about product development and entrepreneurial journalism. They should understand how the advertising model is collapsing on all platforms and study efforts to develop new revenue streams. Tim McGuire’s <a title="Business and Future of Journalism syllabus" href="http://cronkite.asu.edu/mcguireblog/?p=114" target="_blank">Business and Future of Journalism</a> course at Arizona State University provides a good model. While some coverage of business models would be good in lower-level courses, an upper-level course is a good idea and I would encourage requiring it for all students or for some particular majors. The lack of business literacy is a huge problem among journalists and tunnel vision on business issues is a huge problem for people in advertising and executive offices.</p>
<p><strong>Community engagement</strong>. Interaction is a significant part of the future of journalism, from crowdsourcing of stories (investigative, events, features, reviews) to engaging comments on blogs to aggregating the work of community bloggers and citizen journalists. This could certainly be a full course.</p>
<p><strong>Digital content in specialized courses. </strong>A question raised in an email about TCU’s curriculum asked how much digital content should be integrated into advanced courses on journalism specialties, such as public affairs reporting and sports reporting. My answer is that the courses should have as much digital emphasis as the specialties have now, and that’s a lot. For instance, even TCU sportswriting legend <a title="Dan Jenkins Twitter feed" href="http://twitter.com/danjenkinsgd" target="_blank">Dan Jenkins</a>, became a <a title="Golf Writer Dan Jenkins, 79, Starts Using Twitter" href="http://wcco.com/sports/golf/dan.jenkins.twitter.2.1130093.html" target="_blank">Twitter icon</a> this year at age 79. Blogging, liveblogging and video are essential parts of sportswriting now, and the traditional game story is declining in importance to the point that sports writers are <a title="Let's reinvent the game story" href="http://sportsjournalism.org/sports-media-news/let%E2%80%99s-reinvent-the-game-story/" target="_blank">debating whether it’s dying</a>. Any course on a specialty should reflect the current state and projected direction of that specialty.</p>
<p><strong>Visual journalism. </strong>Photojournalism and graphic arts, as narrowly defined for much of my career, are outdated journalism specialties. While those skills remain important, visual journalists need to master (and be taught) a range of digital skills: video, audio, animation, multimedia graphics using programs such as Flash. And, of course, visual journalists need to learn ethical standards for using all these new tools and skills. Journalism students learning graphic arts should certainly learn how to make print graphics, but they also should learn to develop interactive multimedia, including simulations and games.</p>
<p><strong>Live coverage. </strong>Increasingly, journalists need to provide live, unedited coverage of events. Whether in a reporting course, a visual journalism course, a live-coverage course or all three, students should learn how to <a title="Liveblogging: Telling stories as they happen" href="http://stevebuttry.wordpress.com/2009/04/20/liveblogging-telling-stories-as-they-happen-2/" target="_blank">liveblog</a>, stream live video and aggregate real-time public content from social media.</p>
<p><strong>Managing digital content. </strong>Digital journalism and strategic communication both will require a range of digital skills that are rapidly developing. The specific content of such a course and the balance of topics covered would change by semester, but someone should stay abreast of issues such as search-engine optimization, analytics, tagging, curation, aggregation, archiving, content-management systems and semantic technology. Some of these topics need to be introduced in lower-level courses, but they easily could be an upper-level course.</p>
<p><strong>Design. </strong>Print design is fading in importance as newspapers cut newsholes and resources and require more regional design and use of templates. But web design and mobile design are areas of growing importance. Design courses should be adjusted accordingly.</p>
<p><strong>Blogging. </strong>I don’t see a need for a course specifically in blogging (though I wouldn’t object either). <a title="Bloggers share lots of advice" href="http://stevebuttry.wordpress.com/2009/06/18/bloggers-share-lots-of-advice/" target="_blank">Blogging</a> should be part of nearly every writing course. In many courses, students should be required to keep a course blog. I evaluated portfolio blogs for seniors at the University of Nebraska, and I would encourage any journalism school to require students to maintain portfolio blogs.</p>
<p><strong><a title="Why we link" href="http://publishing2.com/2009/06/11/why-we-link-a-brief-rundown-of-the-reasons-your-news-organization-needs-to-tie-the-web-together/" target="_blank">Link journalism</a></strong><strong>. </strong>Students need to learn how to use links, which are the footnotes of the digital world. This certainly should be part of reporting and editing courses.</p>
<p><strong>Law and Ethics. </strong>As I address in my Upholding and Updating Ethical Standards seminars, ethics education needs to address a <a title="Resources for journalism ethics" href="http://stevebuttry.wordpress.com/2009/09/18/resources-for-journalism-ethics/" target="_blank">wide range of digital issues</a>. Of course, digital journalism presents many legal issues as well. In fact, many (I suspect most) editors and journalism professors continue to follow <a title="Why news organizations can police comments and not get sued" href="http://www.niemanlab.org/2009/01/david-ardia-why-news-orgs-can-police-comments-and-not-get-sued/" target="_blank">outdated advice</a> on court interpretations of Section 230 of the Communications Decency Act.</p>
<p><strong>First Amendment</strong>. The <a title="American Press Institute" href="http://americanpressinstitute.org" target="_blank">American Press Institute</a>, where I worked for three years, collaborates with the <a title="First Amendment Center" href="http://www.firstamendmentcenter.org/" target="_blank">First Amendment Center</a> and the Freedom Forum to take our seminars to programs on the First Amendment. These programs gave me both a deep appreciation of our First Amendment freedoms and a keen realization that professional journalists don’t know enough about the history and current status of the First Amendment and the freedoms it guarantees. A First Amendment course could be a cross-disciplinary course with credit in journalism, religion and political science. With TCU’s international communication major, this course should include units on restrictions on our key freedoms in other nations.</p>
<p>TCU&#8217;s curriculum committee asked me whether I thought professionals would be interested in a certificate program in digital journalism for professionals needing to update their skills. While ability to pay might be impaired by staff reductions and fears about job security, I think interest in such programs would be high. I encourage journalism schools to offer such programs in person and/or online, and to either develop financial aid support for such courses or to cut down the university overhead in determining tuition, since professionals would not draw as heavily as younger students on university resources. Such a certificate program should allow considerable flexibility for professionals to fill the gaps in their own skills.</p>
<p>Many journalism schools will be hard-pressed to update their curricula as I&#8217;ve described (though some certainly are already doing some of these things). They will need to hire more faculty with digital skills, use adjunct faculty with digital skills and require faculty to update their own skills and knowledge.</p>
<p>I&#8217;m glad journalism schools are considering these issues and I hope they move decisively and swiftly to update.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Access all the Rails APIs]]></title>
<link>http://dharshivf.wordpress.com/2009/11/24/access-all-the-rails-apis/</link>
<pubDate>Tue, 24 Nov 2009 15:21:36 +0000</pubDate>
<dc:creator>dharshivf</dc:creator>
<guid>http://dharshivf.wordpress.com/2009/11/24/access-all-the-rails-apis/</guid>
<description><![CDATA[If you install Rails using RubyGems (which we recommend), simply start the gem documentation server ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>If you install Rails using RubyGems<br />
(which we recommend), simply start the gem documentation server (using the<br />
command gem server), and you can access all the Rails APIs by pointing your<br />
browser at http://localhost:8808.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[The Canonical Project]]></title>
<link>http://joemcglynn.wordpress.com/2009/11/24/the-canonical-project/</link>
<pubDate>Tue, 24 Nov 2009 08:11:36 +0000</pubDate>
<dc:creator>joemcglynn</dc:creator>
<guid>http://joemcglynn.wordpress.com/2009/11/24/the-canonical-project/</guid>
<description><![CDATA[I&#8217;ve been hard at work on a new rails app recently.  Anyone who has built a Rails app knows th]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve been hard at work on a new rails app recently.  Anyone who has built a Rails app knows the it&#8217;s less about coding than understanding how the framework works for you and following the path of least resistance.  If you&#8217;re writing a lot of Ruby code in your rails app to do what seems to be typical activities&#8230;well you may be approaching it wrong.</p>
<p>In Rails 2.3 some new features were added to simplify dealing with &#8220;nested forms&#8221;.  That is, a single form that manages a model and it relationship data (has_one, has_many, etc)  In the dark ages (last spring) it was necessary to add a faux accessor to accommodate this.  No longer.</p>
<p>If you surf the web you will find many examples, not all of the are current.  I just put an example on github that demonstrates a simple master-detail type of form.  In this case it&#8217;s an order that has_many line_items.  The app is purposefully bare-bones so that the essential aren&#8217;t buried.  Any real app would have more elegant page layout, data validations and a lot of other niceties.</p>
<p>This first example shows adding and removing detail records using AJAX.  There are two simple helper methods to facilitate this.</p>
<p>Check it out on github: <a href="http://github.com/canonical/OrderItemsExample">http://github.com/canonical/OrderItemsExample</a></p>
<p><a href="http://joemcglynn.wordpress.com/files/2009/11/lineitem1.jpg"><img class="aligncenter size-full wp-image-9" title="Screen shot of order item example" src="http://joemcglynn.wordpress.com/files/2009/11/lineitem1.jpg" alt="" width="450" height="168" /></a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Membuat Newstiker dengan Javascript Pada Rails]]></title>
<link>http://mursinah.wordpress.com/2009/11/23/membuat-newstiker-dengan-javascript-pada-rails/</link>
<pubDate>Mon, 23 Nov 2009 23:59:31 +0000</pubDate>
<dc:creator>Andry Sucipto</dc:creator>
<guid>http://mursinah.wordpress.com/2009/11/23/membuat-newstiker-dengan-javascript-pada-rails/</guid>
<description><![CDATA[Nestiker adalah suatu animasi sederhana yang biasanya digunakan oleh banya programer untuk memberika]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Nestiker adalah suatu animasi sederhana yang biasanya digunakan oleh banya programer untuk memberikan animasi berupa text yang berganti satu demi satu secara vertikal, biasanya digunakan di News Later Barita, adapun cara pembuatannya sangat mudah :</p>
<p>1. Mempersiapkan code Javascriptnya :</p>
<p>&#60;script type=&#8221;text/javascript&#8221;&#62;<br />
$(function() {<br />
$(&#8220;.newsticker-jcarousellite&#8221;).jCarouselLite({<br />
vertical: true,<br />
hoverPause:true,<br />
visible: 1,<br />
auto:500,<br />
speed:2500<br />
});<br />
});<br />
&#60;/script&#62;</p>
<p>Download Code Javascript berikutnya <a href="http://www.2shared.com/file/9393311/4b1b7a4b/jquery-latestpack.html?" target="_blank">jquery-latest.pack</a> dan <a href="http://www.2shared.com/file/9393440/4424a81d/jcarousellite_101c4.html?" target="_blank">jcarousellite_1.0.1c4</a> , masukkan semua javascript yang ada di antara head</p>
<p>2. Pada View kita masukkan code berikut :</p>
<p>&#60;div id=&#8221;newsticker-demo&#8221;&#62;<br />
&#60;div class=&#8221;newsticker-jcarousellite&#8221;&#62;<br />
&#60;ul&#62;<br />
&#60;% @articles.each do &#124;article&#124; %&#62;<br />
&#60;li&#62;<br />
&#60;div class=&#8221;info&#8221;&#62;<br />
&#60;span class=&#8221;title&#8221;&#62;&#60;a href=&#8221;/newsbriefs/1&#8243;&#62;&#60;%=h article.title %&#62;&#60;/a&#62;&#60;/span&#62;&#38;nbsp;&#38;nbsp;<br />
&#60;span class=&#8221;cat&#8221;&#62;&#60;a href=&#8221;/newsbriefs/1&#8243;&#62;&#60;%=h article.updated_at %&#62;&#60;/a&#62;&#60;/span&#62;&#60;br /&#62;<br />
&#60;%= snippet(article.content, 30) %&#62;<br />
&#60;/div&#62;<br />
&#60;/li&#62;<br />
&#60;% end %&#62;<br />
&#60;/ul&#62;<br />
&#60;div class=&#8221;clear&#8221;&#62;&#60;/div&#62;<br />
&#60;/div&#62;<br />
&#60;/div&#62;</p>
<p>&#160;</p>
<p>Selesai Selamat Mencoba !!!! Moga aja berhasil</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby On Rails running threads &amp; MySQL silently stops updating after 5 transactions]]></title>
<link>http://philostler.wordpress.com/2009/11/24/ruby-on-rails-running-threads-mysql-silently-stops-updating-after-5-transactions/</link>
<pubDate>Mon, 23 Nov 2009 23:58:02 +0000</pubDate>
<dc:creator>Phil Ostler</dc:creator>
<guid>http://philostler.wordpress.com/2009/11/24/ruby-on-rails-running-threads-mysql-silently-stops-updating-after-5-transactions/</guid>
<description><![CDATA[In my current Ruby n Rails project, the focus of work is to periodically update database entries fro]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In my current Ruby n Rails project, the focus of work is to periodically update database entries from XML feeds.</p>
<p>Naturally I&#8217;ve implemented a threading system using the rufus-scheduler gem for updating database entries every so many minutes. However I soon noticed that after running on the development enviroment with 1 minute intervals on updates, that the updating of the<strong> </strong><em>last updated time</em> column in the db suddenly stopped after about 5 iterations. No error, warnings or other signals (smoke or otherwise).</p>
<p>After a bit of head scratching I finally managed to mentally link the 5 iterations to the pool number setting in the database.yml file. Executing my database updates within the thread job was stopping Rails from cleaning up the unrequired connections (for whatever reason. I suspect this is because the thread is sent back to sleep before this can occur).</p>
<p>So the solution is to simply call the cleanup manually via&#8230;</p>
<p><code><strong>ActiveRecord::Base.connection_pool.clear_stale_cached_connections!</strong></code></p>
<p>&#8230; at the end of every job execution run. Problem sorted!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Conectando ruby + postgres usando DBI:Pg]]></title>
<link>http://diegonogueira.wordpress.com/2009/11/23/conectando-ruby-postgres-usando-dbi/</link>
<pubDate>Mon, 23 Nov 2009 23:55:25 +0000</pubDate>
<dc:creator>diegonogueira</dc:creator>
<guid>http://diegonogueira.wordpress.com/2009/11/23/conectando-ruby-postgres-usando-dbi/</guid>
<description><![CDATA[Olá pessoal!! Recentemente tive vários problemas ao tentar conectar o ruby com o banco postgres via ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Olá pessoal!!</p>
<p>Recentemente tive vários problemas ao tentar conectar o ruby com o banco postgres via dbi com a porta diferente da padrão 5432. Era erro atrás de erro, só conseguia conectar com a porta padrão 5432, mas queria utilizar outra, por exemplo, 5433. Até que consegui assim:</p>
<pre class="brush: ruby;">
require 'dbi'
con=[&#34;DBI:Pg:dbname=nome_do_banco;host=localhost;port=porta&#34;, &#34;nome_do_usuario&#34;, &#34;senha&#34;]
DBI.connect(*con)
</pre>
<p>É isso ai!<br />
Abraços!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Understanding Development from a Day In the Life]]></title>
<link>http://blog.openmountain.com/2009/11/23/development-day-in-the-life/</link>
<pubDate>Mon, 23 Nov 2009 20:57:29 +0000</pubDate>
<dc:creator>bbenedict</dc:creator>
<guid>http://blog.openmountain.com/2009/11/23/development-day-in-the-life/</guid>
<description><![CDATA[Monday morning is the time when our teams interact the most about projects and the coming week.  I]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Monday morning is the time when our teams interact the most about projects and the coming week.  I&#8217;ve decided to capture events typical of Monday to provide insight into our work developing products for clients.  I&#8217;ll do my best to include everything warts and all even if that means sharing something I would not normally share.  In support of full disclosure, I took sparse notes over a period of time and came back later to clean up the text and add commentary.  Here goes nothing!</p>
<p><strong>Our high-tech revolution has plunged us into a state of continuous partial attention.</strong></p>
<p><em>iBrain by Gary Small, M.D. and Gigi Vorgan</em></p>
<p>- A typical Monday starts by pulling my canoe out into the various communication streams.  Logging on to Skype is the watershed event.</p>
<p>- Skype is running.  Firefox is open with tabs for email, calendar, several Google docs, WordPress for this post and YouTube for a side project I am working on.</p>
<p>- I check in with my lead on Skype.  I have the same guy across a few of my projects.  This certainly streamlines the communication.  He&#8217;s in Costa Rica.  When I worked at Adobe, we used IM all the time as people worked on different floors and at different locations.</p>
<p>- I am acting as the product owner for one project and I clarify something about a feature we are implementing.</p>
<p>- On another project, our client provides detailed specifications and we review the documents to make sure we are in sync.  We are, which is good.</p>
<p><strong>The new promise of collaboration is that with peer production we will harness human skill, ingenuity, and intelligence more efficiently and effectively than anything we have witnessed previously.</strong></p>
<p><em>WIKINOMICS by Don Tapscott and Anthony D. Williams</em></p>
<p>- Our newest client jumps on Skype to validate the release, our testing and the schedule.  There is a lot to discuss so we move to a Skype call. He does a good job managing his business to create an active and valuable community.</p>
<p>- Another issue comes in about how a feature should work that requires some thought.  I ignore chats and emails for the next 30 minutes and open specifications in Google docs and mock-ups in Preview.  We clarify the issue.</p>
<p>- By late morning, the major communications have been completed.  Projects are moving forward and our teams seem to understand what needs to happen this week.  I am responsible for a couple of releases that are in full swing.</p>
<p><strong>No matter how clever the idea or great the implementation, an invention typically lives or dies depending on how well it can be integrated into a larger social or technological context.</strong></p>
<p><em>Juice by Evan I. Schwartz</em></p>
<p>- The marketing text for our Web site update is long overdue.  Some tasks on the docket this week are for corporate business.  But I decide to focus on that side project and YouTube.</p>
<p>- I started a project called ReachGivers.org to help charities and non-profits get their message out over the Internet.  ReachGivers.org uses Ruby on Rails and has Twitter integration.  I added a poor man&#8217;s blog a while back as well.  This week I want to add video support.  Side projects help me stay connected with technology.</p>
<p><strong>Economics is above all a science of measurement.  It comprises an extraordinarily powerful and flexible set of tools that can reliably assess a thicket of information to determine the effect of any one factor, or even the whole effect.</strong></p>
<p><em>Freakonomics by Steven D. Levitt and Stephen J. Dubner</em></p>
<p>- Off to Starbucks for a Mocha and a blueberry scone.  This happens so often that people know me by name there.  The Ethos water billboard reminds me I wanted to blog about that on ReachGivers.org after finishing the video work.</p>
<p>- My brain stumbles on some concepts for the marketing text and I jot down some ideas.</p>
<p>- I was working on a product a while back and was not that impressed with the end user documentation.  I sent a book proposal out to a technology book publisher, which turned into a series of titles, and I have been writing every since.  I love it, I really do.  I even enjoy working on marketing text and ads.</p>
<p><strong>Execution is not a one-time event.  Nor is it a process where you check off goals as if your sixth-grade teacher were looking over your shoulder. </strong></p>
<p><em>The Art of the Start by Guy Kawasaki.</em></p>
<p>- Shorty before noon we get a curve ball. Mid-cycle, our client needs to shift direction on a project to change the prioritization and the release date.  I&#8217;ll spend the next few days updating user stories and validating the new plan. Sometimes I feel like we&#8217;re actually better at hitting a curve ball.</p>
<p>- The Agile software process, which is intended for flexible development, actually advocates against this type of mid-cycle change.  Release cycles are purposely shorter so that a direction shift simply influences the next cycle.  For start-ups, next month can be years away.  We have to be more flexible.</p>
<p>- A site we monitor generates an alert right before I can escape for lunch.  I used to get a little rush on these mini-emergencies like working as an EMT. Now I am the ambulance driver who knows that most pick-ups are not at all like the show ER.  Still, up-time is important and so we resolve the issue as quickly as possible.</p>
<p>- It occurs to me that this post demonstrates why people Tweet.  Expressing myself effectively with 140 character didn&#8217;t work well for me.  I decide to try it again because I am enjoying creating this running dialog.</p>
<p>- We&#8217;re trying to send large Photoshop files with mock-ups.  Some days technology just seems to work against us.  We&#8217;re hitting proxy issues and time out issues.  Eventually we solve the problem and remind ourselves yet again we should standardize on an approach.  Problem is, email and Skype are so convenient and work well enough most of the time.  I guess this would be one of those warts.</p>
<p><strong>Agile software development methods should be able to survive in an atmosphere of constant change and still emerge with success.</strong></p>
<p><em>Agile Management for Software Engineering by David J. Anderson</em></p>
<p>- After 40 plus years of eating sandwiches, I still love a good sandwich.  The best sandwich in town is from the deli in Vallergus and the people at the cash register all know me by sight.</p>
<p>- I never get back to the post after lunch.  Clients and partners all eat at different times and issues were waiting for me when I got back.  That is definitely a typical Monday.</p>
<p>- I didn&#8217;t finish the marketing text either.  The text I came up with was not remarkable.  I made some small updates to our corporate site instead and also finished my changes on ReachGivers.org.  Perhaps I will think of something while winding down for the night.</p>
<p>- My iPhone sits by my bed.  With several releases in play, there is always a chance a developer is still working and will fire off a question.  Of course, I can&#8217;t just let the device sit there, now can I?  I pull my canoe back out into the stream and see what else I might have missed during dinner.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby on Rails Plugin: string_encryption]]></title>
<link>http://blogofheath.com/2009/11/23/ruby-on-rails-plugin-string_encryption/</link>
<pubDate>Mon, 23 Nov 2009 17:42:44 +0000</pubDate>
<dc:creator>heathanderson</dc:creator>
<guid>http://blogofheath.com/2009/11/23/ruby-on-rails-plugin-string_encryption/</guid>
<description><![CDATA[This is a very simple Ruby on Rails plugin that allows easy encryption of strings. For the sake of s]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This is a very simple Ruby on Rails plugin that allows easy encryption of strings. For the sake of simplicity there no customization. The only cipher used is ‘des-ede3-cbc’ (Triple DES using Cipher Block Chaining) . See my <a href="http://blogofheath.com/2009/09/25/ruby-string-encryption/">post </a> on encrypting/decrypting a string with Ruby for more information. First install the plugin:</p>
<pre class="brush: ruby;">
 script/plugin install git://github.com/handerson/string_encryption.git
</pre>
<p>Next we need to add an encryption key as the constant <code>ENV['STRING_ENCRYPTION_KEY']</code>. To do this just run</p>
<pre class="brush: ruby;">
 script/generate encryption_key
</pre>
<p>or you could set </p>
<pre class="brush: ruby;">
ENV['STRING_ENCRYPTION_KEY'] = &#34;somekey&#34;
</pre>
<p>where &#8220;somekey&#8221; is your key in environment.rb.</p>
<p>Now encryption/decryption is easy.</p>
<p>Encryption:</p>
<pre class="brush: ruby;">
&#34;Test&#34;.encrypt  #=&#62; &#34;NDFkZTc5NDEyNTg1MzdiZPzBrxZz5aoN%0A&#34;
</pre>
<p>Decryption:</p>
<pre class="brush: ruby;">
&#34;NDFkZTc5NDEyNTg1MzdiZPzBrxZz5aoN%0A&#34;.decrypt  #=&#62; &#34;Test&#34;
</pre>
<p>Code at Github:<br />
<a href="http://github.com/handerson/string_encryption">http://github.com/handerson/string_encryption</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Vive y deja vivir]]></title>
<link>http://mdm84.wordpress.com/2009/11/23/vive-y-deja-vivir/</link>
<pubDate>Mon, 23 Nov 2009 12:21:40 +0000</pubDate>
<dc:creator>mdm84</dc:creator>
<guid>http://mdm84.wordpress.com/2009/11/23/vive-y-deja-vivir/</guid>
<description><![CDATA[Esta entrada es una añdido a la entrada Respeta mi opción personal, y viene a que ayer en el metro e]]></description>
<content:encoded><![CDATA[Esta entrada es una añdido a la entrada Respeta mi opción personal, y viene a que ayer en el metro e]]></content:encoded>
</item>
<item>
<title><![CDATA[Installing RMagick on Ubuntu]]></title>
<link>http://rorworld.wordpress.com/2009/11/23/installing-rmagick-on-ubuntu/</link>
<pubDate>Mon, 23 Nov 2009 08:09:59 +0000</pubDate>
<dc:creator>jacobvthomas</dc:creator>
<guid>http://rorworld.wordpress.com/2009/11/23/installing-rmagick-on-ubuntu/</guid>
<description><![CDATA[I have followed the below steps to install RMagick on Ubuntu 9.04 - the Jaunty Jackalope As Root via]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I have followed the below steps to install RMagick on Ubuntu 9.04 - the Jaunty Jackalope</p>
<p>As Root via terminal</p>
<blockquote><p>1) <strong>apt-get install imagemagick</strong></p>
<p>2)<strong> gem install rmagick</strong></p></blockquote>
<p>It was a failure I was stucked with the below error.</p>
<blockquote>
<div id="_mcePaste"><em>gem install rmagick</em></div>
<div id="_mcePaste"><em>Building native extensions.  This could take a while&#8230;</em></div>
<div id="_mcePaste"><em>ERROR:  Error installing rmagick:</em></div>
<div id="_mcePaste"><em>ERROR: Failed to build gem native extension.</em></div>
<div id="_mcePaste"><em>/usr/bin/ruby1.8 extconf.rb install rmagick</em></div>
<div id="_mcePaste"><em>checking for Ruby version &#62;= 1.8.5&#8230; yes</em></div>
<div id="_mcePaste"><em>checking for cc&#8230; yes</em></div>
<div id="_mcePaste"><strong><em>checking for Magick-config&#8230; no</em></strong></div>
<div id="_mcePaste"><em>Can&#8217;t install RMagick 2.12.2. Can&#8217;t find Magick-config in /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games</em></div>
<div id="_mcePaste"><em>*** extconf.rb failed ***</em></div>
<div id="_mcePaste"><em>Could not create Makefile due to some reason, probably lack of</em></div>
<div id="_mcePaste"><em>necessary libraries and/or headers.  Check the mkmf.log file for more</em></div>
<div id="_mcePaste"><em>details.  You may need configuration options.</em></div>
<div id="_mcePaste"><em>Provided configuration options:</em></div>
<div id="_mcePaste"><em>&#8211;with-opt-dir</em></div>
<div id="_mcePaste"><em>&#8211;without-opt-dir</em></div>
<div id="_mcePaste"><em>&#8211;with-opt-include</em></div>
<div id="_mcePaste"><em>&#8211;without-opt-include=${opt-dir}/include</em></div>
<div id="_mcePaste"><em>&#8211;with-opt-lib</em></div>
<div id="_mcePaste"><em>&#8211;without-opt-lib=${opt-dir}/lib</em></div>
<div id="_mcePaste"><em>&#8211;with-make-prog</em></div>
<div id="_mcePaste"><em>&#8211;without-make-prog</em></div>
<div id="_mcePaste"><em>&#8211;srcdir=.</em></div>
<div id="_mcePaste"><em>&#8211;curdir</em></div>
<div id="_mcePaste"><em>&#8211;ruby=/usr/bin/ruby1.8</em></div>
<div id="_mcePaste"><em>Gem files will remain installed in /var/lib/gems/1.8/gems/rmagick-2.12.2 for inspection.</em></div>
<div id="_mcePaste"><em>Results logged to /var/lib/gems/1.8/gems/rmagick-2.12.2/ext/RMagick/gem_make.out</em></div>
</blockquote>
<p>The Highlighted error was because of missing libraries and when i have googled the error I got a prompt solution to solve it by installing libmagick9-dev</p>
<p>but when i tried installing it also failed</p>
<blockquote><p><em>&#8220;apt-get install libmagick9-dev</em></p>
<p><em>Reading package lists&#8230; Done</em></p>
<p><em>Building dependency tree </em></p>
<p><em>Reading state information&#8230; Done</em></p>
<p><em>Package libmagick9-dev is a virtual package provided by:</em></p>
<p><em> libmagickwand-dev 7:6.4.5.4.dfsg1-1ubuntu3.1</em></p>
<p><em>You should explicitly select one to install.</em></p>
<p><em>E: Package libmagick9-dev has no installation candidate&#8221;</em></p></blockquote>
<p>It was solved by Installing &#8220;libmagickwand-dev&#8221;</p>
<div>
<blockquote>
<div><strong>3) apt-get install libmagickwand-dev</strong></div>
</blockquote>
</div>
<blockquote>
<div><strong>4) gem install rmagick</strong></div>
</blockquote>
<div>Thats it. rmagick is installed successfully. Hope this helps&#8230;</div>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[paperclip processors and after_post_process]]></title>
<link>http://blog.idearise.com/2009/11/23/paperclip-processors/</link>
<pubDate>Mon, 23 Nov 2009 07:20:50 +0000</pubDate>
<dc:creator>robertor</dc:creator>
<guid>http://blog.idearise.com/2009/11/23/paperclip-processors/</guid>
<description><![CDATA[A few things to note when trying to process an uploaded file with paperclip: The only way a post-pro]]></description>
<content:encoded><![CDATA[A few things to note when trying to process an uploaded file with paperclip: The only way a post-pro]]></content:encoded>
</item>
<item>
<title><![CDATA[Debugging made easy]]></title>
<link>http://itsonrail.wordpress.com/2009/11/23/debugging-made-easy/</link>
<pubDate>Mon, 23 Nov 2009 07:06:57 +0000</pubDate>
<dc:creator>zamorin</dc:creator>
<guid>http://itsonrail.wordpress.com/2009/11/23/debugging-made-easy/</guid>
<description><![CDATA[its always a nightmare to debug its more hard when the process is more depending upon the user input]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>its always a nightmare to debug<br />
its more hard when the process is more depending upon the user input<br />
test cases cant help many times but only manual testing</p>
<p>## in controller<br />
def show<br />
@debug_mode = false<br />
if params[:debug] and (params[:debug].downcase == &#8216;true&#8217; &#124;&#124; params[:debug] == &#8216;1&#8242;)<br />
@debug_mode = true<br />
end<br />
post = Post.find params[:id]<br />
end<br />
## in application_helper</p>
<p>def debug_an_object(obj)<br />
&#8220;&#8221;"<br />
This will print the content of the object passed<br />
Usage :<br />
// in controller<br />
location = Location.find :first<br />
// in view<br />
&#60;%= debug_an_object(location) %&#62;</p>
<p>This will returns a table which contains the attribues of the object passed</p>
<p>&#8220;&#8221;"</p>
<p>str_table_start = &#8220;&#60;table border=&#8217;1&#8242; cellpadding=&#8217;2&#8242; cellspacing=&#8217;2&#8242; style=&#8217;font-size:11px;&#8217;&#62;&#8221;<br />
str_table_end = &#8220;&#60;/table&#62;&#8221;</p>
<p>str_tr_start = &#8220;&#60;tr&#62;&#8221;<br />
str_tr_end = &#8220;&#60;/tr&#62;&#8221;</p>
<p>str_td_start = &#8220;&#60;td style=&#8217;background-color:skyblue;&#8217;&#62;&#8221;<br />
str_td_end = &#8220;&#60;/td&#62;&#8221;</p>
<p>str_html = str_table_start + &#8220;&#60;tr&#62;&#60;td style=&#8217;background-color:lightgreen;&#8217;&#62;Name&#60;/td&#62;&#60;td style=&#8217;background-color:lightgreen;&#8217;&#62;Value&#60;/td&#62;&#60;/tr&#62;&#8221;<br />
for key,val in obj.instance_values['attributes']<br />
str_td_key = str_td_start + key.to_s + str_td_end<br />
str_td_val = str_td_start + (val.nil? ? &#8220;nil&#8221;:val.to_s) + str_td_end<br />
str_tr = str_tr_start + str_td_key + str_td_val + str_tr_end<br />
str_html = str_html + str_tr<br />
end<br />
str_html = str_html + str_table_end<br />
return str_html<br />
end</p>
<p>## in view</p>
<p>&#60;%= debug_an_object(post)  %&#62;</p>
<p>this will display the object in a table</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[No eres el centro del universo - Video]]></title>
<link>http://mdm84.wordpress.com/2009/11/22/no-eres-el-centro-del-universo-video/</link>
<pubDate>Sun, 22 Nov 2009 10:07:36 +0000</pubDate>
<dc:creator>mdm84</dc:creator>
<guid>http://mdm84.wordpress.com/2009/11/22/no-eres-el-centro-del-universo-video/</guid>
<description><![CDATA[Veo en el blog libre y salvaje un video super chulo que nos demuestra una vez más que somos una nano]]></description>
<content:encoded><![CDATA[Veo en el blog libre y salvaje un video super chulo que nos demuestra una vez más que somos una nano]]></content:encoded>
</item>
<item>
<title><![CDATA[Rails Bancos e Boletos - Descontinuado]]></title>
<link>http://carlosantoniodasilva.wordpress.com/2009/11/22/rails-bancos-e-boletos-descontinuado/</link>
<pubDate>Sun, 22 Nov 2009 00:25:08 +0000</pubDate>
<dc:creator>Carlos</dc:creator>
<guid>http://carlosantoniodasilva.wordpress.com/2009/11/22/rails-bancos-e-boletos-descontinuado/</guid>
<description><![CDATA[Tenho recebido alguns comentários referentes ao andamento das rotinas de bancos e boletos que estáva]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Tenho recebido alguns comentários referentes ao andamento das rotinas de bancos e boletos que estávamos desenvolvendo a algum tempo atrás, então resolvi fazer um post rápido para informar a todos que o projeto está atualmente parado. O cliente com o qual estávamos trabalhando congelou o projeto e ainda não tem previsão de continuar com o desenvolvimento. Sendo assim, todo o código que desenvolvemos para a geração de boletos e guias também está congelado. Como é um código experimental, ou seja, ainda não foi efetivamente testado e homologado diretamente com nenhum banco, decidimos não divulgar nenhum código ainda.</p>
<p>Para quem está precisando gerar boletos em sua aplicação Rails, aconselho muito a utilização do projeto <a title="Gem para emissão de bloquetos de cobrança para bancos brasileiros" href="http://github.com/kivanio/brcobranca">brcobranca</a>, um plugin/gem criado pelo <a title="Kivanio Barbosa" href="http://www.kivanio.com.br/">Kivanio Barbosa</a> com a ajuda de alguns colaboradores (<a title="Shairon Toledo" href="http://www.hashcode.eti.br/" target="_blank">Shairon Toledo</a> e <a title="Claudio Pozzebon" href="http://www.kraudio.com.br/" target="_blank">Claudio Pozzebon</a>), e que atualmente funciona com vários bancos diferentes (Banco do Brasil, Itaú, HSBC, Banco Real, Bradesco e Unibanco até então), além de geração direta para os formatos png, tif, jpg ou mesmo pdf.</p>
<p>Você pode encontrar mais informações sobre o projeto no <a title="Gem para emissão de bloquetos de cobrança para bancos brasileiros" href="http://github.com/kivanio/brcobranca">github</a> e também na <a title="Boleto Rails" href="http://boletorails.com.br/">página de exemplo</a>, onde é possível gerar boletos de testes para todos os bancos e formatos disponíveis.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Ruby on Rails - How to avoid guessing irrelavant data- Universally Unique Identifier]]></title>
<link>http://dharshivf.wordpress.com/2009/11/21/ruby-on-rails-how-to-avoid-guessing-irrelavant-data-universally-unique-identifier/</link>
<pubDate>Sat, 21 Nov 2009 03:34:10 +0000</pubDate>
<dc:creator>dharshivf</dc:creator>
<guid>http://dharshivf.wordpress.com/2009/11/21/ruby-on-rails-how-to-avoid-guessing-irrelavant-data-universally-unique-identifier/</guid>
<description><![CDATA[As a rails programmer all of you have come accross url like following http://localhost:3000/albums/7]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>As a rails programmer all of you have come accross url like following</p>
<p>http://localhost:3000/albums/7</p>
<p>With the above url in browsers users can guest the next/other album details. For example users can guess that there might be ablums with id 8 or 9, which might not belongs to that particular user. Ofcourse we can always check the if the data is relevant to particular user by checking there session details.</p>
<p>Now there is another way of avoid such a  situation. We can use</p>
<p>UUIDHelper which generates a unique id which can use it as a secondary primary key for viewing data. I am sure that this kind of key wont be able to guess by users.</p>
<p>Step 1</p>
<p>To install UUIDTools gem</p>
<p>gem install uuidtools</p>
<p>Step 2</p>
<p>You need to have string field for above id ,  I am using a string field called s_id</p>
<p>Step 3</p>
<p>Create a file like lib/uuid_helper.rb and add the following content.</p>
<div>
<div>
<pre style="font-family:monospace;"><span style="color:#cc0066;font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#cc0066;font-weight:bold;">require</span> <span style="color:#996600;">'uuidtools'</span>

<span style="color:#9966cc;font-weight:bold;">module</span> UUIDHelper
  <span style="color:#9966cc;font-weight:bold;">def</span> before_create<span style="color:#006600;font-weight:bold;">(</span><span style="color:#006600;font-weight:bold;">)</span>
    <span style="color:#0000ff;font-weight:bold;">self</span>.s_id<span style="color:#9900cc;"> </span> = UUID.<span style="color:#9900cc;">timestamp_create</span><span style="color:#006600;font-weight:bold;">(</span><span style="color:#006600;font-weight:bold;">)</span>.<span style="color:#9900cc;">to_s</span>
  <span style="color:#9966cc;font-weight:bold;">end</span>
<span style="color:#9966cc;font-weight:bold;">end

</span></pre>
</div>
</div>
<p>Step 4</p>
<p>In your models you can use by including the helper methods</p>
<p>include UUIDHelper</p>
<p>Step 5</p>
<p>and you can override</p>
<p>def to_param<br />
s_id<br />
end</p>
<p>in this case the unique id generated is stored as s_id in database.</p>
<p>after that you can edit</p>
<p>Step 6</p>
<p>all the find methods to find_by_s_id(params[:id])</p>
<p>because after overriding to_param you are passing the s_id as id.</p>
<p>sample url after using UUID helper</p>
<p>http://localhost:3000/albums/</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[How to connect to multiple databases in a rails application]]></title>
<link>http://dharshivf.wordpress.com/2009/11/21/how-to-connect-to-multiple-databases-in-a-rails-application/</link>
<pubDate>Sat, 21 Nov 2009 03:23:08 +0000</pubDate>
<dc:creator>dharshivf</dc:creator>
<guid>http://dharshivf.wordpress.com/2009/11/21/how-to-connect-to-multiple-databases-in-a-rails-application/</guid>
<description><![CDATA[Ever wanted to connected to more than one database in a rails application ? Here is how to do it. in]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Ever wanted to connected to more than one database in a rails application ?</p>
<p>Here is how to do it.</p>
<p>in database.yml add your second database connection</p>
<p>example</p>
<p># database.yml</p>
<p>development:</p>
<p>adapter: mysql</p>
<p>encoding: utf8</p>
<p>username: root</p>
<p>password:</p>
<p>database: store_development</p>
<p><span style="color:#ff0000;">#new connection</span></p>
<p><span style="color:#0000ff;">other_development:</span></p>
<p><span style="color:#ff0000;"> adapter: mysql</span></p>
<p><span style="color:#ff0000;"> encoding: utf8</span></p>
<p><span style="color:#ff0000;"> username: limited_user</span></p>
<p><span style="color:#ff0000;"> password: welcome</span></p>
<p><span style="color:#ff0000;"> database: legacy_database</span></p>
<p><span style="color:#ff0000;"> </span><span style="color:#ff0000;"><span style="color:#000000;"> </span></span></p>
<p><span style="color:#ff0000;"><span style="color:#000000;">Now go to the model you want to use the new connection and add following</span></span></p>
<p><span style="color:#ff0000;"><span style="color:#000000;"> </span></span></p>
<p># app/models/guest.rb</p>
<pre>
<div>
<div>
<h3>class Guest &#60; ActiveRecord::Base
     #specify other connection you want to use instead of default connection<span style="color:#ff0000;">
     establish_connection</span> :<span style="color:#0000ff;">other_development</span>
end</h3>
</div>
</div>

<span style="color:#ff0000;"><span style="color:#000000;"> </span></span> <span style="color:#ff0000;"> </span>
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Task E: Check Out!]]></title>
<link>http://pedromtavares.wordpress.com/2009/11/20/task-e-check-out/</link>
<pubDate>Fri, 20 Nov 2009 14:37:00 +0000</pubDate>
<dc:creator>pedromtavares</dc:creator>
<guid>http://pedromtavares.wordpress.com/2009/11/20/task-e-check-out/</guid>
<description><![CDATA[After learning how to build a cart that can keep track of orders, it&#8217;s time to make those orde]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>After learning how to build a cart that can keep track of orders, it&#8217;s time to make those orders happen. When we were dealing with our cart, we didn&#8217;t worry about creating database tables for the core thing the cart holds: cart items, so the time has come to finally create a model for that and for the orders taken (so they too will be stored at the database), and we&#8217;ll do it by using script generators at the command prompt:</p>
<pre class="brush: plain;">
ruby script/generate model order

ruby script/generate model line_item
</pre>
<p>A bunch of files should have been generated, including the migrations for these tables (remember migrations from Task A? Well, you should), so let&#8217;s edit each of &#8216;em for our specific needs. Starting with the create_orders migration file:</p>
<pre class="brush: ruby;">
class CreateOrders &#60; ActiveRecord::Migration
  def self.up
    create_table <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rders do &#124;t&#124;
      t.string :name
      t.text :address
      t.string :email
      t.string :pay_type, :limit =&#62; 10

      t.timestamps
    end
  end

  def self.down
    drop_table <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rders
  end
end
</pre>
<p>We&#8217;re just telling it to create specific filds with the name and type of data we want. Timestamps are the created_at and updated_at fields that every Rails table has. Anyway, moving on to the create_line_items migration:</p>
<pre class="brush: ruby;">
class CreateLineItems &#60; ActiveRecord::Migration
  def self.up
    create_table :line_items do &#124;t&#124;
      t.integer :product_id, :null=&#62;false
      t.integer <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder_id, :null=&#62;false
      t.integer :quantity, :null=&#62;false
      t.decimal :total_price, :null=&#62;false, :precision=&#62;8, :scale=&#62;2

      t.timestamps
    end
  end

  def self.down
    drop_table :line_items
  end
end
</pre>
<p>To make the migrations actually go into the database:</p>
<pre class="brush: plain;">
rake db:migrate
</pre>
<p>There&#8217;s a certain relation between products, orders and line items, an order includes line items, a product also includes line items, and line items are included by both. Of course we know this, but Rails doesn&#8217;t, and there&#8217;s a nice and easy to tell it. First, edit the order model file:</p>
<pre class="brush: ruby;">
class Order&#60;ActiveRecord::Base
  has_many:line_items
end
</pre>
<p>Now the product model file:</p>
<pre class="brush: ruby;">
class Product&#60;ActiveRecord::Base
  has_many:line_items
  #all the stuff we added in other tasks
end
</pre>
<p>And finally, the line item model file:</p>
<pre class="brush: ruby;">
class LineItem&#60;ActiveRecord::Base
  belongs_to:order
  belongs_to:product
end
</pre>
<p>Now that our tables are all set, let&#8217;s create a link on the cart partial to a checkout action:</p>
<pre class="brush: ruby;">
&#60;div class=&#34;cart-title&#34;&#62;Your Cart&#60;/div&#62;
&#60;table&#62;
  &#60;%= render(:partial =&#62; &#34;cart_item&#34; , :collection =&#62; cart.items) %&#62;
  &#60;tr class=&#34;total-line&#34;&#62;
  &#60;td colspan=&#34;2&#34;&#62;Total&#60;/td&#62;
  &#60;td class=&#34;total-cell&#34;&#62;&#60;%= number_to_currency(cart.total_price) %&#62;&#60;/td&#62;
  &#60;/tr&#62;
&#60;/table&#62;
&#60;%= button_to &#34;Checkout&#34;,    :action=&#62;:checkout     %&#62;
&#60;%= button_to &#34;Empty cart&#34; , :action =&#62; :empty_cart %&#62;
</pre>
<p>The cart is now linking to a checkout action, which we will now create (on the store controller):</p>
<pre class="brush: ruby;">
def checkout
  @cart = find_cart
  if @cart.items.empty?
    redirect_to_index(&#34;Your cart is empty&#34;)
  else
    @order = Order.new
  end
end
</pre>
<p>After finding a cart (on the session), the action will check if the cart is empty (maybe some smart guy is trying to make an order with an empty cart) and redirect case it is, case not, a new order is created. The logic for the checkout action is now all set, time to make its view file (checkout.html.erb):</p>
<pre class="brush: ruby;">
&#60;div class=&#34;depot-form&#34;&#62;
  &#60;%= error_messages_for 'order' %&#62;
  &#60;% form_for <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder, :url=&#62;{:action =&#62; :save_order} do &#124;form&#124; %&#62;
  &#60;fieldset&#62;
    &#60;legend&#62;Please enter your details&#60;/legend&#62;
    &#60;p&#62;
      &#60;%= label <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder, :name, &#34;Name:&#34; %&#62;
      &#60;%= form.text_field :name, :size=&#62;40 %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;%= label <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder, :address, &#34;Address:&#34; %&#62;
      &#60;%= form.text_area :address, :rows=&#62;3, :cols=&#62;40 %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;%= label <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder, :email, &#34;E-mail:&#34; %&#62;
      &#60;%= form.text_field :email, :size=&#62;40 %&#62;
    &#60;/p&#62;
    &#60;p&#62;
      &#60;%= label <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder, :pay_type, &#34;Pay with:&#34; %&#62;
      &#60;%= form.select :pay_type, Order::PAYMENT_TYPES,
                      :prompt=&#62;&#34;Select a payment method&#34; %&#62;
    &#60;/p&#62;
    &#60;%= submit_tag &#34;Place Order&#34;, :class=&#62;&#34;submit&#34; %&#62;
  &#60;/fieldset&#62;
  &#60;% end %&#62;
&#60;/div&#62;
</pre>
<p>The error_messages_for displays any validation error regarding the &#8216;order&#8217; form, which we created in the line right below. The form_for helper takes a name (&#8216;order&#8217;), a url to where the HTTP POST request will be sent to (in our case, a save_order action) and a block which will contain everything relating to the form, such as HTML tags and input fields. Notice the select method is using a constant which is in the Order class that we didn&#8217;t define yet, and that&#8217;s what we will be doing now along with adding some validation helpers:</p>
<pre class="brush: ruby;">
class Order &#60; ActiveRecord::Base

  PAYMENT_TYPES = [
    #Displayed        stored in DB
    [&#34;Check&#34;,         &#34;check&#34;],
    [&#34;Credit card&#34;,   &#34;cc&#34;],
    [&#34;Purchase order&#34;,&#34;po&#34;]
  ]

  validates_presence_of :name, :address, :email, :pay_type
  validates_inclusion_of :pay_type, :in =&#62; PAYMENT_TYPES.map {&#124;disp,value&#124; value}

  has_many :line_items
end
</pre>
<p>Try adding stuff to the cart and clicking the &#8216;Checkout&#8217; button, a nice page should show asking for your information. All good, but the data still isn&#8217;t going into the database because we did&#8217;nt set the save_order method (which the form is pointing to), which we will be doing now by going through a few steps.<br />
First we&#8217;ll be creating the save_order method on our store controller, which should capture an order, fill in an order model object with that order (which contains line items), validate the information case it&#8217;s wrong and finally redirect the user to the catalog page with a cheerful message. Getting down to the code:</p>
<pre class="brush: ruby;">
def save_order
  @cart = find_cart
  @order = Order.new(params[:order])
  @order.add_line_items_from_cart(@cart)
  if @order.save
    session[:cart] = nil
    redirect_to_index(&#34;Thank you for your order&#34;)
  else
    render :action =&#62; :checkout
  end
end
</pre>
<p>We&#8217;re telling the code to find a cart, instace a new order based on the object sent by the form, add all items from the cart to that order and save it to the database, clearing the session and redirecting the user case that goes smoothly, or render back the checkout page case validation fails and the database isn&#8217;t able to save the data. To make this work, let&#8217;s define the add_line_items_from_cart method on the order model file:</p>
<pre class="brush: ruby;">
def add_line_items_from_cart(cart)
  cart.items.each do &#124;item&#124;
    li=LineItem.from_cart_item(item)
    self.line_items&#60;&#60;li
  end
end
</pre>
<p>As you can see, it&#8217;s basically an iteration over the cart items that invokes a LineItem method and adds that result to the line_items array, which belongs to the order object itself. Now all we need to do is define that from_cart_item class method on the line item model file:</p>
<pre class="brush: ruby;">
class LineItem &#60; ActiveRecord::Base

  belongs_to <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder
  belongs_to :product

  def self.from_cart_item(cart_item)
    li = self.new
    li.product = cart_item.product
    li.quantity = cart_item.quantity
    li.total_price = cart_item.price
    li
  end
end
</pre>
<p>All this is doing is associating a cart_item (which came from the cart object iteration in the add_line_items_from_cart method) with a new instance of LineItem that will later on be saved into the database when the method @order.save is called. And how is it possible to save an order and save all the line items that correspond to that order without calling the save method on each LineItem? Simple, remember the association we did at the beggining where an Order has_many :line_items and a LineItem belongs_to <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder? We did that to tell Rails that a relation exists between them, so it would automatically associate everything into the database and save all the LineItems that corresponded to that specific Order. Try adding some items to the cart, checking out, filling in correct information and placing the order, you&#8217;ll see that everything is placed perfectly in the database and a nice message appears at the catalog page.</p>
<p>&#160;</p>
<p>Lastly we&#8217;ll be adding a small AJAX feature that will make the &#8220;Thank you for your order&#8221; message disappear when a user is starting a new order after placing and order before that. This can be done with a simple line of code to our add_to_cart RJS template:</p>
<pre class="brush: ruby;">
page.replace_html(&#34;cart&#34;,:partial =&#62; &#34;cart&#34;, <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> bject =&#62; @cart)

page[:cart].visual_effect :blind_down if @cart.total_items == 1

page[:current_item].visual_effect :highlight,
                                  :startcolor =&#62; &#34;#88ff88&#34;,
                                  :endcolor =&#62; &#34;#114411&#34;
page.select(&#34;div#notice&#34;).each {&#124;div&#124;div.hide}
</pre>
<p>The page will now browse through all the divs with the &#8216;notice&#8217; ID and hide them on any request made, so that the thanking message will disappear after any user interaction.</p>
<p>&#160;</p>
<p>Before we finish things off, I&#8217;m gonna add some things that weren&#8217;t specified in the book. If you, like me, noticed that there isn&#8217;t an orders controller (I thought it was going to be added later, but it didn&#8217;t), you should also, like me, feel the urge to add it. With no controller, we cannot view the orders that were made, which is bad because how would our depot admin know where to ship the products to? Anyway, let&#8217;s get started on that, first thing we&#8217;ll do is generate our controller with an index, show and destroy methods:</p>
<pre class="brush: plain;">
ruby script/generate controller orders index show
</pre>
<p>As you&#8217;ll see, this is a pretty basic controller that could be easily generated by scaffold, and there&#8217;s nothing different to explain about it, so here&#8217;s the whole code:</p>
<pre class="brush: ruby;">
class OrdersController &#60; ApplicationController

  def index
    @orders = Order.all
    respond_to do &#124;format&#124;
      format.html
      format.xml {render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @orders}
    end
  end

  def show
    @order = Order.find(params[:id])
    respond_to do &#124;format&#124;
      format.html
      format.xml {render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&#62; @order}
    end
  end

  def destroy
    @order = Order.find(params[:id])
    @order.destroy

    respond_to do &#124;format&#124;
      format.html { redirect_to(orders_url) }
      format.xml  { head <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> k }
    end
  end

end
</pre>
<p>We added the method destroy by hand so the generator wouldn&#8217;t create a view file for it. Moving on to the view files, let&#8217;s start with the index page:</p>
<pre class="brush: ruby;">
&#60;h1&#62;Listing orders&#60;/h1&#62;
&#60;table&#62;
  &#60;tr&#62;&#60;th&#62;Buyer Name&#60;/th&#62;&#60;/tr&#62;
  &#60;% for order in @orders %&#62;
  &#60;tr&#62;
    &#60;td&#62;&#60;%=  link_to order.name, order %&#62;&#60;/td&#62;
  &#60;/tr&#62;
  &#60;% end %&#62;
&#60;/table&#62;
&#60;br /&#62;
</pre>
<p>Basic iteration through all orders with a link to each of them. On with the show page:</p>
<pre class="brush: ruby;">
&#60;p&#62;
  &#60;b&#62;Buyer Name:&#60;/b&#62;
  &#60;%= h @order.name %&#62;
&#60;/p&#62;

&#60;p&#62;
  &#60;b&#62;Address:&#60;/b&#62;
  &#60;%= h @order.address %&#62;
&#60;/p&#62;

&#60;p&#62;
  &#60;b&#62;E-mail:&#60;/b&#62;
  &#60;%= h @order.email %&#62;
&#60;/p&#62;

&#60;p&#62;
  &#60;b&#62;Payment type:&#60;/b&#62;
  &#60;%= h @order.pay_type %&#62;
&#60;/p&#62;

&#60;p&#62;
  &#60;b&#62;Line Items:&#60;/b&#62;&#60;br/&#62;
  &#60;% for item in @order.line_items  %&#62;
  &#60;%= item.quantity %&#62; &#38;times; &#60;%= link_to(item.product.title, product_url(item.product))  %&#62; = &#60;%= number_to_currency item.total_price %&#62;&#60;br/&#62;
  &#60;% end %&#62;
&#60;/p&#62;

&#60;p&#62;
  &#60;b&#62;Total price:&#60;/b&#62;
  &#60;%= number_to_currency @order.total %&#62;
&#60;/p&#62;

&#60;%= link_to 'Back', orders_path %&#62;
&#60;%= link_to 'Destroy', @order ,:confirm =&#62; 'Are you sure?',:method =&#62; :delete %&#62;
</pre>
<p>As learned in this task, an order has many line items, so to show an order, we need to iterate through every line item it has, which we did here by adding the line item quantity, the a link to its product and the price of that line item.  Lastly there&#8217;s a call to a total method which isn&#8217;t defined in our order model, so let&#8217;s add that:</p>
<pre class="brush: ruby;">
def total
  self.line_items.sum(:total_price)
end
</pre>
<p>The sum method iterates through all the line items and sums their total_price, returning a total order price.</p>
<p>That&#8217;s pretty much it, we now have an application with a cool shopping cart that is now able to place orders.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Migrating an existing deployment to Heroku]]></title>
<link>http://gautamrege.wordpress.com/2009/11/20/migrating-an-existing-deployment-to-heroku/</link>
<pubDate>Fri, 20 Nov 2009 14:18:30 +0000</pubDate>
<dc:creator>gautamrege</dc:creator>
<guid>http://gautamrege.wordpress.com/2009/11/20/migrating-an-existing-deployment-to-heroku/</guid>
<description><![CDATA[It was fun &#8212; pure unadulterated fun!! Now, I started looking at heroku since our current deplo]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>It was fun &#8212; pure unadulterated fun!!</p>
<p>Now, I started looking at heroku since our current deployment on a linode was getting a little bulky. Our client has been complaining of &#8217;suddenly things slowing down&#8217; and &#8217;site not working&#8217;. The site is used at a hit rate of 36 Requests per minute and we need to keep our hosting costs down &#8212; so what is the solution???</p>
<p>Currently, its hosted on a linode (740MB) memory and and nginx + 3 thin cluster. There is monit which ensures that ANY thin server going above 140MB is restarted. BackgrounDrb is taking a lot of memory too ( an unavoidable 160MB) and we have ferret to make things more complicated !! <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Enter Heroku &#8211; first thing that got me hooked was a &#8216;git push heroku&#8217; DEPLOYS your application! Fantastic. I have been a capistrano freak till now and loved it &#8211; but its all gone now! (wonder if thats good or bad though).  LoL <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>So, to get started, you sign-up on heroku and follow instructions on your My Apps page:</p>
<pre>$ heroku create
$ git init &#38;&#38; git add . &#38;&#38; git commit -m"initial checkins"
$ git push heroku</pre>
<p>I used the Blossom account (5 MB space) and was pleasantly surprised to see it work &#8216;out of the box&#8217;. It created some wierd named sub-domain for me which I changed using</p>
<pre>$ heroku rename &#60;new-name&#62;</pre>
<p>Digging deeper, I wanted to deploy the application &#8216;as is&#8217; but that was not to be:</p>
<h3>Setup Woes</h3>
<p>Heroku uses PostGres and we had used MySQL &#8211; you need to ensure that there are no special data types being used. As goes Murphy&#8217;s law &#8211; we had used blob and had to change that the bytea (bytearray in PG). The interesting thing I found was that there is NO way to drop the database and re-create it. The answer lies in:</p>
<pre>$ heroku rake db:schema:load</pre>
<p>Production environment is assumed. I was not sure which environment I am in till I issued the command (after reading up) that I was in production mode:</p>
<pre>$ heroku config
RACK_ENV =&#62; production</pre>
<p>I was also curious to see how I get the logs and check the console and it really ROCKS:</p>
<pre>$ heroku logs
$ heroku console</pre>
<p>Alas I could not find a way to access the dbconsole (like what I do sometimes with script/dbconsole -p). Well, that is the way it is!</p>
<h3>Ferret Woes</h3>
<p><span style="font-weight:normal;font-size:13px;">Heroku does not use ferret &#8211; it uses solr and sunspot. I had to install these additional gems using the gem manifest i.e. the .gems file located at RAILS_ROOT.</span></p>
<pre>rupport
acts_as_ferret
prawn
$ git commit
$ git push heroku</pre>
<p><span style="font-weight:normal;font-size:13px;">Since acts_as_ferret is installed, it loads the Rails models and &#8216;expects&#8217; the database to be in place. So, I had to comment out ALL the references to acts_as_ferret to be able to run a </span></p>
<pre><span style="font-weight:normal;font-size:13px;">$ heroku rake db:migrate</span></pre>
<p><span style="font-size:small;">So far so good. Now, since ferret requires to index files and heroku mounts the deployment on a read-only filesystem, we need to tweak the configurations to ensure that the index is created in tmp/ (the are where we can write stuff). Add the following lines to the config/environments/production.rb</span></p>
<pre>require 'acts_as_ferret'
ActsAsFerret.index_dir = "#{RAILS_ROOT}/tmp/index"</pre>
<p>Now, default ferret production environment is to start a Drb server on 9010 port &#8212; and Heroku will not allow this! So, we have to comment out all the configuration in config/ferret_server.yml to ensure that this loads like it does in development. I hate this but no alternative for now. I do plan to migrate to the WebSolr that Heroku is offering but its at 20$ per month! Lets see how that works out.</p>
<p>This should at least get you started on ferret &#8211; phew!</p>
<h3>BackgrounDrb woes</h3>
<p>BackgrounDrb comes with its own baggage I must say. Heroku proposes the use of DelayedJob (yippee) and I have just this plan, so rather than even try to figure out a way to get backgrounDrb to work on Heroku, I simply commented out the config/backgroundrb.yml settings (to ensure it does not get initialized).</p>
<p>I also had to comment out all the MiddleMan references in the controller. The backgrounDrb workers are easily  modified so that they can work as DelayedJob objects <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . I have mentioned this in my earlier posts <a href="http://gautamrege.wordpress.com/2009/11/04/moving-from-backgroundrb-to-delayedjob/">Moving from BackgrounDrb to DelayedJob</a></p>
<p>Once this was done, I did not face any problems and after some quick code fixes, git commits and git push&#8217;es, I was able to get my heroku application up and running.</p>
<p>All in a days work! Thats really amazing. Now, the next step is to get WebSolr  and DelayedJob integrated and see if I can move onto a bigger storage setup &#8212; a couple of months will let me know if this move was right.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[RPCFN#3 Short-circuit]]></title>
<link>http://gautamrege.wordpress.com/2009/11/20/rpcfn3-short-circuit/</link>
<pubDate>Fri, 20 Nov 2009 13:33:56 +0000</pubDate>
<dc:creator>gautamrege</dc:creator>
<guid>http://gautamrege.wordpress.com/2009/11/20/rpcfn3-short-circuit/</guid>
<description><![CDATA[It was great to see so many solutions for the problem statement I had set. After an initial &#8217;s]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>It was great to see so many solutions for the problem statement I had set. After an initial &#8217;shock&#8217; from all electrical engineers, the problem was clearly understood as a variant of the &#8217;shortest path algorithm&#8217;. I hope I was able to derive a laugh from the cryptic clue &#8217;short-circuit&#8217;.</p>
<p>Speaking of &#8216;derive&#8217;, I did see most solutions going into a class implementation of  &#8217;class Graph&#8217; or &#8216;class Vector&#8217;. Though its pretty cool to see a complete packaged solution, I believe this was a slight overkill. This was NOT the basis of judging but I do feel that ruby has its essence in getting the job done in far lesser code. i.e. less LOC. So, I personally did not foresee 3-4 classes with inheritance in them.. I do totally agree its an excellent way to show-case one&#8217;s skills  ;)</p>
<p>Djikstra&#8217;s algorithm seems to be the popular hit for solving this problem &#8211; however, I do feel a recursive solution than an iterative one is more appropriate for this. Again this is just an opinion but to get a sense of the power of ruby programing, a recursive program probably paints a better picture. Its also very concise and readable.</p>
<p>A lot of effort was spent in &#8216;initializing&#8217; the data-structure. This was really nice to see &#8212; unlike me, who took a short-cut. The aim was to see the algorithm but I was really proud to see &#8216;complete&#8217; solutions. Test cases were written in most solutions and it was a pleasure to see them run.</p>
<p>It was interesting to see various forms of Infinity:</p>
<pre>Infinity = 1 &#60;&#60; 64
Infinity = 1 &#60;&#60; 32
Infinity = 1.0 / 0 # simple and ideal
Infinity = 1000000 # incorrect</pre>
<p>It was interesting to note that very few catered for multiple shortest paths, though the question was raised in the comments earlier. Not trying to be a hypocrite here, I should say that I too did not implement multiple shortest paths &#8211; LoL.</p>
<p>My solution to the problem is provided at <a href="http://github.com/gautamrege/short_circuit">http://github.com/gautamrege/short_circuit</a> and its merely a representation of my style of programing. Creating a gem was for kicks but lib/short_circuit.rb has the core code. It was great fun AND learning while doing this and I realized that I will always be a student.</p>
<p>Cheers!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Cómo Autenticar Usuarios con Authlogic]]></title>
<link>http://viarails.wordpress.com/2009/11/19/como-autenticar-usuarios-con-authlogic/</link>
<pubDate>Thu, 19 Nov 2009 22:40:47 +0000</pubDate>
<dc:creator>Gabriel Somoza</dc:creator>
<guid>http://viarails.wordpress.com/2009/11/19/como-autenticar-usuarios-con-authlogic/</guid>
<description><![CDATA[El plugin Authlogic (de BinaryLogic) es un excelente recurso a la hora de facilitar la autenticación]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p style="text-align:justify;">El plugin <a href="http://github.com/binarylogic/authlogic" target="_blank">Authlogic</a> (de <a href="http://www.binarylogic.com/" target="_blank">BinaryLogic</a>) es un excelente recurso a la hora de facilitar la autenticación de usuarios en nuestros sitios web. Se caracteriza por ser muy fácil de configurar, utilizar y extender (existen otros plugins que le agregan funcionalidad, como <a href="http://github.com/stonean/lockdown" target="_blank">Lockdown</a>). Por supuesto, tiene un muy buen nivel de seguridad y muchas funcionalidades extremadamente útiles que, de hacerlas a mano, nos tomaría mucho tiempo implementar.<!--more--></p>
<p style="text-align:justify;">Este tutorial está basado en el <a href="http://github.com/binarylogic/authlogic_example" target="_blank">sitio de ejemplo oficial</a> de Authlogic, en GitHub.</p>
<h3 style="text-align:justify;">1- Instalación</h3>
<p style="text-align:justify;">Authlogic se puede instalar como gem o como plugin.</p>
<p style="text-align:justify;">A) Para instalar como plugin (recomendado por ellos mismos):</p>
<pre class="brush: plain;">
$ ./script/plugin install git://github.com/binarylogic/authlogic.git
</pre>
<p style="text-align:justify;">B) Para instalar como gem, basta agregar lo siguiente a environment.rb</p>
<pre class="brush: ruby;">
# config/environment.rb
config.gem &#34;authlogic&#34;
</pre>
<p style="text-align:justify;">Luego, ejecutar en la consola (si usás linux quizás necesites correrlo con <em>sudo</em>):</p>
<pre class="brush: plain;">
rake gems:install
</pre>
<h3 style="text-align:justify;">2- Crear el modelo UserSession</h3>
<p style="text-align:justify;">El modelo UserSession es aquel que se va a encargar de administrar todo lo que tiene que ver con una sesión en nuestro sitio: su creación (login), su actualización, y su destrucción (logout). Como ellos mismos comentan en su sitio de ejemplo, de la misma forma que ActiveRecord se sitúa entre nosotros y la base de datos, el modelo UserSession se situá entre nosotros y las cookies del usuario.</p>
<p style="text-align:justify;">Asumiendo que lo que queremos autenticar es un modelo nombrado <em>User</em>, vamos a crear nuestro modelo UserSession. En la consola:</p>
<pre class="brush: plain;">
script/generate session user_session
</pre>
<p style="text-align:justify;">Esto va a crear un archivo similar al siguiente:</p>
<pre class="brush: ruby;">
#app/models/user_session.rb
class UserSession &#60; Authlogic::Session::Base
  # aquí va la configuración
end
</pre>
<p style="text-align:justify;">Es importante destacar que este modelo hereda de <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">Authlogic::Session::Base</span>, lo cual nos permitirá configurarlo muy fácilmente. Por ejemplo, es aquí donde podemos proteger a nuestros usuarios de ataques de fuerza bruta. Para más información, ver la <a href="http://rdoc.info/projects/binarylogic/authlogic" target="_blank">documentación</a> de los submódulos de <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">Authlogic::Session</span>.</p>
<h3 style="text-align:justify;">3- Crear el modelo User</h3>
<p style="text-align:justify;">El modelo <em>User</em> es el modelo que guarda la información de registro de los usuarios. Se pueden incluir todos los campos que sean necesarios para nuestra aplicación, pero existen algunos campos que Authlogic administra de forma automática, facilitando muchísimo nuestro trabajo. Pero primero, creemos el modelo: en la consola,</p>
<pre class="brush: plain;">
script/generate model user login:string crypted_password:string
</pre>
<p style="text-align:justify;">Authlogic utilizará este modelo para autenticar. El tutorial oficial (en inglés) incluye una lista que muestra cuáles son los campos administrados por Authlogic. Todos los campos son opcionales excepto el que se utiliza para que la sesión persista: <em>persistence_token</em>. Para este tutorial utilizaremos una combinación de nombre de usuario y contraseña para autenticar. Como fueron especificados como parámetros, ambos campos (<em>login</em> y <em>crypted_password</em>, respectivamente) fueron añadidos automáticamente por Rails a nuestro archivo de migración cuando corrimos el generador anterior. Por lo tanto, podemos directamente ejecutar <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">rake db:migrate</span> para crear la tabla <em>users</em> junto con dichos campos en nuestra base de datos.</p>
<h3 style="text-align:justify;">4- Configurar el modelo</h3>
<p style="text-align:justify;">Configurar el modelo es extremadamente simple:</p>
<pre class="brush: ruby;">
class User &#60; ActiveRecord::Base
  acts_as_authentic do &#124;c&#124;
    c.opcion = valor # ver documentación
  end # el bloque es opcional
end
</pre>
<p style="text-align:justify;">A partir de ahora el modelo intentará validar automáticamente los campos <em>nombre de usuario</em>, <em>email</em>, <em>contraseña</em>, etc. La configuración en bloque nos permite personalizar cómo queremos que se validen esos campos, definir nombres distintos para los campos o incluso cambiar el algoritmo de encriptación para la contraseña.</p>
<h3 style="text-align:justify;">5- Crear el Controlador para UserSessions</h3>
<p style="text-align:justify;">Es a través de este controlador que el usuario iniciará y cerrará su sesión. Es importante aclarar que este controlador <em>no debería </em>ser usado para registrar usuarios u otras acciones similares que tienen que ver con la administración de usuarios; lo utilizaremos simplemente para iniciar o cerrar sesión. En la consola:</p>
<pre class="brush: plain;">
script/generate controller user_sessions
</pre>
<p style="text-align:justify;"><a href="http://github.com/binarylogic/authlogic_example/blob/5819a13477797d758cb6871f475ed1c54bf8a3a7/app/controllers/user_sessions_controller.rb" target="_blank">Aquí</a> hay un ejemplo del contenido básico de un controlador de UserSessions. También existen ejemplos paras las <a href="http://github.com/binarylogic/authlogic_example/tree/5819a13477797d758cb6871f475ed1c54bf8a3a7/app/views/user_sessions" target="_blank">vistas</a> correspondientes. Sin cambiar lo básico, podemos agregar toda la funcionalidad que queramos, tanto a las vistas como al controlador.</p>
<p style="text-align:justify;">En cuanto a las rutas, hace falta conectar el modelo UserSession con el controlador. Para lograrlo:</p>
<pre class="brush: ruby;">
#config/routes.rb
map.resource :user_session
</pre>
<h3 style="text-align:justify;">6- Persistiendo Sesiones</h3>
<p style="text-align:justify;">Para persistir sesiones utilizaremos el ApplicationController. Agregaremos algunos métodos al controlador y a dos de ellos los convertiremos en métodos <em>helper</em>, para poder accederlos desde las vistas. Estos métodos fueron extraídos del sitio ejemplo, son simplemente ilustrativos y pueden ser personalizados según la necesidad.</p>
<pre class="brush: ruby;">
# app/controllers/application.rb
class ApplicationController &#60; ActionController::Base
  helper :all
  filter_parameter_logging :password, :password_confirmation
  helper_method :current_user_session, :current_user

  private
  def current_user_session
    return @current_user_session if defined?(@current_user_session)
    @current_user_session = UserSession.find
  end

  def current_user
  return @current_user if defined?(@current_user)
    @current_user = current_user_session &#38;&#38; current_user_session.user
  end

  def require_user
     unless current_user
       store_location
       flash[:notice] = &#34;You must be logged in to access this page&#34;
       redirect_to new_user_session_url
       return false
     end
   end

   def require_no_user
     if current_user
       store_location
       flash[:notice] = &#34;You must be logged out to access this page&#34;
       redirect_to account_url
       return false
     end
   end

   def store_location
     session[:return_to] = request.request_uri
   end

   def redirect_back_or_default(default)
     redirect_to(session[:return_to] &#124;&#124; default)
     session[:return_to] = nil
   end
end
</pre>
<p style="text-align:justify;">Ahora tendremos acceso al usuario y su sesión en toda nuestra aplicación, con sólo llamar a <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">current_user</span> y <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">current_user_session</span>, respectivamente.</p>
<h3 style="text-align:justify;">7- Restringiendo Acceso</h3>
<p style="text-align:justify;">Authlogic se encarga simplemente de la autenticación, pero nos permite restringir acceso en nuestros controladores de forma muy fácil. Lo podemos hacer a mano o utilizando algún otro plugin que agregue esta funcionalidad. <a href="http://github.com/stonean/lockdown" target="_blank">Lockdown</a> es un plugin muy bueno que permite restringir acceso según los roles que tenga un usuario, y se integra de forma excelente con Authlogic.</p>
<p style="text-align:justify;">Sin embargo, aquí incluiremos un ejemplo muy simple de cómo restringir acceso manualmente dentro de uno de nuestros controladores. En nuestro ApplicationControler:</p>
<pre class="brush: ruby;">
# app/controllers/application.rb
class ApplicationController &#60; ActionController::Base

  #... (código anterior)

  def require_user
     unless current_user
       store_location
       flash[:notice] = &#34;You must be logged in to access this page&#34;
       redirect_to new_user_session_url
       return false
     end
   end

   def require_no_user
     if current_user
       store_location
       flash[:notice] = &#34;You must be logged out to access this page&#34;
       redirect_to account_url
       return false
     end
   end

   def store_location
     session[:return_to] = request.request_uri
   end

   def redirect_back_or_default(default)
     redirect_to(session[:return_to] &#124;&#124; default)
     session[:return_to] = nil
   end
end
</pre>
<p style="text-align:justify;">Y luego utilizamos estos nuevo métodos en nuestros controladores. Por ejemplo, si queremos que una lista de productos pueda ser vista por cualquier persona, pero que sólo usuarios logueados puedan administrarla (crear productos, actualizarlos, borrarlos, etc.), hacemos lo siguiente en nuestro ProductsController (asumiendo que existe):</p>
<pre class="brush: ruby;">
# app/controllers/products_controller.rb
class ProductsController &#60; ActionController::Base
  before_filter :require_user, :except =&#62; [:index, :show]

  #GET /products/new
  def new
    #...
  end

  # ... (resto del código)
end
</pre>
<p style="text-align:justify;">De esta forma, si una visita intenta añadir un producto accediendo a <em>&#8220;sitio.com/products/new&#8221;</em>, será redirigida automáticamente al formulario de <em>login</em> para que se identifique con su usuario antes de poder continuar. Esta lógica se encuentra en el ApplicationController, dentro del método <span style="font-family:Consolas,'Bitstream Vera Sans Mono','Courier New',Courier,monospace!important;">require_user</span>.</p>
<h3 style="text-align:justify;">8- Registrando Usuarios</h3>
<p style="text-align:justify;">Registrar usuarios es muy simple con Authlogic. De hecho, funciona exactamente igual que si no lo usáramos, siempre y cuando utilicemos las acciones CRUD estándar. Esto es debido a que Authlogic se inyecta automáticamente en el modelo, y por lo tanto no nos tenemos que preocupar en absoluto de nada que tenga que ver con lógica que hay detrás de registrar un usuario. Es más, tampoco es necesario preocuparnos de encriptar la contraseña antes de almacenarla en la base de datos. Authlogic se encarga de <em>todo</em>. Y si lo que buscamos es un poco más avanzado, Authlogic es muy fácil de configurar y extender (ver la documentación).</p>
<h3 style="text-align:justify;">9- Próximos Pasos</h3>
<p style="text-align:justify;">La gente de BinaryLogic incluye una lista de próximos pasos que pueden o no ser implementados. Todos remiten a una sección en particular dentro de la <a href="http://rdoc.info/projects/binarylogic/authlogic" target="_blank">documentación</a> de Authlogic. Aquí la incluyo traducida:</p>
<ol style="text-align:justify;">
<li style="text-align:left;">Querés usar otro algoritmo de encriptación, como BCrypt? Ver Authlogic::ActsAsAuthentic::Password::Config</li>
<li style="text-align:left;">Migrando de autenticación REST? Ver Authlogic::ActsAsAuthentic::RestfulAuthentication::Config</li>
<li style="text-align:left;">Querés que las sesiones expiren automáticamente después de un período de inactividad? Ver Authlogic::Session::Timeout</li>
<li style="text-align:left;">Necesitás restringir tus sesiones a una cuenta o modelo en particular? Ver Authlogic::AuthenticatesMany</li>
<li style="text-align:left;">Necesitás muchos tipos diferentes de sesiones? Ver Authlogic::Session::Id</li>
<li style="text-align:left;">Querés permitir que los usuarios reestablezcan sus contraseñas o confirmen su subscripción? Utilize una clave de expiración automática. Ver Authlogic::ActsAsAuthentic::PerishableToken</li>
<li style="text-align:left;">Querés dar acceso privado a una API o  canal RSS? Utilice autenticación básica por HTTP o por parámetros. Ver Authlogic::Session::HttpAuth o Authlogic::Session::Params</li>
<li style="text-align:left;">Necesitás ayuda con tus pruebas? Consulta Authlogic::TestCase</li>
</ol>
<h3 style="text-align:justify;">Créditos</h3>
<p style="text-align:justify;">Este tutorial está estructuralmente basado en el <a href="http://github.com/binarylogic/authlogic_example" target="_blank">tutorial oficial</a> de Authlogic (en inglés). Mucho del código lo extraje de allí directamente, aunque me tomé libertades en cuanto a su presentación y en algunos casos le cambié en formas que me parecieron más convenientes.</p>
<p style="text-align:justify;">Si este tutorial fue de provecho, no dudes en comentar! Lo mismo si encontraste errores o quisieras dar alguna sugerencia.</p>
<p style="text-align:justify;">También podés <a href="http://viarails.wordpress.com/feed/" target="_blank">subscribirte al feed</a> para mantenerte al tanto de los artículos más frescos.</p>
</div>]]></content:encoded>
</item>

</channel>
</rss>
