lib/nytimes_articles/article.rb in harrisj-nytimes-articles-0.1.1 vs lib/nytimes_articles/article.rb in harrisj-nytimes-articles-0.1.2

- old
+ new

@@ -1,21 +1,28 @@ require 'rubygems' module Nytimes module Articles + ## + # The Article class represents a single article returned from the New York Times Article Search API. Note that an article can have many attributes + # but these are not necessarily populated unless you explicitly request them in the reply from the server via the <tt>:fields</tt> parameter to + # search (or use <tt>:fields => :all</tt>). class Article < Base RAW_FIELDS = %w(url) TEXT_FIELDS = %w(abstract author body byline lead_paragraph nytd_lead_paragraph nytd_title title) NUMERIC_FIELDS = %w(word_count) BOOLEAN_FIELDS = %w(fee small_image) IMAGE_FIELDS = %w(small_image small_image_url small_image_height small_image_width) MULTIMEDIA_FIELDS = %w(multimedia related_multimedia) - ALL_FIELDS = TEXT_FIELDS + RAW_FIELDS + NUMERIC_FIELDS + BOOLEAN_FIELDS + IMAGE_FIELDS + MULTIMEDIA_FIELDS + Facet::ALL_FACETS + ALL_FIELDS = TEXT_FIELDS + RAW_FIELDS + NUMERIC_FIELDS + BOOLEAN_FIELDS + MULTIMEDIA_FIELDS + Facet::ALL_FACETS + IMAGE_FIELDS attr_reader *ALL_FIELDS + # special additional objects + attr_reader :thumbnail + # Scalar facets attr_reader :page, :column, :pub_month, :pub_year, :pub_day, :day_of_week, :desk, :date, :section_page, :source # Facets that return multiple values attr_reader :classifiers, :descriptions, :geo, :material_types, :organizations, :persons, :nytd_bylines, :nytd_descriptions, :nytd_geo, :nytd_organizations, :nytd_persons, :nytd_sections, :nytd_works_mentioned, :works_mentioned @@ -51,11 +58,11 @@ :fee => params['fee'] || false, :lead_paragraph => text_field(params['lead_paragraph']), :nytd_title => text_field(params['nytd_title']), :nytd_lead_paragraph => text_field(params['nytd_lead_paragraph']), :related_multimedia => nil, # FIXME - :image => nil, # FIXME + :thumbnail => Thumbnail.init_from_api(params), :title => text_field(params['title']), :url => params['url'], :word_count => integer_field(params['word_count']), # FACETS THAT RETURN SCALARS @@ -149,20 +156,22 @@ # * <tt>Facet::NYTD_ORGANIZATION</tt> - Standardized names of organizations, assigned for use on NYTimes.com (to get standardized terms, use the TimesTags API). When used in a request, values must be Mixed Case # * <tt>Facet::NYTD_PERSON</tt> - Standardized names of people, assigned for use on NYTimes.com (to get standardized terms, use the TimesTags API). When used in a request, values must be Mixed Case. # * <tt>Facet::NYTD_SECTION</tt> - The section the article appears in (on NYTimes.com) # * <tt>Facet::NYTD_WORKS_MENTIONED</tt> - Literary works mentioned (titles formatted for use on NYTimes.com) # + # Note that for your convenience you can also search with symbol versions of the constants (<tt>:geo => ['MANHATTAN']</tt>). Even pluralization is supported. To get the string API version of the facet use Facet#symbol_name + # # The following two search fields are used for facet searching: - # * <tt>:search_facets</tt> - takes a single value or array of facets to search. Facets can either be specified as array pairs (like <tt>[Facet::GEOGRAPHIC, 'CALIFORNIA']</tt>) or facets returned from a previous search can be passed directly. A single string can be passed as well if you have hand-crafted string. - # * <tt>:exclude_facets</tt> - similar to <tt>:search_facets</tt> but is used to specify a list of facets to exclude. + # * <tt>:only_facets</tt> - takes a single value or array of facets to search. Facets can either be specified as array pairs (like <tt>[Facet::GEOGRAPHIC, 'CALIFORNIA']</tt>) or facets returned from a previous search can be passed directly. A single string can be passed as well if you have hand-crafted string. + # * <tt>:except_facets</tt> - similar to <tt>:only_facets</tt> but is used to specify a list of facets to exclude. # # == OTHER SEARCH FIELDS - # * <tt>:fee</tt> - to be implemented + # * <tt>:fee</tt> - if set to true, only returns articles that must be purchased. If false, returns only free articles. If not specified, returns all articles # * <tt>:begin_date</tt>, <tt>:end_date</tt> - the parameters are used to specify a start and end date for search results. BOTH of these must be provided or the API will return an error. Accepts either a Time/Date argument or a string of the format YYYYMMDD. For convenience the following alternative methods are provided # * <tt>:before</tt> - an alternative to :end_date. Automatically adds a :before_date of sometime in 1980 if no :since argument is also provided; to be implemented # * <tt>:since</tt> - An alternative to :begin_date. Automatically adds an :end_date of Time.now if no :before argument is provided; to be implemented. - # * <tt>:has_thumbnail</tt> - to be implemented + # * <tt>:has_thumbnail</tt> - returns only articles that have thumbnail images associated. Note that to see the thumbnails, you must specify either <tt>:thumbnail</tt> or <tt>:all</tt> in the <tt>:fields</tt> argument). # * <tt>:has_multimedia</tt> - to be implemented # # == FACET SUMMARIES # # The <tt>:facets</tt> argument can be used to specify up to 5 facet fields to be returned alongside the search that provide overall counts @@ -191,14 +200,14 @@ end api_params = {} add_query_params(api_params, params) - add_search_facets_param(api_params, params) + add_facet_conditions_params(api_params, params) add_boolean_params(api_params, params) - add_fields_param(api_params, params) add_facets_param(api_params, params) + add_fields_param(api_params, params) add_rank_params(api_params, params) add_date_params(api_params, params) add_offset_params(api_params, params) reply = invoke(api_params) @@ -237,24 +246,38 @@ ResultSet.init_from_api(reply) end def self.add_facets_param(out_params, in_params) if in_params[:facets] - out_params['facets'] = in_params[:facets].to_a.join(',') + out_params['facets'] = in_params[:facets].to_a.map {|f| Facet.symbol_name(f)}.join(',') end end + def self.field_param(name) + case name.to_s + when 'thumbnail' + IMAGE_FIELDS.join(',') + else + name.to_s + end + end + def self.add_fields_param(out_params, in_params) case in_params[:fields] when nil # do nothing when :all out_params['fields'] = ALL_FIELDS.join(',') + when :none + out_params['fields'] = ' ' + unless out_params['facets'] + out_params['facets'] = Facet::DEFAULT_RETURN_FACETS.join(',') + end when String, Symbol - out_params['fields'] = in_params[:fields].to_s + out_params['fields'] = field_param(in_params[:fields]) when Array - out_params['fields'] = in_params[:fields].map {|f| f.to_s}.join(',') + out_params['fields'] = in_params[:fields].map {|f| field_param(f)}.join(',') else raise ArgumentError, "Fields must either be :all, a single field name, or an array of field names (either strings or symbols)" end end @@ -277,23 +300,27 @@ def self.facet_argument(name, value, exclude = false) unless value.is_a? Array value = [value] end + if name.is_a? Symbol + name = Facet.symbol_name(name) + end + "#{'-' if exclude}#{name}:[#{value.join(',')}]" end def self.parse_facet_params(facets, exclude = false) - search_facets = [] + facet_args = [] case facets when nil # do nothing when String - search_facets = [facets] + facet_args = [facets] when Facet - search_facets = [facet_argument(facets.facet_type, facets.term, exclude)] + facet_args = [facet_argument(facets.facet_type, facets.term, exclude)] when Array unless facets.all? {|f| f.is_a? Facet } raise ArgumentError, "Only Facet instances can be passed in as an array; use Hash for Facet::Name => values input" end @@ -305,25 +332,25 @@ facet_hash[f.facet_type] << f.term end facet_hash.each_pair do |k,v| - search_facets << facet_argument(k, v, exclude) + facet_args << facet_argument(k, v, exclude) end when Hash facets.each_pair do |k,v| - search_facets << facet_argument(k, v, exclude) + facet_args << facet_argument(k, v, exclude) end end - search_facets + facet_args end - def self.add_search_facets_param(out_params, in_params) + def self.add_facet_conditions_params(out_params, in_params) query = out_params['query'] - search_facets = parse_facet_params(in_params[:search_facets]) - exclude_facets = parse_facet_params(in_params[:exclude_facets], true) + search_facets = parse_facet_params(in_params[:only_facets]) + exclude_facets = parse_facet_params(in_params[:except_facets], true) unless search_facets.empty? && exclude_facets.empty? out_params['query'] = ([query] + search_facets + exclude_facets).compact.join(' ') end end \ No newline at end of file