Igor Alexandrov

Programming and something else…

Yandex::Webmaster Gem and Something More

| Comments

I’ve just released Yandex::Webmaster-0.2.0 gem. Yandex::Webmaster is an object orientated wrapper for Yandex Webmaster API. Here are some links for you to find out more about Webmaster and its API:

What to know more about gem and also get some bonus?

With the help of Yandex::Webmaster you can easily integrate information from Yandex into your Ruby application. This can be useful in back office part of application, or for example when you have application with subdomain per user/company and want to provide your users additional information. Here are some features that are currently supported by gem:

  • get the list of sites, that are available for you;
  • get site stats: tcy, number of indexes URLs, number of errors etc…
  • create new site;
  • get information about site verification and verify new site;
  • get the list of popular queries
  • get status of Sitemap files
  • etc…

But one of the most interesting part of this post is inside of a gem. While working with different APIs and other third side data sources you often want to easily define classes structure with predefined types of data.

For example you have Host class and you know, that it has some attributes. Then you probably write something like this:

1
2
3
4
class Host
  attr_accessor :href, :tcy, :last_access

end

Looks good, but what if you want to typecast some values. Then our class will be a bit more complex.

1
2
3
4
5
6
7
8
9
10
11
12
class Host
  attr_accessor :href
  attr_reader :tcy, :last_access

  def tcy=(value)
    @tcy = value.to_i
  end

  def last_access=(value)
    @last_access = DateTime.parse(value)
  end
end

More attributes you have, more code you will write and less clear structure of the API will be. Doesn’t look well for me. Are you thinking about some DSL to define attributes too?

When I first time got this task I’ve found Virtus rather fast. At it seemed rather well for me. But when I started to use it in Yandex::Webmaster I understood that it is too complex, it redefines rather common methods in you class like attributes=, it adds a lot of garbage instance variables to you objects and so on.

Of course you can tell me that there is and ActiveAttr, but it requires ActiveSupport, which means that it requires Rails… And we remember that Ruby is not equal to Rails, yes?

So I understood that I have to write some clear, small and easy to customize DSL myself. Ok, a man said, a man made (that is how we speak in Russia)! You can see code Yandex::Webmaster::Api::Attributes module and its descendants and examples in Yandex::Webmaster::Host class for example. Here is small example for those, who doesn’t want to read sources.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module Yandex
  module Webmaster
    class Host < Base
      extend Forwardable

      define_attributes :as => 'api_attributes' do
        attr :href, String, :writer => :protected
        attr :name, String, :writer => :protected
        attr :virused, Boolean, :writer => :protected
        attr :last_access, DateTime, :writer => :protected
      end
    end
  end
end

1.9.3-p327 :001 > Yandex::Webmaster::Host.api_attributes
 => {:href=>{:reader_name=>"href", :writer_name=>"href=", :instance_variable_name=>"@href"}, :name=>{:reader_name=>"name", :writer_name=>"name=", :instance_variable_name=>"@name"}, :virused=>{:reader_name=>"virused", :writer_name=>"virused=", :instance_variable_name=>"@virused"}, :last_access=>{:reader_name=>"last_access", :writer_name=>"last_access=", :instance_variable_name=>"@last_access"}, :tcy=>{:reader_name=>"tcy", :writer_name=>"tcy=", :instance_variable_name=>"@tcy"}}

1.9.3-p327 :002 > h = Yandex::Webmaster::Host.new(:last_access => '2012-12-04')
1.9.3-p327 :003 > h.last_access
 => Tue, 04 Dec 2012 00:00:00 +0000

Looks and works great for me! And it doesn’t have any dependencies. I plan to extract this code to a separate gem soon. Do you have any suggestions for the name?

Comments