Статьи

Милые маленькие библиотеки

Рубин имеет много прекрасных возможностей. Синтаксис прост и понятен, использование методов метапрограммирования легко, объектная модель великолепна… Вы знаете, я могу продолжать с бесконечным списком возможностей и причин любить Ruby. Кстати, одна из недооцененных причин, почему программист должен изучать Ruby, определенно является его сообществом. Есть много умных людей, которые используют Ruby для написания маленьких замечательных библиотек, и в этой статье я расскажу об этом.

Я назвал статью хорошими маленькими библиотеками и, в частности, я хочу сосредоточиться на хорошей маленькой части. Это самый интересный аспект этих библиотек. Это крошечные куски кода, которые элегантно решают проблемы.

и и

Библиотека andand решает проблему безопасного метода навигации очень хорошим способом. Рассмотрим следующий фрагмент кода:

person.address && person.address.zip_code 

Это простая (и уродливая) строка, и здесь идет метод andand:

 require 'andand' # gem install andand person.address.andand.zip_code 

Это отличный способ справиться с такой ситуацией. И мне нравится реализация тоже. Пожалуйста, найдите время, чтобы просмотреть его, вы найдете много интересного. Вы, наверное, знаете, что Rails, благодаря библиотеке ActiveSupport, предоставляет аналогичный метод . Действительно, пример, который мы только что видели, можно написать следующим образом с помощью ActiveSupport:

 require 'active<em>support/core</em>ext/object/try' person.address.try(:zip_code) 

Я должен сказать, что я предпочитаю andand: метод try не использует оператор точки. Я должен передать zip_code как символ, и это дает мне ощущение, что с ним что-то происходит. В некоторых языках даже есть оператор для решения этой проблемы. Например, Groovy предлагает SafeNavigationOperator, а CoffeScript предлагает Existential Operator . Я не фанат такого рода решений, но всегда приятно знать, как другие языки сталкиваются с этими проблемами.

Требование к библиотеке andand имеет приятный побочный эффект: она предоставит вам расширенную версию Object # tap (и определит ее для версий Ruby до 1.9.x). Вы можете фактически вызвать тап без блока:

 [1, 2, 3, 4, 5].tap.pop.map { |n| n * 2 } # => [2, 4, 6, 8] 

Как последний, сладкий , удивительный драгоценный камень, также предлагает метод dont :

 [1, 2, 3, 4, 5].dont.reverse! # => [1, 2, 3, 4, 5] 

Автор этого драгоценного камня ( raganwald ) проделал много интересной работы с Ruby и JavaScript. Он также написал еще одну интересную библиотеку: Invocation Construction Kit, но он не настолько мал, чтобы охватить здесь. В любом случае, вам обязательно нужно проверить его профиль на github, вы найдете много интересного кода и записей.

map_by_method

map_by_method — печально известная маленькая библиотека. Я чувствую, что многие люди не знакомы с этим, но это, безусловно, стоит упомянуть. Gem предоставляет метод map_by_magic для класса Array. Это особенно полезно при работе с IRB (или консолью Rails). Он также работает с ассоциациями ActiveRecord. Нет ничего лучше, чем несколько примеров, объясняющих, как работает эта замечательная библиотека:

 [1, 2, 3, 4, 5].map_by_to_s # => ["1", "2", "3", "4", "5"] %w{foo bar baz}.map_by_reverse => ["oof", "rab", "zab"] 

Хорошие вещи. Наиболее интересной (и полезной) функцией является то, что map_by_method поддерживает следующее:

 Product # => Product(id: integer, name: string, description: text, price: integer, created_at: datetime, updated_at: datetime) Product.all.map_by_name_and_price # => [["foo", 50], ["bar", 100], ["faz", 150]] Product.all.map_by_id_and_name # => [[2, "foo"], [3, "bar"], [4, "faz"]] 

Я рекомендую вам взглянуть на реализацию. Это поможет вам узнать, что map_by_method поддерживает и другие магические методы. На самом деле, вы можете сделать что-то вроде:

 %w{1foo 2foo 2bar 1baz 4baz}.group_by_to_i # {1=>["1foo", "1baz"], 2=>["2foo", "2bar"], 4=>["4baz"]} 

Очень хорошо.

Какие методы

Еще одна маленькая библиотека, которая может быть очень полезна в консоли — это what_methods . Он предоставляет объект № что? это метод поиска. Это поможет вам определить, какие методы могут быть вызваны для данного объекта, чтобы вернуть ожидаемое значение. Вы можете назвать это следующим образом:

 my_obj.what? expected_result 

Вероятно, несколько примеров — лучший способ объяснить, как работает эта маленькая библиотека:

 1.9.3-p0 :001 > require 'what_methods' => true 1.9.3-p0 :002 > 3.5.what? 3 3.5.to_i == 3 3.5.to_int == 3 3.5.floor == 3 3.5.truncate == 3 => [:to_i, :to_int, :floor, :truncate] 1.9.3-p0 :003 > 1.what? 2 1.succ == 2 1.next == 2 => [:succ, :next] 1.9.3-p0 :005 > "Foo".what? "foo" "Foo".downcase == "foo" "Foo".downcase! == "foo" => [:downcase, :downcase!] 1.9.3-p0 :006 > "Foo".what? "FOO" "Foo".upcase == "FOO" "Foo".upcase! == "FOO" => [:upcase, :upcase!] 

Хотите верьте, хотите нет, "Foo".what? "FOO" "Foo".what? "FOO" для меня спасатель. Я не могу объяснить, почему я склонен забывать название этого метода, но это другая история.

До сих пор мы видели три милые маленькие библиотеки, но, по моему скромному мнению, коллекцию драгоценных камней Ruby нельзя считать завершенной, если в ней не указано что-то связанное с тестированием. Ниже я покажу вам несколько действительно интересных проектов, связанных с тестированием.

Бекон

Bacon — это небольшой клон RSpec (и он действительно маленький, посмотрите исходный код). Он очень быстрый (см. Этот доклад для реальных данных) и имеет очень похожий на RSpec синтаксис. Я понимаю возражение по поводу внешней зависимости теперь, когда у нас есть MiniTest. Но если вы, как и я, не любите обязательный глагол для тестирования и хотите что-то более легкое, чем RSpec, то вам обязательно стоит проверить это.

interactive_rspec

Иногда случается, что вы хотите проверить совпадение в консоли. По крайней мере, это случилось со мной, когда я познакомился с RSpec. И вот оно: interactive_spec .

Выполнение команды irspec откроет специальную консоль IRB, и вы сможете сделать что-то вроде следующего:

 1.9.3-p0 :005 > [].should be_empty . Finished in 0.00007 seconds 1 example, 0 failures => true 1.9.3-p0 :006 > [].should_not be_empty RSpec::Expectations::ExpectationNotMetError: expected empty? to return false, got true 

Это великолепно! Кроме того, у драгоценного камня есть много других приятных особенностей. Например, он имеет хорошую интеграцию с Rails. Действительно, вы можете открыть консоль Rails и сделать что-то вроде этого:

 irspec 'spec/requests/users_spec.rb' 

Это все на данный момент. Надеюсь, вам понравилась статья. На самом деле, я думаю о написании других статей по этой теме, поэтому ваши отзывы более чем приветствуются!