module Streamit module DSL extend ActiveSupport::Concern # stream :create, :actor => :watcher, # :receiver => :watched_item # # stream :update, :attributes => :image_url, # module ClassMethods def stream(action, options={}) options.assert_valid_keys(:stream_type, :actor, :subject, :receiver, :attributes) raise ArgumentError, ":create or :update required as first parameter" \ unless [:create, :update].any? {|sym| sym == action } table_name = self.model_name.downcase.pluralize attributes = options[:attributes] attr_name = if action == :update case attributes when Array, nil :default when Symbol attributes end end stream_type = attr_name.nil? ? "streamit.#{table_name}.#{action}" : "streamit.#{table_name}.#{action}.#{attr_name}" method_name = :"_#{stream_type.gsub('.', '_')}" define_method(method_name) do stream_options = [:actor, :receiver, :subject].inject({}) do |memo, sym| memo[sym] = options[sym] ? send(options[sym]) : (sym == :actor ? self : nil) memo end.merge(:stream_type => stream_type, :started_at => Time.now) attr_changed = if action == :update case attributes when nil changed? when Array attributes.any? { |attr| send(:"#{attr}_changed?") } when Symbol send(:"#{attributes}_changed?") end end Streamit.save_stream!(stream_options) if (action != :update || attr_changed) end send(:"after_#{action}", method_name) end end end # DSL end # Streamit