Explorar o código

Refactor Drop classes.

Not alone EventDrop but all subclasses now take a hash of "locals" which
could be referenced in interpolation.  This will make it easier for
Agent classes to add custom "locals" for use in interpolation.
Akinori MUSHA %!s(int64=10) %!d(string=hai) anos
pai
achega
a93bb2674e
Modificáronse 4 ficheiros con 65 adicións e 30 borrados
  1. 42 1
      app/concerns/liquid_droppable.rb
  2. 2 12
      app/models/agent.rb
  3. 12 17
      app/models/event.rb
  4. 9 0
      spec/models/event_spec.rb

+ 42 - 1
app/concerns/liquid_droppable.rb

@@ -1,9 +1,50 @@
 module LiquidDroppable
   extend ActiveSupport::Concern
 
+  # In subclasses of this base class, "locals" take precedence over
+  # methods.
   class Drop < Liquid::Drop
-    def initialize(object)
+    class << self
+      def inherited(subclass)
+        class << subclass
+          attr_reader :drop_methods
+
+          # Make all public methods private so that #before_method
+          # catches everything.
+          def drop_methods!
+            return if @drop_methods
+
+            @drop_methods = Set.new
+
+            (public_instance_methods - Drop.public_instance_methods).each { |name|
+              @drop_methods << name.to_s
+              private name
+            }
+          end
+        end
+      end
+    end
+
+    def initialize(object, locals = nil)
+      self.class.drop_methods!
+
       @object = object
+      @locals = locals || {}
+    end
+
+    def before_method(name)
+      if @locals.include?(name)
+        @locals[name]
+      elsif self.class.drop_methods.include?(name)
+        __send__(name)
+      end
+    end
+
+    def each
+      return to_enum(__method__) unless block_given?
+      self.class.drop_methods.each { |name|
+        yield [name, __send__(name)]
+      }
     end
   end
 

+ 2 - 12
app/models/agent.rb

@@ -391,7 +391,7 @@ class AgentDrop
     @object.short_type
   end
 
-  METHODS = [
+  [
     :name,
     :type,
     :options,
@@ -402,19 +402,9 @@ class AgentDrop
     :disabled,
     :keep_events_for,
     :propagate_immediately,
-  ]
-
-  METHODS.each { |attr|
+  ].each { |attr|
     define_method(attr) {
       @object.__send__(attr)
     } unless method_defined?(attr)
   }
-
-  def each(&block)
-    return to_enum(__method__) unless block
-
-    METHODS.each { |attr|
-      yield [attr, __sent__(attr)]
-    }
-  end
 end

+ 12 - 17
app/models/event.rb

@@ -44,26 +44,21 @@ class Event < ActiveRecord::Base
 end
 
 class EventDrop
-  def initialize(event, payload = event.payload)
-    super(event)
-    @payload = payload
-  end
-
-  def before_method(key)
-    if @payload.key?(key)
-      @payload[key]
-    else
-      case key
-      when 'agent'
-        @object.agent
-      when 'created_at'
-        @object.created_at
-      end
-    end
+  def initialize(object, locals = nil)
+    locals ||= object.payload
+    super
   end
 
   def each(&block)
     return to_enum(__method__) unless block
-    @payload.each(&block)
+    @locals.each(&block)
+  end
+
+  def agent
+    @object.agent
+  end
+
+  def created_at
+    @object.created_at
   end
 end

+ 9 - 0
spec/models/event_spec.rb

@@ -102,6 +102,15 @@ describe EventDrop do
     interpolate(t, @event).should eq('some title: http://some.site.example.org/')
   end
 
+  it 'should use created_at from the payload if it exists' do
+    created_at = @event.created_at - 86400
+    # Avoid timezone issue by using %s
+    @event.payload['created_at'] = created_at.strftime("%s")
+    @event.save!
+    t = '{{created_at | date:"%s" }}'
+    interpolate(t, @event).should eq(created_at.strftime("%s"))
+  end
+
   it 'should be iteratable' do
     # to_liquid returns self
     t = "{% for pair in to_liquid %}{{pair | join:':' }}\n{% endfor %}"