<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/views/blogs/new_post.html.erb</filename>
    </added>
    <added>
      <filename>app/views/blogs/post.html.erb</filename>
    </added>
    <added>
      <filename>app/views/blogs/start.html.erb</filename>
    </added>
    <added>
      <filename>datastore-indexes.xml</filename>
    </added>
    <added>
      <filename>deploy.sh</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,4 @@
-- Create a framework for interacting with DataStore
-- Create a small framework for interacting with UserService
+CSS on stuff
+Fix pooling for Rack
+Check times
 </diff>
      <filename>TODO</filename>
    </modified>
    <modified>
      <diff>@@ -1,28 +1,53 @@
 class BlogsController &lt; ApplicationController
   layout 'blog'
-  require_admin :new, :create, :remove
+  require_admin :new_post, :create_post, :create, :remove, :remove_post
+
+  def start
+    @posts = Post.all({}, :limit =&gt; 15, :iorder =&gt; :created_at)
+  end
   
   def index
     @blogs = Blog.all
   end
   
   def blog
-    @blog = Blog.get(params[:id].to_i)
+    @blog = Blog.get(params[:id])
+    @posts = @blog.posts
   end
 
+  def post
+    @post = Post.get(params[:post_id])
+    @blog = @post.blog
+  end
+  
   def remove
-    Blog.delete(params[:id].to_i)
+    Blog.delete(params[:id])
     redirect_to blogs_url
   end
   
   def create
     name = params[:name]
-
-    blog = Blog.new
-    blog.name = name
-    blog.owner = @person
-    blog.save!
+    blog = Blog.create :name =&gt; name, :owner =&gt; @person, :created_at =&gt; Time.now
 
     redirect_to blogs_url
   end
+  
+  def new_post
+    @blog = Blog.get(params[:id])
+  end
+  
+  def create_post
+    @blog = Blog.get(params[:id])
+    Post.create :title =&gt; params[:title], :content =&gt; params[:content], :blog =&gt; @blog, :created_at =&gt; Time.now
+
+    redirect_to blog_url(@blog)
+  end
+
+  def remove_post
+    post = Post.get(params[:id])
+    blog = post.blog
+    post.delete!
+
+    redirect_to blog_url(blog)
+  end
 end</diff>
      <filename>app/controllers/blogs_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,20 +2,10 @@ class Blog
   include Bumble
 
   ds :name, :owner_id, :created_at
+  belongs_to :owner, Person
+  #  has_many :posts, :Post, :iorder =&gt; :created_at
 
-  def owner
-    if self.owner_id
-      Person.get(self.owner_id)
-    else
-      nil
-    end
-  end
-
-  def owner=(person)
-    self.owner_id = person.key
-  end
-  
   def posts
-    []
+    Post.all({:blog_id =&gt; self.key}, :iorder =&gt; :created_at)
   end
 end</diff>
      <filename>app/models/blog.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,4 +2,5 @@ class Person
   include Bumble
 
   ds :given_name, :sur_name, :email
+  # has_many :blogs, Blog
 end</diff>
      <filename>app/models/person.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,10 +2,5 @@ class Post
   include Bumble
 
   ds :title, :content, :created_at, :blog_id
-
-  def blog=(b)
-  end
-
-  def blog
-  end
+  belongs_to :blog, Blog
 end</diff>
      <filename>app/models/post.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,12 @@
 &lt;h1&gt;&lt;%=@blog.name%&gt;&lt;/h1&gt;
 
-&lt;% @blog.posts.each do |p| %&gt;
-&lt;h3&gt;&lt;%=p.title%&gt;&lt;/h3&gt;
+&lt;% if @admin %&gt;
+  &lt;%=link_to &quot;New post&quot;, new_post_url(@blog) %&gt;&lt;br/&gt;
+&lt;% end %&gt;
+
+&lt;% @posts.each do |p| %&gt;
+&lt;hr/&gt;
+&lt;h3&gt;&lt;%=link_to p.title, post_url(@blog, p)%&gt;&lt;%= @admin ? &quot; - &lt;i&gt;#{link_to(&quot;Remove post&quot;, remove_post_url(p), {:method =&gt; :post})}&lt;/i&gt;&quot; : &quot;&quot;%&gt;&lt;/h3&gt;
 &lt;pre&gt;
 &lt;%=p.content%&gt;
 &lt;/pre&gt;</diff>
      <filename>app/views/blogs/blog.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 
 &lt;table cellpadding=&quot;0&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;width: 30em&quot;&gt;
   &lt;% @blogs.each do |b| %&gt;
-    &lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;%=link_to b.name, blog_url(b.key) %&gt;&lt;/td&gt;&lt;%= @admin ? &quot;&lt;td align=\&quot;right\&quot;&gt;#{link_to(&quot;Remove blog&quot;, remove_blog_url(b.key), {:method =&gt; :post})}&lt;/td&gt;&quot; : &quot;&quot;%&gt;&lt;/tr&gt;
+    &lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;%=link_to b.name, blog_url(b.key) %&gt;&lt;/td&gt;&lt;%= @admin ? &quot;&lt;td align=\&quot;right\&quot;&gt;#{link_to(&quot;Remove blog&quot;, remove_blog_url(b), {:method =&gt; :post})}&lt;/td&gt;&quot; : &quot;&quot;%&gt;&lt;/tr&gt;
   &lt;% end %&gt;
 &lt;/table&gt;
 </diff>
      <filename>app/views/blogs/index.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -11,6 +11,7 @@
           &lt;% else %&gt;
             &lt;%=link_to &quot;Log in!&quot;, BeeU.login(request)%&gt;
           &lt;% end -%&gt;
+          |         &lt;%= link_to &quot;Blogs&quot;, blogs_url %&gt;
         &lt;/td&gt;
       &lt;/tr&gt;
       &lt;tr&gt;</diff>
      <filename>app/views/layouts/blog.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -39,12 +39,15 @@ ActionController::Routing::Routes.draw do |map|
   # Note: These default routes make all actions in every controller accessible via GET requests. You should
   # consider removing the them or commenting them out if you're using named routes and resources.
 
-  map.root :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;index&quot;
+  map.root :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;start&quot;
   map.blogs 'blogs', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;index&quot;
   map.create_blog 'blogs/create', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;create&quot;
   map.remove_blog 'blogs/remove/:id', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;remove&quot;
+  map.new_post 'blog/:id/new', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;new_post&quot;
+  map.create_post 'blog/:id/create', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;create_post&quot;
   map.blog 'blog/:id', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;blog&quot;
-#   map.post 'blog/:blog_id/:post_id', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;post&quot;
+  map.post 'blog/:blog_id/:post_id', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;post&quot;
+  map.remove_post 'post/:id/remove', :controller =&gt; &quot;blogs&quot;, :action =&gt; &quot;remove_post&quot;
   
   map.connect ':controller/:action/:id'
   map.connect ':controller/:action/:id.:format'</diff>
      <filename>config/routes.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ Warbler::Config.new do |config|
   config.dirs = %w(app config lib log vendor tmp)
 
   # Additional files/directories to include, above those in config.dirs
-  config.includes = FileList[&quot;appengine-web.xml&quot;]
+  config.includes = FileList[&quot;appengine-web.xml&quot;, &quot;datastore-indexes.xml&quot;]
 
   # Additional files/directories to exclude
   # config.excludes = FileList[&quot;lib/tasks/*&quot;]</diff>
      <filename>config/warble.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,29 +5,38 @@ module Bumble
   module DS
     import com.google.appengine.api.datastore.DatastoreServiceFactory
     import com.google.appengine.api.datastore.Entity
+    import com.google.appengine.api.datastore.FetchOptions
     import com.google.appengine.api.datastore.KeyFactory
     import com.google.appengine.api.datastore.Key
     import com.google.appengine.api.datastore.EntityNotFoundException
     import com.google.appengine.api.datastore.Query
+    import com.google.appengine.api.datastore.Text
     Service = DatastoreServiceFactory.datastore_service
   end
 
   module InstanceMethods
-    def initialize(*args)
-      super
+    def initialize(attrs = {}, *args)
+      super(*args)
       @__entity = DS::Entity.new(self.class.name)
+      attrs.each do |k,v|
+        self.send &quot;#{k}=&quot;, v
+      end
     end
 
     def key
       __ds_key.get_id
     end
     
+    def to_param
+      self.key
+    end
+    
     def save!
       DS::Service.put(@__entity)
     end
     
     def delete!
-      DS::Service.delete(__ds_key)
+      self.class.delete(self.key)
     end
 
     def __ds_key
@@ -37,18 +46,45 @@ module Bumble
     def __ds_get(name)
       name = name.to_s
       if @__entity.has_property(name)
-        @__entity.get_property(name)
+        ret = @__entity.get_property(name)
+        if ret.is_a?(DS::Text)
+          ret.value
+        else
+          ret
+        end
       else
         nil
       end
     end
     
     def __ds_set(name, value)
-      @__entity.set_property(name.to_s, value)
+      if value.is_a?(String) &amp;&amp; value.length &gt; 499
+        @__entity.set_property(name.to_s, DS::Text.new(value))
+      else
+        @__entity.set_property(name.to_s, value)
+      end
     end
   end
 
   module ClassMethods
+    def belongs_to(attr, type)
+      self.ds &quot;#{attr}_id&quot;
+      type_name = (type.is_a?(Symbol) || type.is_a?(String)) ? type : type.name
+      self.class_eval &lt;&lt;DEF
+  def #{attr}
+    if self.#{attr}_id
+        #{type_name}.get(self.#{attr}_id)
+    else
+      nil
+    end
+  end
+
+  def #{attr}=(value)
+    self.#{attr}_id = value.key
+  end
+DEF
+    end
+    
     # defines zero or more data store attributes - will create attribute accessors for these
     def ds(*names)
       names.each do |name|
@@ -65,11 +101,11 @@ DEF
     end
 
     def get(key)
-      create_from_entity(DS::Service.get(DS::KeyFactory.create_key(self.name, key)))
+      create_from_entity(DS::Service.get(DS::KeyFactory.create_key(self.name, key.to_i)))
     end
     
     def delete(key)
-      DS::Service.delete([DS::KeyFactory.create_key(self.name, key)].to_java(DS::Key))
+      DS::Service.delete([DS::KeyFactory.create_key(self.name, key.to_i)].to_java(DS::Key))
     end
     
     # returns either an object matching the conditions, or nil
@@ -86,9 +122,50 @@ DEF
         result
       end
     end
+
+    def create(attrs = {})
+      val = new(attrs)
+      val.save!
+      val
+    end
     
-    def all(conditions = {})
-      DS::Service.prepare(DS::Query.new(self.name)).as_iterable.map do |ent|
+    def all(conditions = {}, options = {})
+      q = DS::Query.new(self.name)
+      conditions.each do |k, v|
+        q = q.add_filter(k.to_s, DS::Query::FilterOperator::EQUAL, v)
+      end
+      
+      fo = nil
+      
+      if options[:limit]
+        fo = DS::FetchOptions::Builder.with_limit(options[:limit])
+      end
+
+      if options[:offset]
+        if fo
+          fo = fo.offset(options[:offset])
+        else
+          fo = DS::FetchOptions::Builder.with_limit(options[:offset])
+        end
+      end
+      
+      if options[:order]
+        q = q.add_sort(options[:order].to_s)
+      end
+
+      if options[:iorder]
+        q = q.add_sort(options[:iorder].to_s, DS::Query::SortDirection::DESCENDING)
+      end
+
+      $servlet_context.log &quot;doing search: #{q.to_s}&quot;
+      
+      iter = if fo
+               DS::Service.prepare(q).as_iterable(fo)
+             else
+               DS::Service.prepare(q).as_iterable
+             end
+      
+      iter.map do |ent|
         create_from_entity(ent)
       end
     end</diff>
      <filename>lib/bumble/bumble.rb</filename>
    </modified>
    <modified>
      <diff>@@ -42,14 +42,14 @@ YAKTest.tests do
       t3.save!
       k1, k2, k3 = t1.key, t2.key, t3.key
       
-      eq TestBumbleTwo.all.map { |tt| tt.key }, [k1,k2,k3]
+      eq TestBumbleTwo.all.map { |tt| tt.key }.sort, [k1,k2,k3].sort
     ensure 
       begin 
         TestBumbleTwo.all.each do |ee|
           ee.delete!
         end
       rescue Exception =&gt; e
-        $servlet_context.log(e)
+        $servlet_context.log(e.inspect)
       end
     end
   end</diff>
      <filename>lib/bumble/simple_tests.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>public/index.html</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>c80d5e753c5a3d18fe83c4bf750188c40ac374f6</id>
    </parent>
  </parents>
  <author>
    <name>Ola Bini</name>
    <email>ola.bini@gmail.com</email>
  </author>
  <url>http://github.com/olabini/yarbl/commit/6094923b3d1aa7b26f322853e2f87316555ba529</url>
  <id>6094923b3d1aa7b26f322853e2f87316555ba529</id>
  <committed-date>2009-04-03T15:59:27-07:00</committed-date>
  <authored-date>2009-04-03T15:59:27-07:00</authored-date>
  <message>Add the rest of the functionality, and some cleanup</message>
  <tree>7a8f52a37b6e0afe7937b8da029123d7bbc2f8e3</tree>
  <committer>
    <name>Ola Bini</name>
    <email>ola.bini@gmail.com</email>
  </committer>
</commit>
