diff --git a/app/models/comment.rb b/app/models/comment.rb
index b4e42f9299a4fad7c7d62fa56337825fb6e132a8..a19b09cb9107c1c8995e069c18a6453fe02dee8c 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -84,4 +84,19 @@ class Comment < ActiveRecord::Base
   def parent= parent
     self.post = parent
   end
+
+  class Generator < Federated::Generator
+    def self.federated_class
+      Comment
+    end
+
+    def initialize(person, target, text)
+      @text = text
+      super(person, target)
+    end
+
+    def relayable_options
+      {:post => @target, :text => @text}
+    end
+  end
 end
diff --git a/app/models/federated_relayable.rb b/app/models/federated_relayable.rb
deleted file mode 100644
index 540ee096726e2bbd389e25f603fcb2234c2297ff..0000000000000000000000000000000000000000
--- a/app/models/federated_relayable.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-class FederatedRelayable < ActiveRecord::Base
-  self.abstract_class = true
-
-  #crazy ordering issues - DEATH TO ROXML
-  include ROXML
-
-  include Diaspora::Webhooks
-  include Diaspora::Guid
-
-  #seriously, don't try to move this shit around until you have killed ROXML
-  xml_attr :target_type
-  include Diaspora::Relayable
-
-  xml_attr :diaspora_handle
-
-  belongs_to :target, :polymorphic => true
-  belongs_to :author, :class_name => 'Person'
-  #end crazy ordering issues
-
-  validates_uniqueness_of :target_id, :scope => [:target_type, :author_id]
-  validates :parent, :presence => true #should be in relayable (pending on fixing Message)
-
-  def diaspora_handle
-    self.author.diaspora_handle
-  end
-
-  def diaspora_handle=(nh)
-    self.author = Webfinger.new(nh).fetch
-  end
-
-  def parent_class
-    self.target_type.constantize
-  end
-
-  def parent
-    self.target
-  end
-
-  def parent= parent
-    self.target = parent
-  end
-end
\ No newline at end of file
diff --git a/app/models/like.rb b/app/models/like.rb
index 07dc4e2ea0ebd588535b98fbf86c61c3369dddcb..af85c8d709723f5f7c124832bb3684a0349f337a 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -2,7 +2,17 @@
 #   licensed under the Affero General Public License version 3 or later.  See
 #   the COPYRIGHT file.
 
-class Like < FederatedRelayable
+class Like < Federated::Relayable
+  class Generator < Federated::Generator
+    def self.federated_class
+      Like
+    end
+
+    def relayable_options
+      {:target => @target, :positive => true}
+    end
+  end
+
   after_create do
     self.parent.update_likes_counter
   end
diff --git a/app/models/participation.rb b/app/models/participation.rb
index 45ef129a6c720851e784b0a408067ac9179db8ce..229d1afc97b7cc2b53a80a399786b1a965b5d699 100644
--- a/app/models/participation.rb
+++ b/app/models/participation.rb
@@ -1,3 +1,11 @@
-class Participation < FederatedRelayable
+class Participation < Federated::Relayable
+  class Generator < Federated::Generator
+    def self.federated_class
+     Participation
+    end
 
+    def relayable_options
+      {:target => @target}
+    end
+  end
 end
\ No newline at end of file
diff --git a/app/models/user.rb b/app/models/user.rb
index 6bafb452c70efd719e7aa65fede4887f40daec1d..ebbed7f7c4a6d8e45e061e56d7052ef8e2f4562b 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -285,52 +285,19 @@ class User < ActiveRecord::Base
   end
 
   def comment!(post, text, opts={})
-    comment = build_comment(opts.merge!(:post => post, :text => text))
-    if comment.save
-      dispatch_post(comment)
-      comment
-    else
-      false
-    end
+    Comment::Generator.new(self.person, post, text).create!(opts)
   end
 
   def participate!(target, opts={})
-    participation = build_participation(opts.merge!(:target => target))
-    if participation.save
-      dispatch_post(participation)
-      participation
-    else
-      false
-    end
+    Participation::Generator.new(self.person, target).create!(opts)
   end
 
   def like!(target, opts={})
-    like = build_like(opts.merge!(:target => target, :positive => true))
-    if like.save
-      dispatch_post(like)
-      like
-    else
-      false
-    end
-  end
-
-  def build_relayable(model, options = {})
-    r = model.new(options.merge(:author_id => self.person.id))
-    r.set_guid
-    r.initialize_signatures
-    r
-  end
-
-  def build_comment(options = {})
-    build_relayable(Comment, options)
-  end
-
-  def build_participation(options = {})
-    build_relayable(Participation, options)
+    Like::Generator.new(self.person, target).create!(opts)
   end
 
-  def build_like(options = {})
-    build_relayable(Like, options)
+  def build_comment(options={})
+    Comment::Generator.new(self.person, options.delete(:post), options.delete(:text)).build(options)
   end
 
   # Check whether the user has liked a post.
diff --git a/lib/federated/generator.rb b/lib/federated/generator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f9dd2d265743dba3e724cc35267196f86a140cca
--- /dev/null
+++ b/lib/federated/generator.rb
@@ -0,0 +1,32 @@
+module Federated
+  class Generator
+    def initialize(person, target)
+      @person = person
+      @target = target
+    end
+
+    def build(options={})
+      options.merge!(relayable_options)
+      relayable = self.class.federated_class.new(options.merge(:author_id => @person.id))
+      relayable.set_guid
+      relayable.initialize_signatures
+      relayable
+    end
+
+    def create!(options={})
+      relayable = build(options)
+      if relayable.save
+        Postzord::Dispatcher.defer_build_and_post(@person, relayable)
+        relayable
+      else
+        false
+      end
+    end
+
+    protected
+
+    def relayable_options
+      {}
+    end
+  end
+end
\ No newline at end of file
diff --git a/lib/federated/relayable.rb b/lib/federated/relayable.rb
new file mode 100644
index 0000000000000000000000000000000000000000..618c2482035570ab179f19199db7f7c6434261bd
--- /dev/null
+++ b/lib/federated/relayable.rb
@@ -0,0 +1,44 @@
+module Federated
+  class Relayable < ActiveRecord::Base
+    self.abstract_class = true
+
+    #crazy ordering issues - DEATH TO ROXML
+    include ROXML
+
+    include Diaspora::Webhooks
+    include Diaspora::Guid
+
+    #seriously, don't try to move this shit around until you have killed ROXML
+    xml_attr :target_type
+    include Diaspora::Relayable
+
+    xml_attr :diaspora_handle
+
+    belongs_to :target, :polymorphic => true
+    belongs_to :author, :class_name => 'Person'
+    #end crazy ordering issues
+
+    validates_uniqueness_of :target_id, :scope => [:target_type, :author_id]
+    validates :parent, :presence => true #should be in relayable (pending on fixing Message)
+
+    def diaspora_handle
+      self.author.diaspora_handle
+    end
+
+    def diaspora_handle=(nh)
+      self.author = Webfinger.new(nh).fetch
+    end
+
+    def parent_class
+      self.target_type.constantize
+    end
+
+    def parent
+      self.target
+    end
+
+    def parent= parent
+      self.target = parent
+    end
+  end
+end
\ No newline at end of file
diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb
index 7e8bedfc9ea2d4e99b475b3a463f86881d6bf603..e9461192c496c0743a25311bc457df033e63863d 100644
--- a/spec/models/like_spec.rb
+++ b/spec/models/like_spec.rb
@@ -90,7 +90,7 @@ describe Like do
       @object_on_remote_parent = @local_luke.like!(@remote_parent)
     end
 
-    let(:build_object) { alice.build_like(:target => @status, :positive => true) }
+    let(:build_object) { Like::Generator.new(alice.person, @status).build }
     it_should_behave_like 'it is relayable'
   end
 end
diff --git a/spec/models/participation_spec.rb b/spec/models/participation_spec.rb
index 7214c3e6962303d48bcc21e31edfc2979d254a9b..12a1da5a049e1236109a758ba988a37d66ffa771 100644
--- a/spec/models/participation_spec.rb
+++ b/spec/models/participation_spec.rb
@@ -16,7 +16,8 @@ describe Participation do
       @object_on_remote_parent = @local_luke.participate!(@remote_parent)
     end
 
-    let(:build_object) { alice.build_participation(:target => @status) }
+    let(:build_object) { Participation::Generator.new(alice.person, @status).build }
+
     it_should_behave_like 'it is relayable'
   end
 end
\ No newline at end of file