Class: Openbeautyfacts::Product
- Inherits:
-
Hashie::Mash
- Object
- Hashie::Mash
- Openbeautyfacts::Product
- Defined in:
- lib/openbeautyfacts/product.rb
Constant Summary collapse
- LOCALE_WEBURL_PREFIXES =
TODO: Add more locales
{ 'fr' => 'produit', 'uk' => 'product', 'us' => 'product', 'world' => 'product' }
Class Method Summary collapse
- .from_html_list(html, list_css_selector, code_from_link_regex, locale: 'world') ⇒ Object
- .from_jquery_mobile_list(jqm_html) ⇒ Object
- .from_website_list(html, locale: 'world') ⇒ Object
-
.from_website_page(page_url, page: -1,, products_count: nil) ⇒ Object
page -1 to fetch all pages.
-
.get(code, locale: DEFAULT_LOCALE) ⇒ Object
(also: find)
Get product.
-
.search(terms, locale: DEFAULT_LOCALE, page: 1, page_size: 20, sort_by: 'unique_scans_n', domain: DEFAULT_DOMAIN) ⇒ Object
(also: where)
Search products.
- .tags_from_page(_klass, page_url, &custom_tag_parsing) ⇒ Object
-
.url(code, locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN) ⇒ Object
Return product API URL.
Instance Method Summary collapse
-
#fetch ⇒ Object
(also: #reload)
Fetch product.
-
#update(user: nil, domain: DEFAULT_DOMAIN) ⇒ Object
(also: #save)
Update product Only product_name, brands and quantity fields seems to be updatable throught app / API.
-
#url(locale: DEFAULT_LOCALE) ⇒ Object
Return Product API URL.
-
#weburl(locale: nil, domain: DEFAULT_DOMAIN) ⇒ Object
Return Product web URL according to locale.
Class Method Details
.from_html_list(html, list_css_selector, code_from_link_regex, locale: 'world') ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/openbeautyfacts/product.rb', line 55 def from_html_list(html, list_css_selector, code_from_link_regex, locale: 'world') dom = Nokogiri::HTML.fragment(html) dom.css(list_css_selector).map do |product| attributes = {} if link = product.css('a').first attributes["product_name"] = link.inner_text.strip if code = link.attr('href')[code_from_link_regex, 1] attributes["_id"] = code attributes["code"] = code end end if image = product.css('img').first and image_url = image.attr('src') attributes["image_small_url"] = image_url attributes["lc"] = Locale.locale_from_link(image_url) end attributes["lc"] ||= locale new(attributes) end end |
.from_jquery_mobile_list(jqm_html) ⇒ Object
80 81 82 |
# File 'lib/openbeautyfacts/product.rb', line 80 def from_jquery_mobile_list(jqm_html) from_html_list(jqm_html, 'ul li:not(#loadmore)', /code=(\d+)\Z/i) end |
.from_website_list(html, locale: 'world') ⇒ Object
84 85 86 |
# File 'lib/openbeautyfacts/product.rb', line 84 def from_website_list(html, locale: 'world') from_html_list(html, 'ul.products li', /\/(\d+)\/?/i, locale: 'world') end |
.from_website_page(page_url, page: -1,, products_count: nil) ⇒ Object
page -1 to fetch all pages
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/openbeautyfacts/product.rb', line 89 def from_website_page(page_url, page: -1, products_count: nil) if page == -1 if products_count # Avoid one call pages_count = (products_count.to_f / 20).ceil (1..pages_count).map { |page| from_website_page(page_url, page: page) }.flatten else products = [] page = 1 begin products_on_page = from_website_page(page_url, page: page) products += products_on_page page += 1 end while products_on_page.any? products end else html = open("#{page_url}/#{page}").read from_website_list(html, locale: Locale.locale_from_link(page_url)) end end |
.get(code, locale: DEFAULT_LOCALE) ⇒ Object Also known as: find
Get product
21 22 23 24 25 26 27 28 29 |
# File 'lib/openbeautyfacts/product.rb', line 21 def get(code, locale: DEFAULT_LOCALE) if code product_url = url(code, locale: locale) json = open(product_url).read hash = JSON.parse(json) new(hash["product"]) if !hash["status"].nil? && hash["status"] == 1 end end |
.search(terms, locale: DEFAULT_LOCALE, page: 1, page_size: 20, sort_by: 'unique_scans_n', domain: DEFAULT_DOMAIN) ⇒ Object Also known as: where
Search products
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/openbeautyfacts/product.rb', line 43 def search(terms, locale: DEFAULT_LOCALE, page: 1, page_size: 20, sort_by: 'unique_scans_n', domain: DEFAULT_DOMAIN) terms = CGI.escape(terms) path = "cgi/search.pl?search_terms=#{terms}&jqm=1&page=#{page}&page_size=#{page_size}&sort_by=#{sort_by}" url = "https://#{locale}.#{domain}/#{path}" json = open(url).read hash = JSON.parse(json) html = hash["jqm"] from_jquery_mobile_list(html) end |
.tags_from_page(_klass, page_url, &custom_tag_parsing) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/openbeautyfacts/product.rb', line 112 def (_klass, page_url, &custom_tag_parsing) html = open(page_url).read dom = Nokogiri::HTML.fragment(html) dom.css('table#tagstable tbody tr').map do |tag| if custom_tag_parsing custom_tag_parsing.call(tag) else link = tag.css('a').first _klass.new({ "name" => link.text.strip, "url" => URI.join(page_url, link.attr('href')).to_s, "products_count" => tag.css('td')[1].text.to_i }) end end end |
.url(code, locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN) ⇒ Object
Return product API URL
34 35 36 37 38 39 |
# File 'lib/openbeautyfacts/product.rb', line 34 def url(code, locale: DEFAULT_LOCALE, domain: DEFAULT_DOMAIN) if code path = "api/v0/produit/#{code}.json" "https://#{locale}.#{domain}/#{path}" end end |
Instance Method Details
#fetch ⇒ Object Also known as: reload
Fetch product
135 136 137 138 139 140 141 142 |
# File 'lib/openbeautyfacts/product.rb', line 135 def fetch if (self.code) product = self.class.get(self.code) self.merge!(product) end self end |
#update(user: nil, domain: DEFAULT_DOMAIN) ⇒ Object Also known as: save
Update product Only product_name, brands and quantity fields seems to be updatable throught app / API. User can be nil Tested not updatable fields: countries, ingredients_text, purchase_places, purchase_places_tag, purchase_places_tags
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/openbeautyfacts/product.rb', line 150 def update(user: nil, domain: DEFAULT_DOMAIN) if self.code && self.lc subdomain = self.lc == 'world' ? 'world' : "world-#{self.lc}" path = 'cgi/product_jqm.pl' uri = URI("https://#{subdomain}.#{domain}/#{path}") params = self.to_hash params.merge!("user_id" => user.user_id, "password" => user.password) if user response = Net::HTTP.post_form(uri, params) data = JSON.parse(response.body) data["status"] == 1 else false end end |
#url(locale: DEFAULT_LOCALE) ⇒ Object
Return Product API URL
169 170 171 |
# File 'lib/openbeautyfacts/product.rb', line 169 def url(locale: DEFAULT_LOCALE) self.class.url(self.code, locale: locale) end |
#weburl(locale: nil, domain: DEFAULT_DOMAIN) ⇒ Object
Return Product web URL according to locale
175 176 177 178 179 180 181 182 |
# File 'lib/openbeautyfacts/product.rb', line 175 def weburl(locale: nil, domain: DEFAULT_DOMAIN) locale ||= self.lc || DEFAULT_LOCALE if self.code && prefix = LOCALE_WEBURL_PREFIXES[locale] path = "#{prefix}/#{self.code}" "https://#{locale}.#{domain}/#{path}" end end |