flog 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ module Centerstone #:nodoc:
2
+ module AssociationExtensions
3
+ module DateRanged
4
+
5
+ def current
6
+ containing(Time.now)
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ module Centerstone #:nodoc:
2
+ module AssociationExtensions
3
+ module Ranged
4
+
5
+ %w{before after containing contained_by overlapping}.each do |comparison|
6
+ define_method comparison do |target|
7
+ self.select { |x| x.send((comparison + '?').to_sym, target) }
8
+ end
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,50 @@
1
+ module Centerstone #:nodoc:
2
+ module ReflectionExtensions
3
+ module Ranged
4
+
5
+ def self.included(base)
6
+ puts 'hello'
7
+ base.send(:include, InstanceMethods)
8
+
9
+ base.instance_eval do
10
+ alias_method_chain :initialize, :has_many_range_extension
11
+ end
12
+ end
13
+
14
+ module InstanceMethods
15
+ def initialize_with_has_many_range_extension(*args)
16
+ puts 'yo'
17
+ returning initialize_without_has_many_range_extension(*args) do
18
+ puts 'returning stuff'
19
+ if macro.to_s == 'has_many'
20
+ puts 'adding the extension'
21
+ add_has_many_range_extension
22
+ end
23
+ puts 'blah'
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def add_has_many_range_extension
30
+ puts 'extension adding, hey'
31
+ puts 'bbbbb'
32
+ puts "target class [#{klass}]"
33
+ if klass.acts_as_range?
34
+ puts 'target acts as range'
35
+ extension = Centerstone::AssociationExtensions::Ranged
36
+ opts = options
37
+
38
+ opts[:extend] ||= []
39
+ opts[:extend] = [opts[:extend]].flatten
40
+
41
+ opts[:extend].push(extension) unless opts[:extend].include?(extension)
42
+
43
+ @options = opts
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ class BotFilter
2
+ attr_reader :options
3
+
4
+ def initialize(options = {})
5
+ @options = options
6
+ end
7
+
8
+ @@kinds = []
9
+ @@filters_registered = false
10
+
11
+ class << self
12
+ def new(options = {})
13
+ locate_filters(options) unless @@filters_registered
14
+ obj = allocate
15
+ obj.send :initialize, options
16
+ obj
17
+ end
18
+
19
+ def kinds
20
+ @@kinds
21
+ end
22
+
23
+ def register(name)
24
+ @@kinds << name
25
+ end
26
+
27
+ def clear_kinds
28
+ @@kinds = []
29
+ @@filters_registered = false
30
+ end
31
+
32
+ def get(ident)
33
+ name = ident.to_s.gsub(/(?:^|_)([a-z])/) { $1.upcase }.to_sym
34
+ const_get(name)
35
+ end
36
+
37
+ def locate_filters(options)
38
+ if options and options[:active_filters]
39
+ options[:active_filters].each do |filter|
40
+ register_filter(filter)
41
+ end
42
+ end
43
+ @@filters_registered = true
44
+ end
45
+
46
+ def filter_path(name)
47
+ File.expand_path(File.dirname(__FILE__)+"/../lib/filters/#{name}.rb")
48
+ end
49
+
50
+ def register_filter(name)
51
+ path = filter_path(name)
52
+ raise ArgumentError, "Could not find source code for filter [#{name}] in [#{path}]" unless File.exists? path
53
+ load(path)
54
+ register(name)
55
+ end
56
+ end
57
+
58
+ def process(data)
59
+ result = data
60
+ self.class.kinds.each do |k|
61
+ if result
62
+ result = BotFilter.get(k).new(options).process(result)
63
+ else
64
+ result = nil
65
+ break
66
+ end
67
+ end
68
+ result
69
+ end
70
+ end
@@ -0,0 +1,79 @@
1
+ require 'bot_parser_format'
2
+
3
+ class BotParser
4
+ @formats = []
5
+
6
+ class << self
7
+ attr_reader :formats
8
+
9
+ def register_format(*args, &block)
10
+ formats << BotParserFormat.new(*args, &block)
11
+ end
12
+
13
+ def clear_formats
14
+ @formats = []
15
+ end
16
+ end
17
+
18
+ def formats() self.class.formats; end
19
+
20
+ register_format :image, /^\s*(?:(.*?)\s+)?(http:\S+\.(?:jpe?g|png|gif))(?:\s+(\S.*))?$/i,
21
+ %q['http://www.citizenx.cx/img/best_picture_ever.jpg'],
22
+ %q['http://www.citizenx.cx/img/best_picture_never.jpg this poster hangs over my bed'],
23
+ %q['Best. Picture. Ever. http://www.citizenx.cx/img/best_picture_ever.jpg'] do |md, _|
24
+ { :title => md[1], :source => md[2], :caption => md[3] }
25
+ end
26
+
27
+ register_format :video, %r{^\s*(?:(.*?)\s+)?(http://(?:www\.)?youtube\.com/\S+\?\S+)(?:\s+(.*))?$}i,
28
+ %q['http://www.youtube.com/watch?v=E2Fjilze0eI'],
29
+ %q['http://www.youtube.com/watch?v=E2Fjilze0eI the bunny gets it'],
30
+ %q['A waste of chocolate http://www.youtube.com/watch?v=E2Fjilze0eI'] do |md, _|
31
+ { :title => md[1], :embed => md[2], :caption => md[3] }
32
+ end
33
+
34
+ register_format :quote, /^\s*"([^"]+)"\s+--\s*(.*?)(?:\s+\((https?:.*)\))?$/i,
35
+ %q['"adios, turd nuggets" --J.P.'],
36
+ %q['"adios, turd nuggets" --J.P. (http://imdb.com/title/tt0456554/)'] do |md, _|
37
+ { :quote => md[1], :source => md[2], :url => md[3] }
38
+ end
39
+
40
+ register_format :link, %r{^\s*(?:(.*?)\s+)?(https?://\S+)\s*(?:\s+(\S.*))?$}i,
41
+ %q['http://news.yahoo.com/s/ap/20071203/ap_on_sc/dinosaur_mummy'],
42
+ %q['http://news.yahoo.com/s/ap/20071203/ap_on_sc/dinosaur_mummy shows just how fast a mummified dinosaur can be'],
43
+ %q['Fossilized Hadrosaur http://news.yahoo.com/s/ap/20071203/ap_on_sc/dinosaur_mummy'] do |md, _|
44
+ { :name => md[1], :url => md[2], :description => md[3] }
45
+ end
46
+
47
+ register_format :fact, %r{^\s*fact:\s+(.*)}i,
48
+ %q['FACT: Zed Shaw doesn't do pushups, he pushes the earth down'] do |md, _|
49
+ { :title => "FACT: #{md[1]}" }
50
+ end
51
+
52
+ register_format :true_or_false, %r{^\s*(?:(?:true\s+or\s+false)|(?:t\s+or\s+f))\s*[:\?]\s+(.*)}i,
53
+ %q['T or F: the human body has more than one sphincter'],
54
+ %q['true or false: the human body has more than one sphincter'],
55
+ %q['true or false? the human body has more than one sphincter'] do |md, _|
56
+ { :title => "True or False? #{md[1]}" }
57
+ end
58
+
59
+ register_format :definition, %r{^\s*defin(?:e|ition):?\s+(.*?)\s*(?:[:=]|as)\s*(.*)}i,
60
+ %q['Definition: tardulism: the ideology of the tard culture'],
61
+ %q['Definition: tardulism = the ideology of the tard culture'],
62
+ %q["define tardulism as the ideology of the tard culture"] do |md, _|
63
+ { :title => "DEFINITION: #{md[1]}: #{md[2]}" }
64
+ end
65
+
66
+ def parse(sender, channel, mesg)
67
+ return nil if mesg.empty?
68
+
69
+ common = { :poster => sender, :channel => channel }
70
+
71
+ result = nil
72
+ formats.detect { |f| result = f.process(mesg) }
73
+
74
+ return nil unless result
75
+
76
+ result = common.merge(result)
77
+ result
78
+ end
79
+ end
@@ -0,0 +1,23 @@
1
+ class BotParserFormat
2
+ attr_reader :name, :format, :block
3
+
4
+ def initialize(name, format, *description, &block)
5
+ raise ArgumentError, 'Block needed' if block.nil?
6
+
7
+ @name = name
8
+ @format = format
9
+ @block = block
10
+ @description = description
11
+ end
12
+
13
+ def description
14
+ @description.empty? ? nil : @description.join("\n")
15
+ end
16
+
17
+ def process(text)
18
+ md = format.match(text)
19
+ return nil unless md
20
+
21
+ block.call(md, text).merge(:type => name)
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ class BotSender
2
+ attr_reader :kind
3
+
4
+ @@kinds = { }
5
+
6
+ def self.kinds
7
+ @@kinds.keys.sort_by {|k| k.to_s }
8
+ end
9
+
10
+ def self.register(args = {})
11
+ args.each_pair {|k,v| @@kinds[k] = v }
12
+ end
13
+
14
+ def self.new(args = {})
15
+ raise ArgumentError unless self.kinds.include?(args[:destination])
16
+ obj = @@kinds[args[:destination]].allocate
17
+ obj.send :initialize, args
18
+ obj
19
+ end
20
+
21
+ def initialize(args = {})
22
+ validate(args)
23
+ @kind = args[:destination]
24
+ end
25
+
26
+ def deliver(message)
27
+ return nil unless message and message[:type]
28
+ meth = "do_#{message[:type]}".to_sym
29
+ raise ArgumentError, "unknown message type [#{message[:type]}]" unless self.respond_to?(meth)
30
+ begin
31
+ self.send(meth, message)
32
+ rescue Exception => e
33
+ return e.to_s
34
+ end
35
+ end
36
+
37
+ # validate arguments when creating a specific BotSender type instance
38
+ def validate(args = {})
39
+ end
40
+ end
41
+
42
+ require 'senders/tumblr'
43
+
44
+ class BotSender
45
+ @@kinds[:tumblr] = BotSender::Tumblr
46
+ end
File without changes
@@ -0,0 +1,191 @@
1
+ module ObjectDaddy
2
+
3
+ def self.included(klass)
4
+ klass.extend ClassMethods
5
+ if defined? ActiveRecord and klass < ActiveRecord::Base
6
+ klass.extend RailsClassMethods
7
+
8
+ class << klass
9
+ alias_method :validates_presence_of_without_object_daddy, :validates_presence_of
10
+ alias_method :validates_presence_of, :validates_presence_of_with_object_daddy
11
+ end
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ attr_accessor :exemplars_generated, :exemplar_path, :generators
17
+ attr_reader :presence_validated_attributes
18
+ protected :exemplars_generated=
19
+
20
+ # create a valid instance of this class, using any known generators
21
+ def spawn(args = {})
22
+ gather_exemplars
23
+ (generators || {}).each_pair do |handle, gen_data|
24
+ next if args[handle]
25
+ generator = gen_data[:generator]
26
+ if generator[:block]
27
+ if generator[:start]
28
+ generator[:prev] = args[handle] = generator[:start]
29
+ generator.delete(:start)
30
+ else
31
+ generator[:prev] = args[handle] = generator[:block].call(generator[:prev])
32
+ end
33
+ elsif generator[:method]
34
+ args[handle] = send(generator[:method])
35
+ elsif generator[:class]
36
+ args[handle] = generator[:class].next
37
+ end
38
+ end
39
+ if presence_validated_attributes and !presence_validated_attributes.empty?
40
+ req = {}
41
+ (presence_validated_attributes.keys - args.keys).each {|a| req[a.to_s] = true } # find attributes required by validates_presence_of not already set
42
+
43
+ belongs_to_associations = reflect_on_all_associations(:belongs_to).to_a
44
+ missing = belongs_to_associations.select { |a| req[a.name.to_s] or req[a.primary_key_name.to_s] }
45
+ if create_scope = scope(:create)
46
+ missing.reject! { |a| create_scope.include?(a.primary_key_name) }
47
+ end
48
+ missing.each {|a| args[a.name] = a.class_name.constantize.generate }
49
+ end
50
+ new(args)
51
+ end
52
+
53
+ # register a generator for an attribute of this class
54
+ # generator_for :foo do |prev| ... end
55
+ # generator_for :foo do ... end
56
+ # generator_for :foo, value
57
+ # generator_for :foo => value
58
+ # generator_for :foo, :class => GeneratorClass
59
+ # generator_for :foo, :method => :method_name
60
+ def generator_for(handle, args = {}, &block)
61
+ if handle.is_a?(Hash)
62
+ raise ArgumentError, "only specify one attr => value pair at a time" unless handle.keys.length == 1
63
+ gen_data = handle
64
+ handle = gen_data.keys.first
65
+ args = gen_data[handle]
66
+ end
67
+
68
+ raise ArgumentError, "an attribute name must be specified" unless handle = handle.to_sym
69
+
70
+ unless args.is_a?(Hash)
71
+ unless block
72
+ retval = args
73
+ block = lambda { retval } # lambda { args } results in returning the empty hash that args gets changed to
74
+ end
75
+ args = {} # args is assumed to be a hash for the rest of the method
76
+ end
77
+
78
+ if args[:method]
79
+ record_generator_for(handle, :method => args[:method].to_sym)
80
+ elsif args[:class]
81
+ raise ArgumentError, "generator class [#{args[:class].name}] does not have a :next method" unless args[:class].respond_to?(:next)
82
+ record_generator_for(handle, :class => args[:class])
83
+ elsif block
84
+ raise ArgumentError, "generator block must take an optional single argument" unless (-1..1).include?(block.arity) # NOTE: lambda {} has an arity of -1, while lambda {||} has an arity of 0
85
+ h = { :block => block }
86
+ h[:start] = args[:start] if args[:start]
87
+ record_generator_for(handle, h)
88
+ else
89
+ raise ArgumentError, "a block, :class generator, :method generator, or value must be specified to generator_for"
90
+ end
91
+ end
92
+
93
+ def gather_exemplars
94
+ return if exemplars_generated
95
+ if superclass.respond_to?(:gather_exemplars)
96
+ superclass.gather_exemplars
97
+ self.generators = (superclass.generators || {}).dup
98
+ end
99
+
100
+ path = File.join(exemplar_path, "#{underscore(name)}_exemplar.rb")
101
+ load(path) if File.exists?(path)
102
+ self.exemplars_generated = true
103
+ end
104
+
105
+ def presence_validated_attributes
106
+ @presence_validated_attributes ||= {}
107
+ attrs = @presence_validated_attributes
108
+ if superclass.respond_to?(:presence_validated_attributes)
109
+ attrs = superclass.presence_validated_attributes.merge(attrs)
110
+ end
111
+ attrs
112
+ end
113
+
114
+ protected
115
+
116
+ # we define an underscore helper ourselves since the ActiveSupport isn't available if we're not using Rails
117
+ def underscore(string)
118
+ string.gsub(/([a-z])([A-Z])/, '\1_\2').downcase
119
+ end
120
+
121
+ def record_generator_for(handle, generator)
122
+ self.generators ||= {}
123
+ raise ArgumentError, "a generator for attribute [:#{handle}] has already been specified" if (generators[handle] || {})[:source] == self
124
+ generators[handle] = { :generator => generator, :source => self }
125
+ end
126
+ end
127
+
128
+ module RailsClassMethods
129
+ def exemplar_path
130
+ File.join(RAILS_ROOT, 'test', 'exemplars')
131
+ end
132
+
133
+ def validates_presence_of_with_object_daddy(*attr_names)
134
+ @presence_validated_attributes ||= {}
135
+ new_attr = attr_names.dup
136
+ new_attr.pop if new_attr.last.is_a?(Hash)
137
+ new_attr.each {|a| @presence_validated_attributes[a] = true }
138
+ validates_presence_of_without_object_daddy(*attr_names)
139
+ end
140
+
141
+ def generate(args = {})
142
+ obj = spawn(args)
143
+ obj.save
144
+ obj
145
+ end
146
+
147
+ def generate!(args = {})
148
+ obj = spawn(args)
149
+ obj.save!
150
+ obj
151
+ end
152
+ end
153
+ end
154
+
155
+
156
+ # these additional routines are just to give us coverage for flog opcodes that we hadn't yet covered in an integration test
157
+ alias puts print
158
+ attr_writer :foo
159
+
160
+ foo = 2
161
+
162
+ case 'foo'
163
+ when :foo
164
+ true
165
+ else
166
+ false
167
+ end
168
+
169
+ class Foo
170
+ def initialize
171
+ super(:foo)
172
+ end
173
+ end
174
+
175
+ until true
176
+ true
177
+ end
178
+
179
+ while false
180
+ true
181
+ end
182
+
183
+ begin
184
+ true
185
+ rescue Exception
186
+ false
187
+ else
188
+ true
189
+ end
190
+
191
+ puts(/foo/)