Class: OKCupid::Search

Inherits:
Object
  • Object
show all
Defined in:
lib/lonely_coder/search.rb,
lib/lonely_coder/search/options/age.rb,
lib/lonely_coder/search/options/filter.rb,
lib/lonely_coder/search/options/radius.rb,
lib/lonely_coder/search/options/location.rb,
lib/lonely_coder/search/options/order_by.rb,
lib/lonely_coder/search/options/ethnicity.rb,
lib/lonely_coder/search/options/paginator.rb,
lib/lonely_coder/search/options/require_photo.rb

Overview

Reopen Search to accept order_by filters

Defined Under Namespace

Classes: FilterError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, browser = Mechanize.new) ⇒ Search

Returns a new instance of Search.



68
69
70
71
72
# File 'lib/lonely_coder/search.rb', line 68

def initialize(options, browser = Mechanize.new)
  @browser = browser
  options = defaults.merge(options)
  parse(options)
end

Instance Attribute Details

#filtersObject (readonly)

Returns the value of attribute filters.



59
60
61
# File 'lib/lonely_coder/search.rb', line 59

def filters
  @filters
end

Class Method Details

.location_id_for(query) ⇒ Integer

Returns The OKCupid location id for the query.

Parameters:

  • A (String)

    string query for a city and state pair, e.g. ‘Little Rock, Arkansas’

Returns:

  • (Integer)

    The OKCupid location id for the query



63
64
65
66
# File 'lib/lonely_coder/search.rb', line 63

def self.location_id_for(query)
  uri = URI("http://www.okcupid.com/locquery?func=query&query=#{URI.encode(query)}")
  JSON.parse(Net::HTTP.get(uri))['results'][0]['locid'].to_s
end

Instance Method Details

#add_age_option(value) ⇒ Object



9
10
11
# File 'lib/lonely_coder/search/options/age.rb', line 9

def add_age_option(value)
  @filters << AgeFilter.new('age', value)
end

#add_ethnicity_option(values) ⇒ Object



10
11
12
# File 'lib/lonely_coder/search/options/ethnicity.rb', line 10

def add_ethnicity_option(values)
  @filters << EthnicityFilter.new('ethnicity', values)
end

#add_gentation_option(value) ⇒ Object



66
67
68
# File 'lib/lonely_coder/search/options/filter.rb', line 66

def add_gentation_option(value)
  @filters << Filter.new('gentation', value)
end

#add_last_login_option(value) ⇒ Object



70
71
72
# File 'lib/lonely_coder/search/options/filter.rb', line 70

def (value)
  @filters << Filter.new('last_login', value)
end

#add_location_option(value) ⇒ Object



21
22
23
# File 'lib/lonely_coder/search/options/location.rb', line 21

def add_location_option(value)
  @parameters << LocationParameter.new(value)
end

#add_order_by_option(value) ⇒ Object



15
16
17
# File 'lib/lonely_coder/search/options/order_by.rb', line 15

def add_order_by_option(value)
  @parameters << OrderByParameter.new(value)
end

#add_pagination_option(value) ⇒ Object



29
30
31
# File 'lib/lonely_coder/search/options/paginator.rb', line 29

def add_pagination_option(value)
  @parameters << @pagination = Paginator.new(value)
end

#add_radius_option(value) ⇒ Object



14
15
16
# File 'lib/lonely_coder/search/options/radius.rb', line 14

def add_radius_option(value)
  @filters << RadiusFilter.new('radius', value)
end

#add_relationship_status_option(value) ⇒ Object



62
63
64
# File 'lib/lonely_coder/search/options/filter.rb', line 62

def add_relationship_status_option(value)
  @filters << Filter.new('relationship_status', value)
end

#add_require_photo_option(value) ⇒ Object



9
10
11
# File 'lib/lonely_coder/search/options/require_photo.rb', line 9

def add_require_photo_option(value)
  @filters << RequirePhotoFilter.new('require_photo', value)
end

#ajax_urlObject



195
196
197
# File 'lib/lonely_coder/search.rb', line 195

def ajax_url
  "#{url}&ajax_load=1"
end

#check_for_required_options(options) ⇒ Object

Raises:



100
101
102
# File 'lib/lonely_coder/search.rb', line 100

def check_for_required_options(options)
  raise(FilterError, 'gentation is a required option') unless options.has_key?(:gentation)
end

#combine_ages(options) ⇒ Object



104
105
106
107
# File 'lib/lonely_coder/search.rb', line 104

def combine_ages(options)
  age = [options.delete(:min_age), options.delete(:max_age)]
  options[:age] = age
end

#defaultsObject



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/lonely_coder/search.rb', line 110

def defaults
  {
    :pagination => {
      :page => 1,
      :per_page => 10
    },
    :min_age => 18,
    :max_age => 99,
    :order_by => 'Match %',
    :last_login => 'last month',
    :location => 'Near me',
    :radius => 25,
    :require_photo => true,
    :relationship_status => 'single'
  }
end

#filters_as_queryObject



203
204
205
# File 'lib/lonely_coder/search.rb', line 203

def filters_as_query
  filters.compact.to_enum(:each_with_index).map {|filter,index| filter.to_param(index+1)}.join('&')
end

#load_next_pagetrue, false

Loads the next page of possible results. Will return ‘true` if additional results were available or `false` if not

Returns:

  • (true, false)


174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/lonely_coder/search.rb', line 174

def load_next_page
  @browser.pluggable_parser.html = SearchPaginationParser
  
  @pagination.next
  previous_length = @results.size
  
  page = @browser.get(ajax_url)
  
  @results += page.search('.match_row').collect do |node|
    OKCupid::Profile.from_search_result(node)
  end
  
  @browser.pluggable_parser.html = Mechanize::Page
  
  previous_length != @results.size
end

#magic_params_not_truly_understoodObject

no idea what the following parameters do. They don’t appear to have an effect: sort_type=0 fromWhoOnline=0 update_prefs=1 using_saved_search=0 mygender=m

no idea what the following parameters do, but without them, the search behaves erratically &custom_search=0

OKCupid timestamps searches for pagination. The first search gets a timestamp of 1 (e.g. 1 second into the epoch) and future searches are stamped with some server cache value. If that server value isn’t submitted, the results for pagniation don’t quite match what you’d expect: you’ll get duplicates, or lower numbers than expected. &timekey=1



166
167
168
# File 'lib/lonely_coder/search.rb', line 166

def magic_params_not_truly_understood
  "timekey=#{@timekey}&custom_search=0"
end

#parameters_as_queryObject



199
200
201
# File 'lib/lonely_coder/search.rb', line 199

def parameters_as_query
  @parameters.collect {|param| param.to_param }.join('&')
end

#parse(options) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/lonely_coder/search.rb', line 74

def parse(options)
  check_for_required_options(options)
  
  # :age appears as two options when creating a search
  # but is combined into one for paramterizing.
  options[:age] = combine_ages(options)
  
  # filters appear in the query string as filterN=code,value
  # e.g. filter4=11,75
  @filters = []
  
  # parameters appear in the query string as named query parameters
  # e.g. loc_id=1234567
  @parameters = []
  
  
  options.each do |name,value|
    self.send("add_#{name}_option", value)
  end
  
  # OKC needs an initial time key of 1 to represent "waaaay in the past"
  # futures searches will use the OKC server value returned from the first
  # results set.
  @timekey = 1
end

#resultsObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/lonely_coder/search.rb', line 127

def results
  return @results if @results
  
  # the first results request has to receive a full HTML page.
  # subseqent calls can make json requests
  page = @browser.get(url)
  
  # Stores the OKCupid server timestamp. Without this, pagination returns
  # inconsistent results.
  @timekey = page.search('script')[0].text.match(/CurrentGMT = new Date\(([\d]+)\*[\d]+\)/).captures[0]
  
  # OKCupid may return previously found profiles if there aren't enough
  # to fill a query or pagination, so we stop that with a set.
  @results = Set.new
  @results += page.search('.match_row').collect do |node|
    OKCupid::Profile.from_search_result(node)
  end
        
  @results
end

#urlObject



191
192
193
# File 'lib/lonely_coder/search.rb', line 191

def url
  "/match?#{filters_as_query}&#{parameters_as_query}&#{magic_params_not_truly_understood}"
end