<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>daydreaming &#187; ruby</title>
	<atom:link href="http://n79.org/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://n79.org</link>
	<description></description>
	<lastBuildDate>Thu, 12 Aug 2010 02:33:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Fire Eagle Sample App &#8211; whereis</title>
		<link>http://n79.org/2008/03/07/fireeagle-sample-app-whereis/</link>
		<comments>http://n79.org/2008/03/07/fireeagle-sample-app-whereis/#comments</comments>
		<pubDate>Fri, 07 Mar 2008 17:36:04 +0000</pubDate>
		<dc:creator>nikhilb</dc:creator>
				<category><![CDATA[camping]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[fireeagle]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://n79.org/2008/03/07/fireeagle-sample-app-whereis/</guid>
		<description><![CDATA[Fire Eagle (not fireeagle) is a new location platform from some of my colleagues here at Yahoo! Brickhouse. I&#8217;ve put together a simple sample app called whereis which shows off the power of the platform. What is whereis? Each instance of whereis lets you share location within a trusted group of people. Whereis does not [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-bottom: 10px;margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fn79.org%2F2008%2F03%2F07%2Ffireeagle-sample-app-whereis%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fn79.org%2F2008%2F03%2F07%2Ffireeagle-sample-app-whereis%2F&amp;source=nikibobb&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><a href="http://fireeagle.com">Fire Eagle</a> (not fireeagle) is a new location platform from some of my colleagues here at <a href="http://yahoo.com">Yahoo!</a> Brickhouse. I&#8217;ve put together a simple sample app called whereis which shows off the power of the platform. </p>
<h3>What is whereis?</h3>
<p>Each instance of whereis lets you share location within a trusted group of people. Whereis <b>does not</b> update location in Fire Eagle, you should do this using other apps (eg. Fire Eagle automatic device updaters, or other sites).  This screenshot basically sums it up -</p>
<p><img src='http://n79.org/wp-content/uploads/2008/03/whereis.gif' alt='whereis screenshot' /></p>
<h3>What can I use it for?</h3>
<ul>
<li>Run it on your intranet to easily share location between your co-workers</li>
<li>Run it on the internet so friends and family can share location</li>
</ul>
<h3>Who is whereis intended for?</h3>
<p>Whereis is intended for developers who have familiarity with Ruby and access to a server.</p>
<h3>Why are you releasing it?</h3>
<p>It is a simple app (~200 lines of code) built on top of the <a href="http://code.whytheluckystiff.net/camping/">camping framework</a>. If you understand Ruby and the <a href="http://en.wikipedia.org/wiki/Model-view-controller">MVC</a> pattern, it will give you a good idea of how FE works and can be used. I think the code is pretty self explanatory, drop me a line if you have any suggestions.</p>
<p><span id="more-27"></span></p>
<h3>What else should I do with it?</h3>
<ul>
<li>run an instance for your group</li>
<li>use it to experiment with fireeagle</li>
<li>skin it with CSS to make it look good</li>
<li>build a service around it</li>
<li>add a subscriptions table with acls to have a twitter like mode</li>
<li>anything else</li>
</ul>
<h3>How do I use it?</h3>
<ul>
<li>download the <a href='http://n79.org/wp-content/uploads/2008/03/whereis.tgz' title='whereis.tgz'>files</a></li>
<li>make sure you and everyone you want to use whereis have fireeagle accounts</li>
<li>install camping (via gem)</li>
<li>install dependencies</li>
<li>get a fireeagle consumer token and secret from the FE website and set up the correct callback URL</li>
<li>insert the token and secret in getFEClient &#8211; whereis.rb</li>
<li>change the login password in createTheBasics &#8211; whereis.rb</li>
<li>&#8220;camping whereis.rb&#8221; on the command line</li>
</ul>
<h3>Caveats</h3>
<ul>
<li>Whereis uses sqlite as it&#8217;s database so it&#8217;s probably not suitable for large scale deployments.</li>
<li>I&#8217;m using a very early version of the fireeagle gem, before you write anything make sure to look at the newest version.</li>
<li>This code might be a bit slow in production if the fireeagle servers are heavily loaded. If you want to take initiative and fix the problem this is how you would do it (via <a href="http://mojodna.net/">Seth Fitzsimmons</a>) &#8211; instead of updating the locations on query, update them periodically using a cron job or some other method.
</ul>
<pre name="code" class="ruby">

#!ruby
#whereis - a simple fireeagle demo
#IMPORTANT: make sure to use the version of fireeagle.rb included in the tarball
#Nikhil Bobb (nikhilb at yahoo-inc.com)
#26th Feb 08

require 'camping/session'
require 'FireEagle'
require 'JSON'

Camping.goes :Whereis

module Whereis
  include Camping::Session
  table_style = &quot;border-width:1px; border-style:outset&quot;

  def getFEClient(access_token = &quot;&quot;, access_token_secret = &quot;&quot;)
    client = FireEagle::Client.new \
	  :consumer_key        =&gt; &quot;&quot;,
	  :consumer_secret     =&gt; &quot;&quot;,
	  :access_token        =&gt; access_token,
          :access_token_secret =&gt; access_token_secret
  end

  #gets a user's location from fireEagle and returns a nice
  #string
  def getFELocation(access_token, access_token_secret)
    client = getFEClient(access_token, access_token_secret)
    location_obj = client.user
    #query the JSON object to get the location
    #where best guess = true
    hierarchy = location_obj[&quot;user&quot;][&quot;location_hierarchy&quot;]
    current_loc = hierarchy.select {|l| l[&quot;best_guess&quot;]}.first
    [current_loc[&quot;name&quot;], current_loc[&quot;located_at&quot;]]
  end
end

module Whereis::Models

  class User &lt; Base;
    has_one :request_token
    serialize :access_token
  end

  class RequestToken &lt; Base;
    belongs_to :user
    serialize :bin
  end 

  class Login &lt; Base; end

  class CreateTheBasics &lt; V 1.0
    def self.up
      create_table :whereis_logins do |t|
        t.column :username, :string
        t.column :password, :string
      end
      create_table :whereis_users do |t|
        t.column :name, :string
        t.column :access_token, :text
      end
      create_table :whereis_request_tokens do |t|
        t.column :str, :string
        t.column :bin, :text
        t.column :user_id, :integer
      end
      Login.create :username =&gt; 'admin', :password =&gt; &quot;eagle123&quot;
    end
    def self.down
      drop_table :whereis_users
      drop_table :whereis_request_tokens
      drop_table :whereis_logins
    end
  end
end

module Whereis::Controllers
  class Style &lt; R '/styles.css'
    def get
      @headers[&quot;Content-Type&quot;] = &quot;text/css; charset=utf-8&quot;
      @body = %{
        table {
          border-width:1px;
          border-style: dotted;
        }
        td {
          border-width: 1px 1px 1px 1px;
          border-style: solid;
        }
      }
    end
  end
  class Auth &lt; R '/auth'
    def post
      @logged_in_user = Login.find :first, :conditions =&gt; ['username = ? AND password = ?', input.username, input.password]
      if @logged_in_user
        @login = 'login success !'
        @state.user_id = @logged_in_user.id
        redirect R(Index)
      else
        @login = 'wrong user name or password'
        render :id
      end

    end
    def get
      render :id
    end
  end

  class Index &lt; R '/'
    def get
      if @state.user_id.blank?
        redirect R(Auth)
        return
      end

      @users = []
      User.find(:all).each do |u|
        t = u.access_token
        if t
          location = getFELocation(t.token, t.secret)
          @users &lt;&lt; [u.name, location[0], location[1]]
        end
      end
      render :whereis
    end

    def post
      if @state.user_id.blank?
        redirect R(Auth)
        return
      end

      client = getFEClient
      request_token = client.get_access_token_part1
      rt = RequestToken.create :bin =&gt; request_token, :str =&gt; request_token.token
      u = User.create :name =&gt; input.user, :request_token =&gt; rt
      redirect &quot;#{FireEagle::AUTHORIZATION_URL}?oauth_token=#{request_token.token}&quot;
    end
  end

  class Callback &lt; R '/callback'
    def get

      if @state.user_id.blank?
        redirect R(Auth)
        return
      end

      client = getFEClient
      rt = RequestToken.find_by_str(input.oauth_token)
      at = client.get_access_token_part2(rt.bin)
      user = rt.user
      user.access_token = at
      user.save
      rt.destroy
      redirect &quot;/&quot;
    end
  end
end

module Whereis::Views
  def layout
    html do
      head do
        title { &quot;Where is everyone?&quot; }
        link :rel =&gt; 'stylesheet', :type =&gt; 'text/css',
             :href =&gt; '/styles.css', :media =&gt; 'screen'
      end
    end
    body { self &lt;&lt; yield }
  end

  def id
    p @login
    form :action =&gt; R(Auth), :method =&gt; 'post' do
      label 'Username', :for =&gt; 'username'; br
      input :name =&gt; 'username', :type =&gt; 'text'; br

      label 'Password', :for =&gt; 'password'; br
      input :name =&gt; 'password', :type =&gt; 'text'; br

      input :type =&gt; 'submit', :name =&gt; 'login', :value =&gt; 'Login'
    end

  end

  def whereis
    form :method =&gt; &quot;post&quot; do
      input :type =&gt; &quot;text&quot;, :name =&gt; &quot;user&quot;
      input :type =&gt; &quot;submit&quot;, :value =&gt; &quot;add me&quot;
    end
    table do
      tr do
        td &quot;name&quot;
        td &quot;location&quot;
        td &quot;time&quot;
      end
      tr do
        @users.each do |u|
          u.each{|c| td c}
        end
      end
    end
  end
end

def Whereis.create
  Camping::Models::Session.create_schema
  Whereis::Models.create_schema :assume =&gt; (Whereis::Models::User.table_exists? ? 1.0 : 0.0)
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://n79.org/2008/03/07/fireeagle-sample-app-whereis/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Overrides in Camping</title>
		<link>http://n79.org/2008/03/05/overrides-in-camping/</link>
		<comments>http://n79.org/2008/03/05/overrides-in-camping/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 08:18:06 +0000</pubDate>
		<dc:creator>nikhilb</dc:creator>
				<category><![CDATA[camping]]></category>
		<category><![CDATA[dev]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://n79.org/2008/03/05/overrides-in-camping/</guid>
		<description><![CDATA[If you want to add a call to all the controllers in your Camping miroframework app you can use before or after overrides. These are similar to the before_filter in Rails. Remember to return the superclass or Camping will throw a &#8220;Read error: #&#60;NoMethodError: undefined method `status&#8217; for nil:NilClass&#62;&#8221; because it can&#8217;t call back into [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-bottom: 10px;margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fn79.org%2F2008%2F03%2F05%2Foverrides-in-camping%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fn79.org%2F2008%2F03%2F05%2Foverrides-in-camping%2F&amp;source=nikibobb&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p>If you want to add a call to all the controllers in your  <a href="http://code.whytheluckystiff.net/camping/" title="Camping Microframework" target="_blank">Camping miroframework</a> app you can use <a href="http://code.whytheluckystiff.net/camping/wiki/BeforeAndAfterOverrides" title="Before or After Override for camping" target="_blank">before or after overrides</a>. These are similar to the <em>before_filter</em> in Rails.</p>
<p>Remember to return the superclass or Camping will throw a <em>&#8220;Read error: #&lt;NoMethodError: undefined method `status&#8217; for nil:NilClass&gt;</em>&#8221; because it can&#8217;t call back into the returned controller. A <font color="#ff0000">modification</font> of the above linked wiki page example illustrates -</p>
<pre name="code" class="ruby">

Camping.goes :YourApp

module YourSession
  def service(*a)
    @session = YourApp::Session.new
    s = super(*a)
    @session.close
    #return s from above after completing
    s
  end
end

module YourApp
  include YourSession
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://n79.org/2008/03/05/overrides-in-camping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
