Goods
The purpose of this gem is to provide simple, yet reliable solution for parsing YML (Yandex Market Language) files, with clean and convenient interface, and a few extra capabilites, such as categories prunning.
Installation
Add this line to your application's Gemfile:
gem 'goods'
And then execute:
$ bundle
Or install it yourself as:
$ gem install goods
Usage
-
How to parse YML-catalog:
begin catalog = Goods.from_string(xml, url, encoding) [ or Goods.from_url(url, encoding) ] [ or Goods.from_file(io, encoding) ] rescue Goods::XML::InvalidFormatError => e #do something end
-
encoding
is optional; -
url
is optional when parsing string;
-
-
How to iterate over offers:
catalog.offers.each do |offer| offer.id # => "some id" offer.category # => <Goods::Category> offer.currency # => <Goods::Currency> offer.price # => 50.0 (for example) etc... end
-
How to iterate over categories:
catalog.categories.each do |category| category.id # => "some id" category.name # => "some name" category.parent # => <Goods::Category> or nil etc... end
-
How to iterate over currencies:
catalog.currencies.each do |currency| currency.id # => "RUR" currency.rate # => 1.00 or 30.00 or some other float etc... end
-
How to get a single element from the collection:
If you know an ID of an object, you may act like this
(for example, let's take currencies) rur = catalog.currencies.find("RUR") # => <Goods::Curency> rur.rate # => 1.00
-
How to prune categories in a whole catalog:
catalog.prune(level_of_pruning)
It will replace all categories with level greater than
level_of_pruning
with their parents at that level.What is the purpose of prunning? For example, with very deep categories structure it may be very costly in terms of performance to mirror this structure in your database. It may be sufficient to have a representation with lower level of details.
-
How to convert currencies and prices for a whole catalog:
rur = catalog.currencies.find("RUR") catalog.convert_currency(rur)
It will convert all prices and change
currency
for every offer. -
But what's with invalid elements:
General validation is performed according to DTD spec., and guarantees that you will have all the fields, that you're expecting to find in a YML-catalog. However, there can be somewhat trickier inconsistencies in YML-files, like offer having non-existing category_id, or currency_id.
All that valid (according to DTD), but defective elements are saved under
defectives
property of a collection. Each defective element hasinvalid_field
property. For example:defectives = catalog.offers.defectives # => Array of Goods::Offer defectives.first.invalid_fields # => [:category_id, :currency_id]
-
How can I manually validate YML-file against DTD?:
validator = Goods::XML::Validator.new validator.valid?(xml_string) # => true or false validator.error # => first validation error
-
Is that all?
No, it is not. For more information look at the source code.
Contributing
At current time, Goods::Offer is quite incomplete, and works only with properties, that I need. Generalization of Goods::Offer is welcome!
So:
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request