smartdict-core 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +5 -2
- data/VERSION +1 -1
- data/bin/smartdict +3 -7
- data/bin/smartdict-populator +6 -3
- data/config/default_config.yml +4 -0
- data/lib/smartdict/commands/list_command.rb +2 -2
- data/lib/smartdict/commands/translate_command.rb +11 -4
- data/lib/smartdict/commands/version_command.rb +29 -0
- data/lib/smartdict/commands.rb +1 -0
- data/lib/smartdict/core/command_manager.rb +3 -0
- data/lib/smartdict/core/driver_manager.rb +1 -0
- data/lib/smartdict/drivers/abstract_driver.rb +4 -3
- data/lib/smartdict/drivers/lingvo_yandex_driver.rb +146 -0
- data/lib/smartdict/drivers.rb +1 -0
- data/lib/smartdict/errors.rb +13 -1
- data/lib/smartdict/info.rb +14 -0
- data/lib/smartdict/log.rb +108 -0
- data/lib/smartdict/models/translation.rb +13 -12
- data/lib/smartdict/models/word.rb +0 -1
- data/lib/smartdict/storage/seeder.rb +6 -3
- data/lib/smartdict/storage/seeds/drivers.csv +1 -0
- data/lib/smartdict/storage/seeds/word_classes.csv +3 -1
- data/lib/smartdict/translator/base.rb +35 -0
- data/lib/smartdict/translator/driver_configuration.rb +19 -0
- data/lib/smartdict/translator/language_detector.rb +72 -0
- data/lib/smartdict/translator.rb +18 -23
- data/lib/smartdict.rb +6 -1
- metadata +27 -8
- data/lib/smartdict/list_builder.rb +0 -51
- data/lib/smartdict/runner.rb +0 -5
    
        data/README.markdown
    CHANGED
    
    | @@ -1,6 +1,9 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # smartdict-core [](http://travis-ci.org/smartdict/smartdict-core)
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            By [Sergey Potapov](https://github.com/greyblake)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             | 
| 6 | 
            +
            Core of [Smartdict dictionary](https://github.com/smartdict/smartdict).
         | 
| 4 7 |  | 
| 5 8 | 
             
            ## Installation
         | 
| 6 9 |  | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0 | 
| 1 | 
            +
            0.1.0
         | 
    
        data/bin/smartdict
    CHANGED
    
    | @@ -4,17 +4,13 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) | |
| 4 4 | 
             
            require 'rubygems'
         | 
| 5 5 |  | 
| 6 6 | 
             
            require 'smartdict'
         | 
| 7 | 
            -
            require 'smartdict/runner'
         | 
| 8 7 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
            Smartdict.env = :user
         | 
| 8 | 
            +
            env = ENV["SMARTDICT_ENV"] ? ENV["SMARTDICT_ENV"].to_sym : :user
         | 
| 9 | 
            +
            Smartdict.env = env
         | 
| 13 10 |  | 
| 14 11 | 
             
            args = ARGV.clone
         | 
| 15 12 |  | 
| 16 13 | 
             
            Smartdict.load_plugins
         | 
| 17 14 |  | 
| 18 | 
            -
            # TODO :move Smartdict.run to Runner.run
         | 
| 19 15 | 
             
            Smartdict.run
         | 
| 20 | 
            -
            Smartdict:: | 
| 16 | 
            +
            Smartdict::Core::CommandManager.run(args)
         | 
    
        data/bin/smartdict-populator
    CHANGED
    
    | @@ -15,11 +15,14 @@ Smartdict.load_plugins | |
| 15 15 | 
             
            # TODO :mode Smartdict.run to Runner.run
         | 
| 16 16 | 
             
            Smartdict.run
         | 
| 17 17 |  | 
| 18 | 
            +
            $translator = Smartdict::Translator.new
         | 
| 18 19 |  | 
| 19 20 |  | 
| 20 21 | 
             
            def translate(word)
         | 
| 21 | 
            -
               | 
| 22 | 
            +
              $translator.translate(word, :log => true)
         | 
| 22 23 | 
             
            rescue Smartdict::TranslationNotFound
         | 
| 24 | 
            +
            rescue NoMethodError => err
         | 
| 25 | 
            +
              puts "Trouble word: #{word}"
         | 
| 23 26 | 
             
            end
         | 
| 24 27 |  | 
| 25 28 | 
             
            def translate_words(words, from_lang, to_lang)
         | 
| @@ -37,8 +40,8 @@ to_lang   = Smartdict::Models::Language.first(:code => 'ru') | |
| 37 40 |  | 
| 38 41 |  | 
| 39 42 | 
             
            while(true)
         | 
| 40 | 
            -
               | 
| 41 | 
            -
               | 
| 43 | 
            +
              $translator.default_opts[:from_lang] = from_lang.code
         | 
| 44 | 
            +
              $translator.default_opts[:to_lang] = to_lang.code
         | 
| 42 45 |  | 
| 43 46 | 
             
              words = Smartdict::Models::Word.all(:language_id => from_lang.id).map(&:name)
         | 
| 44 47 | 
             
              translate_words(words, from_lang, to_lang)
         | 
    
        data/config/default_config.yml
    CHANGED
    
    
| @@ -24,14 +24,14 @@ module Smartdict::Commands | |
| 24 24 | 
             
                        :driver => nil
         | 
| 25 25 |  | 
| 26 26 | 
             
                def execute
         | 
| 27 | 
            -
                   | 
| 27 | 
            +
                  fetch_opts = {
         | 
| 28 28 | 
             
                    :since     => @options[:since],
         | 
| 29 29 | 
             
                    :till      => @options[:till],
         | 
| 30 30 | 
             
                    :from_lang => @options[:from],
         | 
| 31 31 | 
             
                    :to_lang   => @options[:to],
         | 
| 32 32 | 
             
                    :driver    => @options[:driver]
         | 
| 33 33 | 
             
                  }
         | 
| 34 | 
            -
                  translations = Smartdict:: | 
| 34 | 
            +
                  translations = Smartdict::Log.fetch(fetch_opts)
         | 
| 35 35 | 
             
                  puts format.format_list(translations)
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| @@ -16,12 +16,19 @@ module Smartdict::Commands | |
| 16 16 |  | 
| 17 17 | 
             
                options :from   => lambda { configatron.default.from_lang },
         | 
| 18 18 | 
             
                        :to     => lambda { configatron.default.to_lang },
         | 
| 19 | 
            -
                        :format => lambda { configatron.default.format }
         | 
| 19 | 
            +
                        :format => lambda { configatron.default.format },
         | 
| 20 | 
            +
                        :driver => nil
         | 
| 20 21 |  | 
| 21 22 | 
             
                def execute
         | 
| 22 | 
            -
                   | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 23 | 
            +
                  translator_opts = {
         | 
| 24 | 
            +
                    :from_lang => @options[:from],
         | 
| 25 | 
            +
                    :to_lang   => @options[:to],
         | 
| 26 | 
            +
                    :log       => true
         | 
| 27 | 
            +
                  }
         | 
| 28 | 
            +
                  translator_opts[:driver] = @options[:driver] if @options[:driver]
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  translator = Smartdict::Translator.new(translator_opts)
         | 
| 31 | 
            +
                  translation = translator.translate(@arguments[:word])
         | 
| 25 32 | 
             
                  puts format.format_translation(translation)
         | 
| 26 33 | 
             
                end
         | 
| 27 34 |  | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module Smartdict::Commands
         | 
| 2 | 
            +
              # Displays information about the program.
         | 
| 3 | 
            +
              # It's executed when user runs one of:
         | 
| 4 | 
            +
              # * smartdict -v
         | 
| 5 | 
            +
              # * smartdict --version
         | 
| 6 | 
            +
              # * smartdict version
         | 
| 7 | 
            +
              class VersionCommand < AbstractCommand
         | 
| 8 | 
            +
                include Smartdict::Core
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                set_name        "version"
         | 
| 11 | 
            +
                set_summary     "Displays information about Smartdict"
         | 
| 12 | 
            +
                set_description "Displays information about Smartdict"
         | 
| 13 | 
            +
                set_syntax       prog_name
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                set_usage <<-SYNTAX
         | 
| 16 | 
            +
                  smartdict --version
         | 
| 17 | 
            +
                  smartdict -v
         | 
| 18 | 
            +
                  #{prog_name}
         | 
| 19 | 
            +
                SYNTAX
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # :nodoc:
         | 
| 22 | 
            +
                def execute
         | 
| 23 | 
            +
                  info = Smartdict.info
         | 
| 24 | 
            +
                  puts "Smartdict core v#{info.version}\n" \
         | 
| 25 | 
            +
                       "Author: #{info.author} (#{info.email})\n" \
         | 
| 26 | 
            +
                       "URL: #{info.url}"
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/smartdict/commands.rb
    CHANGED
    
    
| @@ -3,6 +3,7 @@ class Smartdict::Core::CommandManager | |
| 3 3 | 
             
              include Smartdict::Commands
         | 
| 4 4 |  | 
| 5 5 | 
             
              register 'help'     , HelpCommand
         | 
| 6 | 
            +
              register 'version'  , VersionCommand
         | 
| 6 7 | 
             
              register 'translate', TranslateCommand
         | 
| 7 8 | 
             
              register 'list'     , ListCommand
         | 
| 8 9 |  | 
| @@ -12,6 +13,8 @@ class Smartdict::Core::CommandManager | |
| 12 13 | 
             
                case first_arg
         | 
| 13 14 | 
             
                when nil, '-h', '--help', 'help'
         | 
| 14 15 | 
             
                  run_command :help, args
         | 
| 16 | 
            +
                when nil, '-v', '--version', 'version'
         | 
| 17 | 
            +
                  run_command :version, args
         | 
| 15 18 | 
             
                else
         | 
| 16 19 | 
             
                  run_command(first_arg, args)
         | 
| 17 20 | 
             
                end
         | 
| @@ -27,7 +27,7 @@ class Smartdict::Drivers::AbstractDriver | |
| 27 27 | 
             
              attr_accessor :translated, :transcription
         | 
| 28 28 |  | 
| 29 29 | 
             
              # Is used to identify a driver
         | 
| 30 | 
            -
               | 
| 30 | 
            +
              class_attribute :name
         | 
| 31 31 |  | 
| 32 32 | 
             
              def self.translate(*args)
         | 
| 33 33 | 
             
                self.new(*args).build_translation
         | 
| @@ -40,9 +40,10 @@ class Smartdict::Drivers::AbstractDriver | |
| 40 40 |  | 
| 41 41 | 
             
              def initialize(word, from_lang, to_lang)
         | 
| 42 42 | 
             
                @word      = word
         | 
| 43 | 
            -
                @from_lang = from_lang
         | 
| 44 | 
            -
                @to_lang   = to_lang
         | 
| 43 | 
            +
                @from_lang = from_lang.to_s
         | 
| 44 | 
            +
                @to_lang   = to_lang.to_s
         | 
| 45 45 | 
             
                translate
         | 
| 46 | 
            +
                raise Smartdict::TranslationNotFound if(translated.nil? || translated.empty?)
         | 
| 46 47 | 
             
              end
         | 
| 47 48 |  | 
| 48 49 | 
             
              def build_translation
         | 
| @@ -0,0 +1,146 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'cgi'
         | 
| 4 | 
            +
            require 'nokogiri'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Smartdict::Drivers
         | 
| 7 | 
            +
              # The translation driver for Google Translate service.
         | 
| 8 | 
            +
              #
         | 
| 9 | 
            +
              # DISCLAIMER:
         | 
| 10 | 
            +
              # It's was written when I had one hand broken. Refactoring costs a lot of
         | 
| 11 | 
            +
              # movements so that I've left it as it was. I'm gonna refactor it soon.
         | 
| 12 | 
            +
              # -- Sergey Potapov
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # TODO:
         | 
| 15 | 
            +
              #   * Refactor
         | 
| 16 | 
            +
              class LingvoYandexDriver < AbstractDriver
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # Pretend being Firefox :)
         | 
| 19 | 
            +
                USER_AGENT = "Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.1.16) Gecko/20110429 Iceweasel/3.5.16 (like Firefox/3.5.1623123)"
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # Host of Lingvo service.
         | 
| 22 | 
            +
                HOST = "lingvo.yandex.ru"
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # Mapping for word classes. Default is "other"
         | 
| 25 | 
            +
                WORD_CLASSES = {
         | 
| 26 | 
            +
                  "имя существительное"     => "noun",
         | 
| 27 | 
            +
                  "имя прилагательное"      => "adjective",
         | 
| 28 | 
            +
                  "глагол"                  => "verb",
         | 
| 29 | 
            +
                  "наречие"                 => "adverb",
         | 
| 30 | 
            +
                  "предлог"                 => "preposition",
         | 
| 31 | 
            +
                  "имя числительное"        => "numeral",
         | 
| 32 | 
            +
                  "междометие (часть речи)" => "interjection",
         | 
| 33 | 
            +
                  "сокращение"              => "abbreviation",
         | 
| 34 | 
            +
                  "местоимение"             => "pronoun",
         | 
| 35 | 
            +
                  "союз (часть речи)"       => "conjunction"
         | 
| 36 | 
            +
                }.tap{ |hash| hash.default = "other" }
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                set_name "lingvo_yandex"
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 41 | 
            +
             | 
| 42 | 
            +
                # TODO: refactor
         | 
| 43 | 
            +
                def translate
         | 
| 44 | 
            +
                  doc = Nokogiri::HTML(get_response)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  if main_div = doc.css("div.b-translate > div.b-translate__value > ul > li#I").first
         | 
| 47 | 
            +
                    translate__value = main_div
         | 
| 48 | 
            +
                  else
         | 
| 49 | 
            +
                    main_div = doc.css("div.b-translate").first
         | 
| 50 | 
            +
                    translate__value = main_div.css("div.b-translate__value")
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  # Fetch transcription
         | 
| 54 | 
            +
                  self.transcription = main_div.xpath('(.//span[@class="b-translate__tr"])[1]').try(:text)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  self.translated = {}
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  if translate__value.xpath("./i/acronym").any?
         | 
| 59 | 
            +
                    grep_meanings(translate__value)
         | 
| 60 | 
            +
                  else
         | 
| 61 | 
            +
                    translate__value.xpath("./ul/li").each do |li|
         | 
| 62 | 
            +
                      grep_meanings(li)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                # TODO: refactor
         | 
| 68 | 
            +
                def grep_meanings(html_element)
         | 
| 69 | 
            +
                  acronym = html_element.css("acronym").first
         | 
| 70 | 
            +
                  return unless acronym
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  ru_word_class = acronym["title"]
         | 
| 73 | 
            +
                  word_class = WORD_CLASSES[ru_word_class]
         | 
| 74 | 
            +
                  translations = []
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  html_element.css("ul > li").each do |tr|
         | 
| 77 | 
            +
                    # a text line with translations separated by commas
         | 
| 78 | 
            +
                    line = ""
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                    # use strong tag as an anchor
         | 
| 81 | 
            +
                    strong = tr.css("strong").first
         | 
| 82 | 
            +
                    if strong && strong.text =~ /\d+|[а-я]+\)/
         | 
| 83 | 
            +
                      node = strong
         | 
| 84 | 
            +
                      while(node = node.next_sibling)
         | 
| 85 | 
            +
                        if node.text? || node.name == "a"
         | 
| 86 | 
            +
                          text = node.text
         | 
| 87 | 
            +
                          line << text unless text =~ /\(|\)/
         | 
| 88 | 
            +
                        elsif ["em", "acronym"].include? node.name
         | 
| 89 | 
            +
                          next
         | 
| 90 | 
            +
                        else
         | 
| 91 | 
            +
                          break
         | 
| 92 | 
            +
                        end
         | 
| 93 | 
            +
                      end
         | 
| 94 | 
            +
                    end
         | 
| 95 | 
            +
                    translations += words_from_line(line)
         | 
| 96 | 
            +
                  end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
             | 
| 99 | 
            +
                  # sometimes there is only one meaning
         | 
| 100 | 
            +
                  if translations.empty?
         | 
| 101 | 
            +
                    if a_tag = html_element.css("span > a").first
         | 
| 102 | 
            +
                      line = a_tag.text
         | 
| 103 | 
            +
                    elsif span = html_element.css("span").first
         | 
| 104 | 
            +
                      line = span.text
         | 
| 105 | 
            +
                    elsif i_tag = html_element.xpath("i[2]")
         | 
| 106 | 
            +
                      line = i_tag.text
         | 
| 107 | 
            +
                    else
         | 
| 108 | 
            +
                      return nil
         | 
| 109 | 
            +
                    end
         | 
| 110 | 
            +
                    translations = words_from_line(line)
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  self.translated[word_class] = translations.uniq
         | 
| 114 | 
            +
                end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                def get_response
         | 
| 117 | 
            +
                  http = Net::HTTP.new(HOST, 80)
         | 
| 118 | 
            +
                  request = Net::HTTP::Get.new(http_path, { "User-Agent" => USER_AGENT })
         | 
| 119 | 
            +
                  http.request(request).read_body
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                # @return [String] http path for request to translate word.
         | 
| 123 | 
            +
                def http_path
         | 
| 124 | 
            +
                  phrase = case [from_lang, to_lang]
         | 
| 125 | 
            +
                  when ["en", "ru"] then "с английского"
         | 
| 126 | 
            +
                  # ru -> en does not seem to be good and it's not trivial to parse
         | 
| 127 | 
            +
                  # when ["ru", "en"] then "по-английски"
         | 
| 128 | 
            +
                  else raise Smartdict::TranslationNotFound
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  "/#{escape(word)}/#{escape(phrase)}/"
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                def escape(str)
         | 
| 135 | 
            +
                  CGI.escape(str)
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
             | 
| 139 | 
            +
                private
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                def words_from_line(line)
         | 
| 142 | 
            +
                  line.split(/,|;/).map(&:strip).reject(&:empty?)
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              end
         | 
| 146 | 
            +
            end
         | 
    
        data/lib/smartdict/drivers.rb
    CHANGED
    
    
    
        data/lib/smartdict/errors.rb
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            module Smartdict
         | 
| 2 2 |  | 
| 3 | 
            -
              class Error < :: | 
| 3 | 
            +
              class Error < ::StandardError; end
         | 
| 4 | 
            +
             | 
| 4 5 |  | 
| 5 6 | 
             
              class TranslationNotFound < Error
         | 
| 6 7 | 
             
                def initialize(msg = "Translation is not found")
         | 
| @@ -8,4 +9,15 @@ module Smartdict | |
| 8 9 | 
             
                end
         | 
| 9 10 | 
             
              end
         | 
| 10 11 |  | 
| 12 | 
            +
             | 
| 13 | 
            +
              class MissingOption < Error
         | 
| 14 | 
            +
                def initialize(option)
         | 
| 15 | 
            +
                  @option = option
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def message
         | 
| 19 | 
            +
                  "Translator option is missing: `#{@option}`"
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
             | 
| 11 23 | 
             
            end
         | 
| @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            require 'singleton'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Smartdict
         | 
| 4 | 
            +
              class Info < Struct.new(:version, :author, :email, :url)
         | 
| 5 | 
            +
                include Singleton
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize
         | 
| 8 | 
            +
                  self.version = Smartdict::VERSION
         | 
| 9 | 
            +
                  self.author  = "Sergey Potapov"
         | 
| 10 | 
            +
                  self.email   = "open.smartdict@gmail.com"
         | 
| 11 | 
            +
                  self.url     = "http://smartdict.net"
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,108 @@ | |
| 1 | 
            +
            class Smartdict::Log
         | 
| 2 | 
            +
              include Smartdict::Models
         | 
| 3 | 
            +
             | 
| 4 | 
            +
              # Options:
         | 
| 5 | 
            +
              # * +:since+
         | 
| 6 | 
            +
              # * +:till+
         | 
| 7 | 
            +
              # * +:from_lang+
         | 
| 8 | 
            +
              # * +:to_lang+
         | 
| 9 | 
            +
              # * +:driver+
         | 
| 10 | 
            +
              # * +:limit+
         | 
| 11 | 
            +
              # * +:order_desc+
         | 
| 12 | 
            +
              # * +:unique+
         | 
| 13 | 
            +
              #
         | 
| 14 | 
            +
              # @return [Array] array of {Smartdict::Translation}.
         | 
| 15 | 
            +
              def self.fetch(options = {})
         | 
| 16 | 
            +
                new(options).send(:fetch)
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
              private
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def initialize(options)
         | 
| 23 | 
            +
                @options = options
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              def fetch
         | 
| 27 | 
            +
                fetch_translations.map(&:to_struct)
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
              # Unfortunately it's not possible to build necessary query with DataMapper
         | 
| 33 | 
            +
              # TODO: Refactor in QueryBuilder class.
         | 
| 34 | 
            +
              def fetch_translations
         | 
| 35 | 
            +
                adapter = Translation.repository.adapter
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                translations_table = Translation.storage_name
         | 
| 38 | 
            +
                queries_table = TranslationQuery.storage_name
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                sql = "SELECT #{'DISTINCT' if @options[:unique]} #{translations_table}.id \n" \
         | 
| 41 | 
            +
                      "FROM #{translations_table} \n" \
         | 
| 42 | 
            +
                      "INNER JOIN #{queries_table} ON \n" \
         | 
| 43 | 
            +
                      "  #{queries_table}.translation_id == #{translations_table}.id"
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                if [:till, :since, :from_lang, :to_lang, :driver].any? {|opt| @options[opt] }
         | 
| 46 | 
            +
                  sql << " WHERE "
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  if @options[:till]
         | 
| 49 | 
            +
                    till = @options[:till].is_a?(String) ? Date.parse(@options[:till]) : @options[:till]
         | 
| 50 | 
            +
                    sql << " #{queries_table}.created_at < \"#{till.to_s(:db)}\" "
         | 
| 51 | 
            +
                    where = true
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  if @options[:since]
         | 
| 55 | 
            +
                    sql << " AND " if where
         | 
| 56 | 
            +
                    since = @options[:since].is_a?(String) ? Date.parse(@options[:since]) : @options[:since]
         | 
| 57 | 
            +
                    sql << " #{queries_table}.created_at >  \"#{since.to_s(:db)}\" "
         | 
| 58 | 
            +
                    where = true
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  if from_lang
         | 
| 62 | 
            +
                    sql << " AND " if where
         | 
| 63 | 
            +
                    sql << " #{translations_table}.from_lang_id = #{from_lang.id} "
         | 
| 64 | 
            +
                    where = true
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  if to_lang
         | 
| 68 | 
            +
                    sql << " AND " if where
         | 
| 69 | 
            +
                    sql << " #{translations_table}.to_lang_id = #{to_lang.id} "
         | 
| 70 | 
            +
                    where = true
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  if driver
         | 
| 74 | 
            +
                    sql << " AND " if where
         | 
| 75 | 
            +
                    sql << " #{translations_table}.driver_id = #{driver.id} "
         | 
| 76 | 
            +
                    where = true
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                if @options[:order_desc]
         | 
| 81 | 
            +
                  sql << " ORDER BY #{queries_table}.created_at DESC "
         | 
| 82 | 
            +
                else
         | 
| 83 | 
            +
                  sql << " ORDER BY #{queries_table}.created_at "
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                if @options[:limit]
         | 
| 87 | 
            +
                  sql << " LIMIT #{@options[:limit]} "
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                ids = adapter.select(sql)
         | 
| 91 | 
            +
                trs = Translation.all(:id => ids)
         | 
| 92 | 
            +
                # Sort manually, since database doesn't guaranty required order
         | 
| 93 | 
            +
                trs.sort! { |a, b| ids.index(a.id) <=> ids.index(b.id) }
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              def from_lang
         | 
| 97 | 
            +
                Language[@options[:from_lang]]
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              def to_lang
         | 
| 101 | 
            +
                Language[@options[:to_lang]]
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              def driver
         | 
| 105 | 
            +
                Driver[@options[:driver]]
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            end
         | 
| @@ -2,11 +2,12 @@ class Smartdict::Models::Translation | |
| 2 2 | 
             
              include DataMapper::Resource
         | 
| 3 3 | 
             
              include Smartdict::Models
         | 
| 4 4 |  | 
| 5 | 
            -
              property :id | 
| 6 | 
            -
              property :word_id | 
| 7 | 
            -
              property :from_lang_id, Integer, :unique_index => :index_translation
         | 
| 8 | 
            -
              property :to_lang_id | 
| 9 | 
            -
              property :driver_id | 
| 5 | 
            +
              property :id           , Serial
         | 
| 6 | 
            +
              property :word_id      , Integer, :unique_index => :index_translation
         | 
| 7 | 
            +
              property :from_lang_id , Integer, :unique_index => :index_translation
         | 
| 8 | 
            +
              property :to_lang_id   , Integer, :unique_index => :index_translation
         | 
| 9 | 
            +
              property :driver_id    , Integer, :unique_index => :index_translation
         | 
| 10 | 
            +
              property :transcription, String
         | 
| 10 11 |  | 
| 11 12 | 
             
              belongs_to :word
         | 
| 12 13 | 
             
              belongs_to :driver
         | 
| @@ -28,14 +29,14 @@ class Smartdict::Models::Translation | |
| 28 29 | 
             
                driver    = Driver[struct.driver]
         | 
| 29 30 |  | 
| 30 31 | 
             
                word = Word.first_or_create(:name => struct.word, :language_id => from_lang.id)
         | 
| 31 | 
            -
                word.transcription = struct.transcription if word.transcription.blank?
         | 
| 32 32 | 
             
                word.save!
         | 
| 33 33 |  | 
| 34 34 | 
             
                translation = self.create(
         | 
| 35 | 
            -
                  :word | 
| 36 | 
            -
                  :driver | 
| 37 | 
            -
                  :from_lang_id | 
| 38 | 
            -
                  :to_lang_id | 
| 35 | 
            +
                  :word          => word,
         | 
| 36 | 
            +
                  :driver        => driver,
         | 
| 37 | 
            +
                  :from_lang_id  => from_lang.id,
         | 
| 38 | 
            +
                  :to_lang_id    => to_lang.id,
         | 
| 39 | 
            +
                  :transcription => struct.transcription
         | 
| 39 40 | 
             
                )
         | 
| 40 41 |  | 
| 41 42 | 
             
                struct.translated.each do |word_class_name, meanings|
         | 
| @@ -59,7 +60,7 @@ class Smartdict::Models::Translation | |
| 59 60 | 
             
              end
         | 
| 60 61 |  | 
| 61 62 |  | 
| 62 | 
            -
              # TODO: it's a hack | 
| 63 | 
            +
              # TODO: it's a hack which necessary because of weird DM bugs.
         | 
| 63 64 | 
             
              def initialize(*args)
         | 
| 64 65 | 
             
                self.class.finalize
         | 
| 65 66 | 
             
                self.word_class_id = 1
         | 
| @@ -69,7 +70,7 @@ class Smartdict::Models::Translation | |
| 69 70 | 
             
              def to_struct
         | 
| 70 71 | 
             
                struct = Smartdict::Translation.new(
         | 
| 71 72 | 
             
                  :word          => word.name,
         | 
| 72 | 
            -
                  :transcription =>  | 
| 73 | 
            +
                  :transcription => self.transcription,
         | 
| 73 74 | 
             
                  :from_lang     => from_lang.code,
         | 
| 74 75 | 
             
                  :to_lang       => to_lang.code,
         | 
| 75 76 | 
             
                  :driver        => driver.name
         | 
| @@ -19,8 +19,11 @@ module Smartdict::Storage::Seeder | |
| 19 19 |  | 
| 20 20 | 
             
              def seed_from(csv_file)
         | 
| 21 21 | 
             
                model = csv_file_to_model(csv_file)
         | 
| 22 | 
            -
                CSV. | 
| 23 | 
            -
             | 
| 22 | 
            +
                csv = CSV.open(csv_file, 'r')
         | 
| 23 | 
            +
                headers = csv.shift
         | 
| 24 | 
            +
                while(row = csv.shift and not row.empty?)
         | 
| 25 | 
            +
                  attrs = Hash[headers.zip(row)]
         | 
| 26 | 
            +
                  model.create(attrs)
         | 
| 24 27 | 
             
                end
         | 
| 25 28 | 
             
              end
         | 
| 26 29 |  | 
| @@ -29,4 +32,4 @@ module Smartdict::Storage::Seeder | |
| 29 32 | 
             
                model_name = plural_name.classify
         | 
| 30 33 | 
             
                Smartdict::Models.const_get(model_name)
         | 
| 31 34 | 
             
              end
         | 
| 32 | 
            -
            end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            # The very basic translator middleware.
         | 
| 2 | 
            +
            module Smartdict
         | 
| 3 | 
            +
              class Translator::Base
         | 
| 4 | 
            +
                # Just to make the interface compatible
         | 
| 5 | 
            +
                def initialize(translator = nil)
         | 
| 6 | 
            +
                end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def call(word, opts)
         | 
| 9 | 
            +
                  validate_opts!(opts)
         | 
| 10 | 
            +
                  driver = Smartdict::Core::DriverManager.find(opts[:driver])
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  translation_model = Models::Translation.find(word, opts[:from_lang], opts[:to_lang], opts[:driver])
         | 
| 13 | 
            +
                  unless translation_model
         | 
| 14 | 
            +
                    translation = driver.translate(word, opts[:from_lang], opts[:to_lang])
         | 
| 15 | 
            +
                    translation_model = Models::Translation.create_from_struct(translation)
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                  log_query(translation_model) if opts[:log]
         | 
| 18 | 
            +
                  translation_model.to_struct
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
             | 
| 22 | 
            +
                private
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def validate_opts!(opts)
         | 
| 25 | 
            +
                  required_opts = [:from_lang, :to_lang, :driver, :log]
         | 
| 26 | 
            +
                  required_opts.each do |opt|
         | 
| 27 | 
            +
                    raise(MissingOption.new(opt)) if opts[opt].nil?
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def log_query(translation)
         | 
| 32 | 
            +
                  Models::TranslationQuery.create(:translation => translation)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            # Middleware
         | 
| 2 | 
            +
            class Smartdict::Translator::DriverConfiguration
         | 
| 3 | 
            +
              def initialize(translator)
         | 
| 4 | 
            +
                @translator = translator
         | 
| 5 | 
            +
              end
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              def call(word, opts)
         | 
| 8 | 
            +
                unless opts[:driver]
         | 
| 9 | 
            +
                  opts[:driver] = define_driver(opts[:from_lang], opts[:to_lang])
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                @translator.call(word, opts)
         | 
| 12 | 
            +
              end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              def define_driver(from_lang, to_lang)
         | 
| 15 | 
            +
                key = "#{from_lang}-#{to_lang}"
         | 
| 16 | 
            +
                conf = configatron.drivers
         | 
| 17 | 
            +
                conf.retrieve(key) || conf.retrieve(:default) || raise(Smartdict::Error.new("No default driver"))
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            #encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # It's a translator middleware which tries to identify a language of the
         | 
| 4 | 
            +
            # passed word basing on :from_lang and :to_lang options. If it's possible to
         | 
| 5 | 
            +
            # explicitly identify a language and :from_lang and :to_lang options are
         | 
| 6 | 
            +
            # required to be exchanged it exchanges them.
         | 
| 7 | 
            +
            #
         | 
| 8 | 
            +
            # Example:
         | 
| 9 | 
            +
            #   detector = LanguageDetector.new(translator)
         | 
| 10 | 
            +
            #   detector.call("groß", :from_lang => :en, :to_lang => :de)
         | 
| 11 | 
            +
            #   # It delegates call to translator like this:
         | 
| 12 | 
            +
            #   #   translator.call("groß", :from_lang => :de, :to_lang => :en)
         | 
| 13 | 
            +
            #   # Because in English there is no character "ß" but it exists in German.
         | 
| 14 | 
            +
            #
         | 
| 15 | 
            +
            # NOTE: It doesn't support Ruby 1.8
         | 
| 16 | 
            +
            class Smartdict::Translator::LanguageDetector
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              CHARS = {
         | 
| 19 | 
            +
                :ru => %w(А а Б б В в Г г Д д Е е Ё ё Ж ж З з И и Й й К к Л л М м Н н О о П п Р р С с Т т У у Ф ф Х х Ц ц Ч ч Ш ш Щ щ Ъ ъ Ы ы Ь ь Э э Ю ю Я я),
         | 
| 20 | 
            +
                :en => %w(a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z),
         | 
| 21 | 
            +
                :uk => %w(А а Б б В в Г г Ґ ґ Д д Е е Є є Ж ж З з И и І і Ї ї Й й К к Л л М м Н н О о П п Р р С с Т т У у Ф ф Х х Ц ц Ч ч Ш ш Щ щ Ь ь Ю ю Я я '),
         | 
| 22 | 
            +
                :de => %w(a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z Ä ä Ö ö Ü ü ß),
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # TODO: Add vowels with stresses
         | 
| 25 | 
            +
                :es => %w(A a B b С с D d E e F f G g H h I i J j K k L l M m N n Ň ñ O o P p Q q R r S s T t U u V v W w X x Y y Z z)
         | 
| 26 | 
            +
              }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def initialize(translator)
         | 
| 29 | 
            +
                @translator = translator
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                @matchers = {}
         | 
| 32 | 
            +
                CHARS.each do |lang, chars|
         | 
| 33 | 
            +
                  @matchers[lang] = Matcher.new(chars)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              def call(word, opts)
         | 
| 38 | 
            +
                if exchange?(word, opts[:from_lang], opts[:to_lang]) && !ruby18?
         | 
| 39 | 
            +
                  opts[:to_lang], opts[:from_lang] = opts[:from_lang], opts[:to_lang]
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
                @translator.call(word, opts)
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
             | 
| 45 | 
            +
              private
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def exchange?(word, from_lang, to_lang)
         | 
| 48 | 
            +
                from_matcher = @matchers[from_lang.to_sym]
         | 
| 49 | 
            +
                to_matcher   = @matchers[to_lang.to_sym]
         | 
| 50 | 
            +
                return false unless [from_matcher, to_matcher].all?
         | 
| 51 | 
            +
                to_matcher.match?(word) && !from_matcher.match?(word)
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def ruby18?
         | 
| 55 | 
            +
                RUBY_VERSION =~ /^1\.8/
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
             | 
| 59 | 
            +
             | 
| 60 | 
            +
              class Matcher
         | 
| 61 | 
            +
                def initialize(chars)
         | 
| 62 | 
            +
                  @chars = chars + [" ", "-"]
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def match?(word)
         | 
| 66 | 
            +
                  word.each_char do |char|
         | 
| 67 | 
            +
                    return false unless @chars.include? char
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                  true
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
    
        data/lib/smartdict/translator.rb
    CHANGED
    
    | @@ -1,38 +1,33 @@ | |
| 1 1 | 
             
            module Smartdict
         | 
| 2 2 | 
             
              class Translator
         | 
| 3 | 
            +
                extend ActiveSupport::Autoload
         | 
| 3 4 |  | 
| 4 | 
            -
                 | 
| 5 | 
            -
                 | 
| 5 | 
            +
                autoload :Base
         | 
| 6 | 
            +
                autoload :DriverConfiguration
         | 
| 7 | 
            +
                autoload :LanguageDetector
         | 
| 6 8 |  | 
| 7 | 
            -
                 | 
| 8 | 
            -
                self.from_lang_code = :en
         | 
| 9 | 
            +
                attr_reader :default_opts
         | 
| 9 10 |  | 
| 10 | 
            -
                 | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
                self.log_queries = true
         | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
                def self.translate(word)
         | 
| 18 | 
            -
                  unless translation_model = Models::Translation.find(word, from_lang_code, to_lang_code, driver_name)
         | 
| 19 | 
            -
                    translation = driver.translate(word, from_lang_code, to_lang_code)
         | 
| 20 | 
            -
                    translation_model = Models::Translation.create_from_struct(translation)
         | 
| 21 | 
            -
                  end
         | 
| 22 | 
            -
                  log_query(translation_model) if log_queries
         | 
| 23 | 
            -
                  translation_model.to_struct
         | 
| 11 | 
            +
                def initialize(default_opts = {})
         | 
| 12 | 
            +
                  @default_opts = default_opts
         | 
| 13 | 
            +
                  @middleware_classes = [Base, DriverConfiguration, LanguageDetector]
         | 
| 14 | 
            +
                  @middleware = build_middleware
         | 
| 24 15 | 
             
                end
         | 
| 25 16 |  | 
| 26 | 
            -
                def  | 
| 27 | 
            -
                   | 
| 17 | 
            +
                def translate(word, opts = {})
         | 
| 18 | 
            +
                  opts.reverse_merge!(default_opts)
         | 
| 19 | 
            +
                  @middleware.last.call(word, opts)
         | 
| 28 20 | 
             
                end
         | 
| 29 21 |  | 
| 30 22 |  | 
| 31 23 | 
             
                private
         | 
| 32 24 |  | 
| 33 | 
            -
                def  | 
| 34 | 
            -
                   | 
| 25 | 
            +
                def build_middleware
         | 
| 26 | 
            +
                  hooks = []
         | 
| 27 | 
            +
                  @middleware_classes.each do |klass|
         | 
| 28 | 
            +
                    hooks << klass.new(hooks.last)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                  hooks
         | 
| 35 31 | 
             
                end
         | 
| 36 | 
            -
             | 
| 37 32 | 
             
              end
         | 
| 38 33 | 
             
            end
         | 
    
        data/lib/smartdict.rb
    CHANGED
    
    | @@ -33,7 +33,8 @@ module Smartdict | |
| 33 33 | 
             
              autoload :Translator
         | 
| 34 34 | 
             
              autoload :Formats
         | 
| 35 35 | 
             
              autoload :Translation
         | 
| 36 | 
            -
              autoload : | 
| 36 | 
            +
              autoload :Log
         | 
| 37 | 
            +
              autoload :Info
         | 
| 37 38 |  | 
| 38 39 | 
             
              include Smartdict::Core
         | 
| 39 40 |  | 
| @@ -94,4 +95,8 @@ module Smartdict | |
| 94 95 | 
             
              def plugins_dir
         | 
| 95 96 | 
             
                ENV['SMARTDICT_PLUGINS_DIR'] or File.join(root_dir, 'plugins')
         | 
| 96 97 | 
             
              end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
              def info
         | 
| 100 | 
            +
                Info.instance
         | 
| 101 | 
            +
              end
         | 
| 97 102 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: smartdict-core
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012- | 
| 12 | 
            +
            date: 2012-06-10 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: dm-core
         | 
| @@ -139,6 +139,22 @@ dependencies: | |
| 139 139 | 
             
                - - ! '>='
         | 
| 140 140 | 
             
                  - !ruby/object:Gem::Version
         | 
| 141 141 | 
             
                    version: '0'
         | 
| 142 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 143 | 
            +
              name: nokogiri
         | 
| 144 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 145 | 
            +
                none: false
         | 
| 146 | 
            +
                requirements:
         | 
| 147 | 
            +
                - - ! '>='
         | 
| 148 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 149 | 
            +
                    version: '0'
         | 
| 150 | 
            +
              type: :runtime
         | 
| 151 | 
            +
              prerelease: false
         | 
| 152 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 153 | 
            +
                none: false
         | 
| 154 | 
            +
                requirements:
         | 
| 155 | 
            +
                - - ! '>='
         | 
| 156 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 157 | 
            +
                    version: '0'
         | 
| 142 158 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 143 159 | 
             
              name: guard
         | 
| 144 160 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -388,7 +404,6 @@ extensions: [] | |
| 388 404 | 
             
            extra_rdoc_files:
         | 
| 389 405 | 
             
            - README.markdown
         | 
| 390 406 | 
             
            files:
         | 
| 391 | 
            -
            - ./bin/smartdict
         | 
| 392 407 | 
             
            - ./lib/smartdict-core.rb
         | 
| 393 408 | 
             
            - ./lib/smartdict.rb
         | 
| 394 409 | 
             
            - ./lib/smartdict/commands.rb
         | 
| @@ -397,6 +412,7 @@ files: | |
| 397 412 | 
             
            - ./lib/smartdict/commands/help_command.rb
         | 
| 398 413 | 
             
            - ./lib/smartdict/commands/list_command.rb
         | 
| 399 414 | 
             
            - ./lib/smartdict/commands/translate_command.rb
         | 
| 415 | 
            +
            - ./lib/smartdict/commands/version_command.rb
         | 
| 400 416 | 
             
            - ./lib/smartdict/core.rb
         | 
| 401 417 | 
             
            - ./lib/smartdict/core/command_manager.rb
         | 
| 402 418 | 
             
            - ./lib/smartdict/core/driver_manager.rb
         | 
| @@ -408,13 +424,15 @@ files: | |
| 408 424 | 
             
            - ./lib/smartdict/drivers.rb
         | 
| 409 425 | 
             
            - ./lib/smartdict/drivers/abstract_driver.rb
         | 
| 410 426 | 
             
            - ./lib/smartdict/drivers/google_translate_driver.rb
         | 
| 427 | 
            +
            - ./lib/smartdict/drivers/lingvo_yandex_driver.rb
         | 
| 411 428 | 
             
            - ./lib/smartdict/errors.rb
         | 
| 412 429 | 
             
            - ./lib/smartdict/formats.rb
         | 
| 413 430 | 
             
            - ./lib/smartdict/formats/abstract_format.rb
         | 
| 414 431 | 
             
            - ./lib/smartdict/formats/fb2_format.rb
         | 
| 415 432 | 
             
            - ./lib/smartdict/formats/text_color_format.rb
         | 
| 416 433 | 
             
            - ./lib/smartdict/formats/text_format.rb
         | 
| 417 | 
            -
            - ./lib/smartdict/ | 
| 434 | 
            +
            - ./lib/smartdict/info.rb
         | 
| 435 | 
            +
            - ./lib/smartdict/log.rb
         | 
| 418 436 | 
             
            - ./lib/smartdict/models.rb
         | 
| 419 437 | 
             
            - ./lib/smartdict/models/driver.rb
         | 
| 420 438 | 
             
            - ./lib/smartdict/models/language.rb
         | 
| @@ -425,7 +443,6 @@ files: | |
| 425 443 | 
             
            - ./lib/smartdict/models/word_class.rb
         | 
| 426 444 | 
             
            - ./lib/smartdict/plugin.rb
         | 
| 427 445 | 
             
            - ./lib/smartdict/plugin/initializer_context.rb
         | 
| 428 | 
            -
            - ./lib/smartdict/runner.rb
         | 
| 429 446 | 
             
            - ./lib/smartdict/storage.rb
         | 
| 430 447 | 
             
            - ./lib/smartdict/storage/seeder.rb
         | 
| 431 448 | 
             
            - ./lib/smartdict/storage/seeds/drivers.csv
         | 
| @@ -433,13 +450,15 @@ files: | |
| 433 450 | 
             
            - ./lib/smartdict/storage/seeds/word_classes.csv
         | 
| 434 451 | 
             
            - ./lib/smartdict/translation.rb
         | 
| 435 452 | 
             
            - ./lib/smartdict/translator.rb
         | 
| 453 | 
            +
            - ./lib/smartdict/translator/base.rb
         | 
| 454 | 
            +
            - ./lib/smartdict/translator/driver_configuration.rb
         | 
| 455 | 
            +
            - ./lib/smartdict/translator/language_detector.rb
         | 
| 436 456 | 
             
            - ./lib/smartdict/version.rb
         | 
| 437 457 | 
             
            - GPL-LICENSE.txt
         | 
| 438 458 | 
             
            - VERSION
         | 
| 459 | 
            +
            - bin/smartdict
         | 
| 439 460 | 
             
            - config/default_config.yml
         | 
| 440 461 | 
             
            - README.markdown
         | 
| 441 | 
            -
            - !binary |-
         | 
| 442 | 
            -
              YmluL3NtYXJ0ZGljdA==
         | 
| 443 462 | 
             
            - !binary |-
         | 
| 444 463 | 
             
              YmluL3NtYXJ0ZGljdC1wb3B1bGF0b3I=
         | 
| 445 464 | 
             
            homepage: http://github.com/smartdict/smartdict-core
         | 
| @@ -463,7 +482,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 463 482 | 
             
                  version: '0'
         | 
| 464 483 | 
             
            requirements: []
         | 
| 465 484 | 
             
            rubyforge_project: 
         | 
| 466 | 
            -
            rubygems_version: 1.8. | 
| 485 | 
            +
            rubygems_version: 1.8.24
         | 
| 467 486 | 
             
            signing_key: 
         | 
| 468 487 | 
             
            specification_version: 3
         | 
| 469 488 | 
             
            summary: CLI dictionary
         | 
| @@ -1,51 +0,0 @@ | |
| 1 | 
            -
            # TODO: tests
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            class Smartdict::ListBuilder
         | 
| 4 | 
            -
              include Smartdict::Models
         | 
| 5 | 
            -
             | 
| 6 | 
            -
              # Options:
         | 
| 7 | 
            -
              # * +:since+
         | 
| 8 | 
            -
              # * +:till+
         | 
| 9 | 
            -
              # * +:from_lang+
         | 
| 10 | 
            -
              # * +:to_lang+
         | 
| 11 | 
            -
              # * +:driver+
         | 
| 12 | 
            -
              #
         | 
| 13 | 
            -
              # @return [Array] array of {Smartdict::Translation}.
         | 
| 14 | 
            -
              def self.build(options = {})
         | 
| 15 | 
            -
                new(options).send(:build)
         | 
| 16 | 
            -
              end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
              private
         | 
| 20 | 
            -
             | 
| 21 | 
            -
              def initialize(options)
         | 
| 22 | 
            -
                @options = options
         | 
| 23 | 
            -
                @options[:till] ||= Time.now
         | 
| 24 | 
            -
              end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
              def build
         | 
| 27 | 
            -
                fetch_translations.map(&:to_struct)
         | 
| 28 | 
            -
              end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
              def fetch_translations
         | 
| 31 | 
            -
                query = Translation.all(Translation.translation_queries.created_at.lte => @options[:till])
         | 
| 32 | 
            -
                query = query.all(Translation.translation_queries.created_at.gte => @options[:since]) if @options[:since]
         | 
| 33 | 
            -
                query = query.all(Translation.to_lang_id   => to_lang.id)   if to_lang
         | 
| 34 | 
            -
                query = query.all(Translation.from_lang_id => from_lang.id) if from_lang
         | 
| 35 | 
            -
                query = query.all(Translation.driver_id    => driver.id)    if driver
         | 
| 36 | 
            -
                query
         | 
| 37 | 
            -
              end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
              def from_lang
         | 
| 40 | 
            -
                Language[@options[:from_lang]]
         | 
| 41 | 
            -
              end
         | 
| 42 | 
            -
             | 
| 43 | 
            -
              def to_lang
         | 
| 44 | 
            -
                Language[@options[:to_lang]]
         | 
| 45 | 
            -
              end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
              def driver
         | 
| 48 | 
            -
                Driver[@options[:driver]]
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
            end
         |