Skip to content
Newer
Older
100644 117 lines (95 sloc) 3.72 KB
032399b @msepcot first commit
authored Feb 15, 2010
1 require 'crack'
2 require 'net/http'
3 require 'uri'
4
95637dd @msepcot AtD no longer requires you to register for an API key to use the serv…
authored Apr 20, 2010
5 def AfterTheDeadline(dictionary = nil, types = AfterTheDeadline::DEFAULT_IGNORE_TYPES)
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
6 AfterTheDeadline.set_custom_dictionary(dictionary)
7 AfterTheDeadline.set_ignore_types(types)
8 nil
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 17, 2010
9 end
10
032399b @msepcot first commit
authored Feb 15, 2010
11 class AfterTheDeadline
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
12 @@custom_dictionary = []
13 @@ignore_types = []
032399b @msepcot first commit
authored Feb 15, 2010
14
15 BASE_URI = 'http://service.afterthedeadline.com'
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
16 DEFAULT_IGNORE_TYPES = ['Bias Language', 'Cliches', 'Complex Expression', 'Diacritical Marks', 'Double Negatives', 'Hidden Verbs', 'Jargon Language', 'Passive voice', 'Phrases to Avoid', 'Redundant Expression']
032399b @msepcot first commit
authored Feb 15, 2010
17
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
18 class <<self
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
19 def set_custom_dictionary(dict)
20 if dict.kind_of?(Array)
21 @@custom_dictionary = dict
22 elsif dict.kind_of?(String)
23 File.open(dict) { |f| @@custom_dictionary = f.readlines.map &:strip }
24 end
25 end
26
27 def set_ignore_types(types)
28 @@ignore_types = types if types.kind_of?(Array)
29 end
30
95637dd @msepcot AtD no longer requires you to register for an API key to use the serv…
authored Apr 21, 2010
31 # Invoke the checkDocument service with provided text.
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
32 #
33 # Returns list of AfterTheDeadline::Error objects.
95637dd @msepcot AtD no longer requires you to register for an API key to use the serv…
authored Apr 21, 2010
34 def check(data)
35 results = Crack::XML.parse(perform('/checkDocument', :data => data))['results']
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
36 return [] if results.nil? # we have no errors in our data
37
38 raise "Server returned an error: #{results['message']}" if results['message']
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
39 errors = if results['error'].kind_of?(Array)
40 results['error'].map { |e| AfterTheDeadline::Error.new(e) }
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
41 else
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
42 [AfterTheDeadline::Error.new(results['error'])]
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
43 end
13c36e7 @msepcot add custom dictionary support, ignore specific error types, update ex…
authored Feb 22, 2010
44
45 # Remove any error types we don't care about
46 errors.reject! { |e| @@ignore_types.include?(e.description) }
47
48 # Remove spelling errors from our custom dictionary
49 errors.reject! { |e| e.type == 'spelling' && @@custom_dictionary.include?(e.string) }
50 return errors
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
51 end
52 alias :check_document :check
53
95637dd @msepcot AtD no longer requires you to register for an API key to use the serv…
authored Apr 21, 2010
54 # Invoke the stats service with provided text.
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
55 #
56 # Returns AfterTheDeadline::Metrics object.
95637dd @msepcot AtD no longer requires you to register for an API key to use the serv…
authored Apr 21, 2010
57 def metrics(data)
58 results = Crack::XML.parse(perform('/stats', :data => data))['scores']
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
59 return if results.nil? # we have no stats about our data
60 AfterTheDeadline::Metrics.new results['metric']
61 end
62 alias :stats :metrics
63
64 def perform(action, params)
65 response = Net::HTTP.post_form URI.parse(BASE_URI + action), params
66 raise "Unexpected response code from AtD service: #{response.code} #{response.message}" unless response.is_a? Net::HTTPSuccess
67 response.body
3525e4d @msepcot always return an array when checking for errors. empty array for no e…
authored Feb 17, 2010
68 end
032399b @msepcot first commit
authored Feb 15, 2010
69 end
70
50c47e3 @msepcot Use class methods instead of instance methods since we don't need to …
authored Feb 18, 2010
71 private_class_method :perform
032399b @msepcot first commit
authored Feb 15, 2010
72 end
73
74 class AfterTheDeadline::Error
75 attr_reader :string, :description, :precontext, :type, :suggestions, :url
76
77 def initialize(hash)
78 raise "#{self.class} must be initialized with a Hash" unless hash.kind_of?(Hash)
79 [:string, :description, :precontext, :type, :url].each do |attribute|
80 self.send("#{attribute}=", hash[attribute.to_s])
81 end
82 self.suggestions = hash['suggestions'].nil? ? [] : [*hash['suggestions']['option']]
83 end
84
85 def info(theme = nil)
86 return unless self.url
87 uri = URI.parse self.url
88 uri.query = (uri.query || '') + "&theme=#{theme}"
89 Net::HTTP.get(uri).strip
90 end
91
92 def to_s
93 "#{self.string} (#{self.description})"
94 end
95
96 private
97 attr_writer :string, :description, :precontext, :type, :suggestions, :url
98 end
99
100 class AfterTheDeadline::Metrics
101 attr_reader :spell, :grammer, :stats, :style
102
103 def initialize(array)
104 unless array.kind_of?(Array) && array.all? {|i| i.kind_of?(Hash) }
105 raise "#{self.class} must be initialized with an Array of Hashes"
106 end
107
108 self.spell, self.grammer, self.stats, self.style = {}, {}, {}, {}
109 array.each do |metric|
110 self.send(metric['type'])[metric['key']] = metric['value']
111 end
112 end
113
114 private
115 attr_writer :spell, :grammer, :stats, :style
116 end
Something went wrong with that request. Please try again.