<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7401872276116867063</id><updated>2011-04-21T23:05:26.846+04:00</updated><category term='ruby'/><category term='yaml'/><category term='beginners'/><category term='open3'/><category term='learnrb'/><category term='rails'/><category term='caller'/><category term='kernel'/><category term='hash'/><category term='community'/><category term='rmagick'/><category term='thumbnails'/><category term='cmd'/><category term='file'/><category term='config'/><category term='life'/><title type='text'>Digging Ruby</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://digging-ruby.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-5054644511452599862</id><published>2008-12-24T14:09:00.003+03:00</published><updated>2008-12-24T14:11:06.925+03:00</updated><title type='text'>For Crying Out Loud</title><content type='html'>&lt;a href="http://ismerbrails.com/"&gt;http://ismerbrails.com/&lt;/a&gt; :D&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-5054644511452599862?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5054644511452599862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5054644511452599862'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2008/12/for-crying-out-loud.html' title='For Crying Out Loud'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-1719403582670780469</id><published>2008-09-25T19:28:00.002+04:00</published><updated>2008-09-25T19:31:43.069+04:00</updated><title type='text'>Redefining unary operators</title><content type='html'>&lt;script src="http://gist.github.com/12840.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-1719403582670780469?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/1719403582670780469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/1719403582670780469'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2008/09/redefining-unary-operators.html' title='Redefining unary operators'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-8657123217122485144</id><published>2008-08-15T13:07:00.000+04:00</published><updated>2008-08-15T13:08:06.648+04:00</updated><title type='text'>Developers song by Steve Ballmer</title><content type='html'>&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/qh_k4b6Xmh8&amp;hl=en&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/qh_k4b6Xmh8&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-8657123217122485144?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8657123217122485144'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8657123217122485144'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2008/08/developers-song-by-steve-ballmer.html' title='Developers song by Steve Ballmer'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-8030064397314550193</id><published>2008-03-31T16:23:00.006+04:00</published><updated>2008-03-31T21:31:49.932+04:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='community'/><category scheme='http://www.blogger.com/atom/ns#' term='learnrb'/><category scheme='http://www.blogger.com/atom/ns#' term='beginners'/><title type='text'>Разбор решений для задачи про календарные промежутки</title><content type='html'>Время для разбора решений для &lt;a href="http://groups.google.com/group/learnrb/browse_thread/thread/59d65e7ba36e65b5"&gt;задачи про календарные промежутки&lt;/a&gt; =)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Примечание&lt;/span&gt;: &lt;span class="Apple-style-span" style="font-style: italic;"&gt;если в приведенном коде встретился незнакомы метод или класс, то найти документацию можно из терминала с помощь утилиты ri или на сайтах &lt;a target="_blank" rel="nofollow" href="http://gotapi.com/" style="color: rgb(0, 0, 204); "&gt;http://gotapi.com&lt;/a&gt;, &lt;a target="_blank" rel="nofollow" href="http://noobkit.com/" style="color: rgb(0, 0, 204); "&gt;http://noobkit.com&lt;/a&gt;. Также можно использовать &lt;a target="_blank" rel="nofollow" href="http://ru.wikibooks.org/wiki/Ruby" style="color: rgb(85, 26, 139); "&gt;http://ru.wikibooks.org/wiki/Ruby&lt;/a&gt;для русскоязычной документации по часто-употребительным методам встроенных классов. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Само задание не представляет ничего сложного. У нас есть массив со строками, представляющими разные даты. Даты могут повторяться и массив не упорядочен. Требуется выделить из этих дат непрерывные временные диапазоны (то есть найти все последовательности дат, которые идут по календарю подряд)).&lt;br /&gt;&lt;br /&gt;Сама постановка задачи предлагает решение - убрать все повторяющиеся даты, отсортировать их и выделить в отдельные группы даты, идущие друг за другом.  &lt;br /&gt;&lt;br /&gt;Удаление дубликатов и сортировка делаются в одну строчку: &lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;dates.&lt;span class="Entity"&gt;sort!&lt;/span&gt;.uniq!&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Теперь остается реализовать метод для разделения идущие подряд даты на группы.&lt;br /&gt;&lt;br /&gt;Посмотрим, как реализовали этот метод участники в своих решениях:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Версия Кирилла&lt;/span&gt;:&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;date_dzn_start&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;[]&lt;br /&gt;date_dzn_end&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;[]&lt;br /&gt;i&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;&lt;span style="color:#DA4939"&gt;0&lt;/span&gt;&lt;br /&gt;dates.&lt;span class="Entity"&gt;length&lt;/span&gt;.&lt;span class="Entity"&gt;times&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;&lt;br /&gt;  a&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;dates[i].&lt;span class="Entity"&gt;split&lt;/span&gt;(&lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;&amp;quot;&lt;/span&gt;-&lt;span style="color:#A5C261"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;  d&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;&lt;span class="Support"&gt;Date&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt;(a[&lt;span style="color:#DA4939"&gt;0&lt;/span&gt;].&lt;span class="Entity"&gt;to_i&lt;/span&gt; ,a[&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;].&lt;span class="Entity"&gt;to_i&lt;/span&gt;,a[&lt;span style="color:#DA4939"&gt;2&lt;/span&gt;].&lt;span class="Entity"&gt;to_i&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; (d &lt;span style="color:#CC7833"&gt;-&lt;/span&gt; &lt;span style="color:#DA4939"&gt;1&lt;/span&gt;).&lt;span class="Entity"&gt;to_s&lt;/span&gt; &lt;span style="color:#CC7833"&gt;!=&lt;/span&gt; dates[i&lt;span style="color:#CC7833"&gt;-&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;] &lt;span style="color:#CC7833"&gt;then&lt;/span&gt;&lt;br /&gt;    date_dzn_start.&lt;span class="Entity"&gt;push&lt;/span&gt;(d)&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; (d &lt;span style="color:#CC7833"&gt;+&lt;/span&gt; &lt;span style="color:#DA4939"&gt;1&lt;/span&gt;).&lt;span class="Entity"&gt;to_s&lt;/span&gt; &lt;span style="color:#CC7833"&gt;!=&lt;/span&gt; dates[i&lt;span style="color:#CC7833"&gt;+&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;] &lt;span style="color:#CC7833"&gt;then&lt;/span&gt;&lt;br /&gt;    date_dzn_end.&lt;span class="Entity"&gt;push&lt;/span&gt;(d)&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;  i&lt;span style="color:#CC7833"&gt;+=&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;i&lt;span style="color:#CC7833"&gt;=&lt;/span&gt;&lt;span style="color:#DA4939"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;date_dzn_end.&lt;span class="Entity"&gt;length&lt;/span&gt;.&lt;span class="Entity"&gt;times&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;if&lt;/span&gt;(date_dzn_start[i]&lt;span style="color:#CC7833"&gt;!=&lt;/span&gt;date_dzn_end[i]) &lt;span style="color:#CC7833"&gt;then&lt;/span&gt;&lt;br /&gt;    puts date_dzn_start[i]..date_dzn_end[i]&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;else&lt;/span&gt;&lt;br /&gt;    puts date_dzn_start[i]&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;  i&lt;span style="color:#CC7833"&gt;+=&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Каждый элемент массива сравнивается с соседними элементами, причем если текущий элемент не является следующей датой в календаре для левого элемента, или предыдущей датой - для правого, тогда мы его добавляем в массив с начальными датами диапазонов или конечными соответственно. &lt;br /&gt;&lt;br /&gt;Но при таком алгоритме мы делаем в два раза больше проверок, чем необходимо (предположим, что n - текущий индекс элемента массива, тогда мы должны сравнить n-элемент массива с (n-1)-элементом и (n+1)- &lt;br /&gt;элементом, но мы уже сравнивали n-элемент и (n-1)-элемент, когда (n-1) было текущим индексом).&lt;br /&gt;&lt;br /&gt;Конечно, сам &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;код можно сделать более рубиновым&lt;/span&gt;, к примеру, если не вручную поддерживать счетчик, а использовать автоматический предоставляемый методом times, и заменить условные конструкции их сокращенными формами. Вот, что получится, если учесть сказанное и заменить times более подходящими в данном случае методами each и each_with_index :&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;dates.&lt;span class="Entity"&gt;each_with_index&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF"&gt;date&lt;/span&gt;, &lt;span style="color:#D0D0FF"&gt;index&lt;/span&gt;|&lt;br /&gt;  date &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Date&lt;/span&gt;.&lt;span class="Entity"&gt;parse&lt;/span&gt;(date)&lt;br /&gt;  start_dates.&lt;span class="Entity"&gt;push&lt;/span&gt; date &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; (date&lt;span style="color:#CC7833"&gt;-&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;).&lt;span class="Entity"&gt;to_s&lt;/span&gt; &lt;span style="color:#CC7833"&gt;!=&lt;/span&gt; dates[index&lt;span style="color:#CC7833"&gt;-&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;]&lt;br /&gt;  end_dates.&lt;span class="Entity"&gt;push&lt;/span&gt; date &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; (date&lt;span style="color:#CC7833"&gt;+&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;).&lt;span class="Entity"&gt;to_s&lt;/span&gt; &lt;span style="color:#CC7833"&gt;!=&lt;/span&gt; dates[index&lt;span style="color:#CC7833"&gt;+&lt;/span&gt;&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;]&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;start_dates.&lt;span class="Entity"&gt;zip&lt;/span&gt;(end_dates) &lt;span style="color:#CC7833"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF"&gt;start_date&lt;/span&gt;, &lt;span style="color:#D0D0FF"&gt;end_date&lt;/span&gt;|&lt;br /&gt;  puts start_date &lt;span style="color:#CC7833"&gt;==&lt;/span&gt; end_date &lt;span style="color:#CC7833"&gt;?&lt;/span&gt; start_date : start_date..end_date&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Теперь перейдем к &lt;span style="font-weight:bold;"&gt;версии kaineer'a&lt;/span&gt;:&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#D0D0FF"&gt;SEC_PER_HOUR&lt;/span&gt; &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span style="color:#DA4939"&gt;3600&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#D0D0FF"&gt;DAY_AND_HALF&lt;/span&gt; &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; ( &lt;span style="color:#DA4939"&gt;24&lt;/span&gt; &lt;span style="color:#CC7833"&gt;+&lt;/span&gt; &lt;span style="color:#DA4939"&gt;12&lt;/span&gt; ) &lt;span style="color:#CC7833"&gt;*&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;SEC_PER_HOUR&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;more_than_day&lt;/span&gt;(&lt;span style="color:#D0D0FF"&gt; s1&lt;span style="color:#D0D0FF"&gt;,&lt;/span&gt; s2 &lt;/span&gt;)&lt;br /&gt;  d1 &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Time&lt;/span&gt;.&lt;span class="Entity"&gt;mktime&lt;/span&gt;( &lt;span style="color:#CC7833"&gt;*&lt;/span&gt;s1.&lt;span class="Entity"&gt;scan&lt;/span&gt;( &lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexpSpecial"&gt;\d&lt;/span&gt;+&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt; ) )&lt;br /&gt;  d2 &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Time&lt;/span&gt;.&lt;span class="Entity"&gt;mktime&lt;/span&gt;( &lt;span style="color:#CC7833"&gt;*&lt;/span&gt;s2.&lt;span class="Entity"&gt;scan&lt;/span&gt;( &lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexpSpecial"&gt;\d&lt;/span&gt;+&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt; ) )&lt;br /&gt;&lt;br /&gt;  ( d2 &lt;span style="color:#CC7833"&gt;-&lt;/span&gt; d1 ) &lt;span style="color:#CC7833"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;DAY_AND_HALF&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;result &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; dates.&lt;span class="Entity"&gt;inject&lt;/span&gt;( [] ) { |&lt;span style="color:#D0D0FF"&gt;arr&lt;/span&gt;, &lt;span style="color:#D0D0FF"&gt;str&lt;/span&gt;|&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; arr.&lt;span class="Entity"&gt;empty?&lt;/span&gt; &lt;span style="color:#CC7833"&gt;||&lt;/span&gt; &lt;span class="Entity"&gt;more_than_day&lt;/span&gt;( arr.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;last&lt;/span&gt;, str )&lt;br /&gt;    arr &lt;span style="color:#CC7833"&gt;&amp;lt;&amp;lt;&lt;/span&gt; [ str, str ]&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;else&lt;/span&gt;&lt;br /&gt;    arr.&lt;span class="Entity"&gt;last&lt;/span&gt;[ &lt;span style="color:#DA4939"&gt;1&lt;/span&gt; ] &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; str&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  arr&lt;br /&gt;}.&lt;span class="Entity"&gt;map&lt;/span&gt;{|&lt;span style="color:#D0D0FF"&gt;arr&lt;/span&gt;|( arr.&lt;span class="Entity"&gt;first&lt;/span&gt; )..( arr.&lt;span class="Entity"&gt;last&lt;/span&gt; )}&lt;br /&gt;&lt;br /&gt;puts result.inspect&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;здесь выбран правильный подход, когда каждый элемент сравнивается только с  предыдущим элементом, и в зависимости от результатов проверки добавляется либо в последний временной диапазон, либо в новый. Но несмотря на это в решении &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;все равно используется в два раза больше проверок, чем требуется&lt;/span&gt;, и все из-за лишних проверок на начальное состояние.&lt;br /&gt;&lt;br /&gt;Еще пара мелких замечаний: нам не нужно при создании нового временного диапазона дважды добавлять текущий элемент и для выражения "&lt;span style="font-style:italic;"&gt;puts object.inspect&lt;/span&gt;" есть альтернативный лаконичный синтаксис "&lt;span style="font-style:italic;"&gt;p object&lt;/span&gt;". Ну, и опять же в этом решении не использовался класс Date, его метод parse и метод next объектов класса Date, что придало объема программе.&lt;br /&gt;&lt;br /&gt;Устранив лишние сравнения и использовав Date.parse, мы получили довольно симпатичный вариант, хоть и не конечный:&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;result &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; dates.&lt;span class="Entity"&gt;inject&lt;/span&gt;([[ &lt;span class="Support"&gt;Date&lt;/span&gt;.&lt;span class="Entity"&gt;parse&lt;/span&gt;(dates.&lt;span class="Entity"&gt;shift&lt;/span&gt;) ]]) &lt;span style="color:#CC7833"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF"&gt;ranges&lt;/span&gt;, &lt;span style="color:#D0D0FF"&gt;date&lt;/span&gt;|&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;if&lt;/span&gt; (date &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Date&lt;/span&gt;.&lt;span class="Entity"&gt;parse&lt;/span&gt;(date)) &lt;span style="color:#CC7833"&gt;==&lt;/span&gt; ranges.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;next&lt;/span&gt;&lt;br /&gt;    ranges.&lt;span class="Entity"&gt;last&lt;/span&gt;[&lt;span style="color:#DA4939"&gt;1&lt;/span&gt;] &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; date&lt;br /&gt;    ranges&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;else&lt;/span&gt;&lt;br /&gt;    ranges &lt;span style="color:#CC7833"&gt;&amp;lt;&amp;lt;&lt;/span&gt; [date]&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;p result.&lt;span class="Entity"&gt;map&lt;/span&gt; {|&lt;span style="color:#D0D0FF"&gt;it&lt;/span&gt;| &lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;&amp;quot;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;..&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;last&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#A5C261"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Нужно всегда выделять более универсальные алгоритмы, с целью их повторного использования. Поэтому выделим в отдельный метод &lt;span style="font-weight:bold;"&gt;Array#group_by_range&lt;/span&gt; разбивку на группы идущих подряд элементов:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;Array&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;group_by_range&lt;/span&gt;&lt;br /&gt;   &lt;span class="Entity"&gt;inject&lt;/span&gt;([[shift]]) &lt;span style="color:#CC7833;"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF;"&gt;result&lt;/span&gt;, &lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;|&lt;br /&gt;     result &lt;span style="color:#CC7833;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; [] &lt;span style="color:#CC7833;"&gt;unless&lt;/span&gt; it &lt;span style="color:#CC7833;"&gt;==&lt;/span&gt; result.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;next&lt;/span&gt;&lt;br /&gt;     result.&lt;span class="Entity"&gt;last&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; it&lt;br /&gt;     result&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;puts dates.&lt;span class="Entity"&gt;group_by_range&lt;/span&gt;.&lt;span class="Entity"&gt;map&lt;/span&gt; {|&lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;| &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;..&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;last&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Этот метод потом можно будет применить к любому массиву, главное чтобы его элементы поддерживали метод next. То есть в случае с массивом dates нужно всего лишь привести его элементы к классу Date:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;dates.&lt;span class="Entity"&gt;map!&lt;/span&gt; {|&lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;| &lt;span class="Support"&gt;Date&lt;/span&gt;.&lt;span class="Entity"&gt;parse&lt;/span&gt; it }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ну и напоследок пользуясь случаем приведу пример (хоть и немного притянутый за уши) использования метода &lt;span style="font-weight:bold;"&gt;Object#tap&lt;/span&gt;:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;Object&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;tap&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;yield&lt;/span&gt; &lt;span style="color:#D0D0FF;"&gt;self&lt;/span&gt;; &lt;span style="color:#D0D0FF;"&gt;self&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Для этого мы незначительно модифицируем предыдущую версию и получим:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;Array&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;group_by_range&lt;/span&gt;&lt;br /&gt;   &lt;span class="Entity"&gt;inject&lt;/span&gt;([[shift]]) &lt;span style="color:#CC7833;"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF;"&gt;result&lt;/span&gt;, &lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;|&lt;br /&gt;     result &lt;span style="color:#CC7833;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; [] &lt;span style="color:#CC7833;"&gt;unless&lt;/span&gt; it &lt;span style="color:#CC7833;"&gt;==&lt;/span&gt; result.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;last&lt;/span&gt;.&lt;span class="Entity"&gt;next&lt;/span&gt;&lt;br /&gt;     result.&lt;span class="Entity"&gt;tap&lt;/span&gt; {|&lt;span style="color:#D0D0FF;"&gt;array&lt;/span&gt;| array.&lt;span class="Entity"&gt;last&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; it }&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;puts dates.&lt;span class="Entity"&gt;group_by_range&lt;/span&gt;.&lt;span class="Entity"&gt;map&lt;/span&gt; {|&lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;| &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;..&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;it&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;last&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Как видно с помощью &lt;span style="font-weight:bold;"&gt;Object#tap&lt;/span&gt; можно сделать несколько модификаций перед возвращением объекта из метода и тем самым немного улучшить его вид.&lt;br /&gt;&lt;br /&gt;P.S.&lt;br /&gt;Вместо последовательного использование методов uniq и sort было бы конечно лучше использовать что-то вроде sort_uniq (когда сортировка проводится с одновременным отбросом повторяющихся значений), потому что это было бы эффективнее, чем два прохода сначала для отсева повторяющихся значений, а потом сортировки. Главное то, что руби со своим набором готовых алгоритмических и дизайнерских решений позволяет быстро создать рабочий прототип&lt;br /&gt;программы и учит главному правилу программирования - "откладывай оптимизацию на потом". Это позволяет проводить оптимизацию только действительно узких мест, а не всего подряд, что дает значительный прирост продуктивности разработчиков.&lt;br /&gt;&lt;br /&gt;P.P.S.&lt;br /&gt;В методе &lt;span style="font-weight:bold;"&gt;group_by_range&lt;/span&gt; не все в порядке, есть маленькая деталька, которую можно улучшить - жду кто первым заметит =)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-8030064397314550193?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8030064397314550193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8030064397314550193'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2008/03/blog-post.html' title='Разбор решений для задачи про календарные промежутки'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-7221702754000224094</id><published>2008-03-25T17:17:00.005+03:00</published><updated>2008-03-25T17:27:22.244+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='community'/><category scheme='http://www.blogger.com/atom/ns#' term='learnrb'/><category scheme='http://www.blogger.com/atom/ns#' term='beginners'/><title type='text'>Новая google-группа: Знакомство с ruby и ruby on rails</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: arial; font-size: 13px; -webkit-border-horizontal-spacing: 10px; -webkit-border-vertical-spacing: 10px; "&gt;&lt;div&gt;Группа создана для помощи в решении вопросов, связанных с руби и ориентирована прежде всего на начинающих, для прошаренных существует ror2ru. &lt;br /&gt;&lt;/div&gt;&lt;p&gt;Не стесняйтесь задавать простые вопросы - помните &lt;br /&gt;"&lt;span class="Apple-style-span" style="font-style: italic;"&gt;имидж ничто, жажда познания все&lt;/span&gt;", &lt;br /&gt;"&lt;span class="Apple-style-span" style="font-style: italic;"&gt;глупых вопросов не бывает, хотя иногда бывают глупые ответы&lt;/span&gt;".&lt;/p&gt;&lt;p&gt;(from &lt;a href="http://groups.google.com/group/learnrb/about"&gt;http://groups.google.com/group/learnrb/about&lt;/a&gt;)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Кроме того в этой группе я буду регулярно публиковать небольшие задачки разных уровней сложности. Надеюсь, это поможет осознать насколько руби может быть удобен. &lt;/p&gt;&lt;p&gt;&lt;a href="http://groups.google.com/group/learnrb/browse_thread/thread/59d65e7ba36e65b5"&gt;Первая простенькая задачка&lt;/a&gt;.&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-7221702754000224094?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/7221702754000224094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/7221702754000224094'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2008/03/google-ruby-ruby-on-rails.html' title='Новая google-группа: Знакомство с ruby и ruby on rails'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-3720344263279732301</id><published>2007-12-15T21:09:00.000+03:00</published><updated>2007-12-15T21:40:25.403+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='thumbnails'/><category scheme='http://www.blogger.com/atom/ns#' term='rmagick'/><title type='text'>Polaroid thumbnails</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_DLkmVEXn9mk/R2Qae4cVqHI/AAAAAAAAAAU/49QMAI-eXFA/s1600-h/pet-hamster.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: left; cursor: pointer;" src="http://bp2.blogger.com/_DLkmVEXn9mk/R2Qae4cVqHI/AAAAAAAAAAU/49QMAI-eXFA/s200/pet-hamster.jpg" alt="" id="BLOGGER_PHOTO_ID_5144265792213592178" border="0" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_DLkmVEXn9mk/R2QcT4cVqJI/AAAAAAAAAAk/kAjVsoJmUI8/s1600-h/pet-hamster_thumb2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: right; cursor: pointer;" src="http://bp2.blogger.com/_DLkmVEXn9mk/R2QcT4cVqJI/AAAAAAAAAAk/kAjVsoJmUI8/s200/pet-hamster_thumb2.png" alt="" id="BLOGGER_PHOTO_ID_5144267802258286738" border="0" /&gt;&lt;/a&gt;Хотите быть способным преобразовывать так картинки на лету?&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;Я реализовал  у себя в одном rails приложении генерацию подобных thumbnails при отправке пользователем картинки с помощью следующего кода:&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre style="padding: 6px; overflow: auto; background-color: rgb(43, 43, 43); color: rgb(230, 225, 220); line-height: 12px; font-size: 12px;"&gt;&lt;code&gt;&lt;/code&gt;&lt;pre class="sunburst"&gt;  &lt;span style="color: rgb(204, 120, 51);"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;after_save&lt;/span&gt; &lt;br /&gt;   thumbnail   &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Magick&lt;/span&gt;::&lt;span class="Entity"&gt;Image&lt;/span&gt;.&lt;span class="Entity"&gt;read&lt;/span&gt;(image_path).&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;br /&gt;   cols, rows  &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; thumbnail.&lt;span class="Entity"&gt;columns&lt;/span&gt;, thumbnail.&lt;span class="Entity"&gt;rows&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;   thumbnail.&lt;span class="Entity"&gt;crop_resized!&lt;/span&gt;(&lt;span style="color: rgb(218, 73, 57);"&gt;400&lt;/span&gt;,&lt;span style="color: rgb(218, 73, 57);"&gt;300&lt;/span&gt;)&lt;br /&gt;   thumbnail[&lt;span style="color: rgb(218, 73, 57);"&gt;&lt;span style="color: rgb(218, 73, 57);"&gt;:&lt;/span&gt;caption&lt;/span&gt;] &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(165, 194, 97);"&gt;&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;&lt;span class="StringConstant"&gt;\n&lt;/span&gt;  &lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;pet&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;breed&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;animal&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;kind&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;, &lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;pet&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;breed&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;title&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;, &lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;pet&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;name&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="StringConstant"&gt;\n&lt;/span&gt;  Cost: &lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;pet&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;.&lt;/span&gt;&lt;span class="Entity"&gt;price&lt;/span&gt;&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;$&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;   thumbnail &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; thumbnail.&lt;span class="Entity"&gt;polaroid&lt;/span&gt;(&lt;span style="color: rgb(218, 73, 57);"&gt;5&lt;/span&gt; &lt;span style="color: rgb(204, 120, 51);"&gt;-&lt;/span&gt; &lt;span class="Entity"&gt;rand&lt;/span&gt;(&lt;span style="color: rgb(218, 73, 57);"&gt;10&lt;/span&gt;)) &lt;span style="color: rgb(204, 120, 51);"&gt;do &lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(208, 208, 255);"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;gravity&lt;/span&gt;      &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Magick&lt;/span&gt;::&lt;span class="Entity"&gt;CenterGravity&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(208, 208, 255);"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;shadow_color&lt;/span&gt; &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(165, 194, 97);"&gt;&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;black&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(208, 208, 255);"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;align&lt;/span&gt;        &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span class="Support"&gt;Magick&lt;/span&gt;::&lt;span class="Entity"&gt;LeftAlign&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(208, 208, 255);"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;pointsize&lt;/span&gt;    &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(218, 73, 57);"&gt;30&lt;/span&gt;&lt;br /&gt;     &lt;span style="color: rgb(208, 208, 255);"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;font_family&lt;/span&gt;  &lt;span style="color: rgb(204, 120, 51);"&gt;=&lt;/span&gt; &lt;span style="color: rgb(165, 194, 97);"&gt;&lt;span style="color: rgb(165, 194, 97);"&gt;'&lt;/span&gt;comic sans ms&lt;span style="color: rgb(165, 194, 97);"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color: rgb(204, 120, 51);"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;   thumbnail.&lt;span class="Entity"&gt;change_geometry!&lt;/span&gt;(&lt;span style="color: rgb(165, 194, 97);"&gt;&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;cols&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;x&lt;span class="StringEmbeddedSource"&gt;&lt;span class="StringEmbeddedSource"&gt;#{&lt;/span&gt;rows&lt;span class="StringEmbeddedSource"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(165, 194, 97);"&gt;"&lt;/span&gt;&lt;/span&gt;) &lt;span style="color: rgb(204, 120, 51);"&gt;do &lt;/span&gt;|&lt;span style="color: rgb(208, 208, 255);"&gt;ncols&lt;/span&gt;, &lt;span style="color: rgb(208, 208, 255);"&gt;nrows&lt;/span&gt;, &lt;span style="color: rgb(208, 208, 255);"&gt;img&lt;/span&gt;|&lt;br /&gt;     img.&lt;span class="Entity"&gt;resize!&lt;/span&gt;(ncols, nrows)&lt;br /&gt;   &lt;span style="color: rgb(204, 120, 51);"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;   thumbnail.&lt;span class="Entity"&gt;resize!&lt;/span&gt;(&lt;span style="color: rgb(218, 73, 57);"&gt;200&lt;/span&gt;,&lt;span style="color: rgb(218, 73, 57);"&gt;150&lt;/span&gt;)&lt;br /&gt;   thumbnail.&lt;span class="Entity"&gt;write&lt;/span&gt;(thumbnail_path)&lt;br /&gt; &lt;span style="color: rgb(204, 120, 51);"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;Требуется наличие RMagick.&lt;br /&gt;&lt;br /&gt;Примечание: делается двойной resize - до и после полароид-эффекта, для более четкого изображения.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-3720344263279732301?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/3720344263279732301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/3720344263279732301'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/polaroid-thumbnails.html' title='Polaroid thumbnails'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_DLkmVEXn9mk/R2Qae4cVqHI/AAAAAAAAAAU/49QMAI-eXFA/s72-c/pet-hamster.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-2246167331966557482</id><published>2007-12-15T00:59:00.000+03:00</published><updated>2007-12-15T01:29:08.280+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='yaml'/><category scheme='http://www.blogger.com/atom/ns#' term='config'/><title type='text'>YAML-конфиги</title><content type='html'>Поработав некоторое время с конфигурационным файлами в формате YAML, вы заметите, что встроенного простого метода для синхронизации изменений нет. Чтобы каждый раз не расписывать однородные конструкции для записи изменений, я написал маленькое расширение:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833"&gt;module&lt;/span&gt; &lt;span class="JEntityNameType"&gt;YAML&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.set_connection&lt;/span&gt;(&lt;span style="color:#D0D0FF"&gt;path&lt;/span&gt;)&lt;br /&gt;    data &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span class="Entity"&gt;load_file&lt;/span&gt;(path).&lt;span class="Entity"&gt;symbolize_keys&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#CC7833"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;&lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;&amp;lt;&amp;lt;&lt;/span&gt; data&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#CC7833"&gt;attr_accessor&lt;/span&gt; &lt;span style="color:#DA4939"&gt;&lt;span style="color:#DA4939"&gt;:&lt;/span&gt;path&lt;/span&gt;&lt;br /&gt;      &lt;span style="color:#CC7833"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;sync&lt;/span&gt;&lt;br /&gt;        &lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;open&lt;/span&gt;(&lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;@&lt;/span&gt;path&lt;/span&gt;, &lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;w+&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt;) { |&lt;span style="color:#D0D0FF"&gt;file&lt;/span&gt;| file.&lt;span class="Entity"&gt;puts&lt;/span&gt;(&lt;span style="color:#D0D0FF"&gt;self&lt;/span&gt;.&lt;span class="Entity"&gt;stringify_keys&lt;/span&gt;.&lt;span class="Entity"&gt;to_yaml&lt;/span&gt;) }&lt;br /&gt;      &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;    data.&lt;span class="Entity"&gt;path&lt;/span&gt; &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; path&lt;br /&gt;    data&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Заметьте, что я также автоматом применяю symbolize_keys, когда вытаскиваю данные из yaml, и stringify_keys, когда отправляю обратно изменения. Все это сделано по простой причине, что у меня на верхнем уровне конфига всегда находится хэш (со строками в качестве ключей, так как они смотрятся более органично в yaml чем символы, на моей взгляд), а в коде уже удобнее работать с символами для доступа к отдельным разделам конфига. Можно было, конечно, проверять является ли хэшем выгружаемая информация и, в случае, положительного ответа, применять эти функции, но кто захочет - сам сделает, а для моих целей этого достаточно.&lt;br /&gt;&lt;br /&gt;Пример из скрипта, который я использую для управления рейлс приложениями:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;$&lt;/span&gt;config&lt;/span&gt; &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; &lt;span style="color:#D0D0FF"&gt;YAML&lt;/span&gt;.&lt;span class="Entity"&gt;set_connection&lt;/span&gt;(&lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;config.yaml&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt;.&lt;span class="Entity"&gt;in_current_dir&lt;/span&gt;)&lt;br /&gt;&lt;span style="color:#BC9458"&gt;&lt;span style="color:#BC9458"&gt;#&lt;/span&gt;...&lt;/span&gt;&lt;br /&gt;mode &lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;config&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;&lt;br /&gt;  &lt;span class="Entity"&gt;keyword&lt;/span&gt;(&lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;repository&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt;, &lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;r&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;&lt;br /&gt;    default &lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;$&lt;/span&gt;config&lt;/span&gt;[&lt;span style="color:#DA4939"&gt;&lt;span style="color:#DA4939"&gt;:&lt;/span&gt;repository&lt;/span&gt;]&lt;br /&gt;&lt;span style="color:#BC9458"&gt;    &lt;span style="color:#BC9458"&gt;#&lt;/span&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span class="Entity"&gt;keyword&lt;/span&gt;(&lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;rails_apps&lt;span style="color:#A5C261"&gt;'&lt;/span&gt;&lt;/span&gt;) &lt;span style="color:#CC7833"&gt;do&lt;/span&gt;&lt;br /&gt;    default &lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;$&lt;/span&gt;config&lt;/span&gt;[&lt;span style="color:#DA4939"&gt;&lt;span style="color:#DA4939"&gt;:&lt;/span&gt;rails_apps&lt;/span&gt;]&lt;br /&gt;&lt;span style="color:#BC9458"&gt;    &lt;span style="color:#BC9458"&gt;#&lt;/span&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;  &lt;br /&gt;  &lt;span style="color:#CC7833"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;run&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#BC9458"&gt;    &lt;span style="color:#BC9458"&gt;#&lt;/span&gt;...&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#A5C261"&gt;&lt;span style="color:#A5C261"&gt;%w(&lt;/span&gt;repository rails_apps&lt;span style="color:#A5C261"&gt;)&lt;/span&gt;&lt;/span&gt;.&lt;span class="Entity"&gt;each&lt;/span&gt; { |&lt;span style="color:#D0D0FF"&gt;setting&lt;/span&gt;| &lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;$&lt;/span&gt;config&lt;/span&gt;[setting.&lt;span class="Entity"&gt;to_sym&lt;/span&gt;] &lt;span style="color:#CC7833"&gt;=&lt;/span&gt; params[setting].&lt;span class="Entity"&gt;value&lt;/span&gt; }&lt;br /&gt;    &lt;span style="color:#D0D0FF"&gt;&lt;span style="color:#D0D0FF"&gt;$&lt;/span&gt;config&lt;/span&gt;.&lt;span class="Entity"&gt;sync&lt;/span&gt; &lt;br /&gt;  &lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-2246167331966557482?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/2246167331966557482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/2246167331966557482'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/yaml.html' title='YAML-конфиги'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-5781920435774733577</id><published>2007-12-08T01:37:00.002+03:00</published><updated>2008-03-25T14:30:22.845+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='life'/><title type='text'>Amazing ruby</title><content type='html'>Сегодня на учебе я увидел, что мой знакомый внимательно пытается чего-то разглядеть у себя на ноуте в переменной PATH, к счастью, у него на компе находился руби (результат - предыдущих безуспешных попыток подсадить его на руби).&lt;br /&gt;&lt;br /&gt;Одна строчка в консоли:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;ruby &lt;span style="color:#CC7833;"&gt;-&lt;/span&gt;e &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;puts ENV['PATH'].split(';').sort&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;(; - так как действие проиходило в windows)&lt;br /&gt;и он обладатель читабельного приятного списка. Удивительно, но данный пример поразил его настолько, что он наконец признал, что в руби есть что-то очень хорошее =)))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Также сегодня перевел код знакомого из:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;r &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; []; a.&lt;span class="Entity"&gt;each&lt;/span&gt; { |&lt;span style="color:#D0D0FF;"&gt;x&lt;/span&gt;| b.&lt;span class="Entity"&gt;each&lt;/span&gt; { |&lt;span style="color:#D0D0FF;"&gt;y&lt;/span&gt;| r &lt;span style="color:#CC7833;"&gt;&amp;lt;&amp;lt;&lt;/span&gt; [x,y] } };&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt; в&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;(a&lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;b.&lt;span class="Entity"&gt;size&lt;/span&gt;).&lt;span class="Entity"&gt;zip&lt;/span&gt;(b&lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;a.&lt;span class="Entity"&gt;size&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Демонстрация,&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;a, b &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; [&lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;,&lt;span style="color:#DA4939;"&gt;2&lt;/span&gt;,&lt;span style="color:#DA4939;"&gt;3&lt;/span&gt;], [&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;a&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;b&lt;/span&gt;]&lt;br /&gt;p (a&lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;b.&lt;span class="Entity"&gt;size&lt;/span&gt;).&lt;span class="Entity"&gt;zip&lt;/span&gt;(b&lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;a.&lt;span class="Entity"&gt;size&lt;/span&gt;) &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; [[1, :a], [2, :b], [3, :a], [1, :b], [2, :a], [3, :b]]&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Интересно, потянет на &lt;a href="http://www.novemberain.com/tags/TiaBWTDI"&gt;http://www.novemberain.com/tags/TiaBWTDI&lt;/a&gt; ? =))&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-5781920435774733577?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5781920435774733577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5781920435774733577'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/amazing-ruby.html' title='Amazing ruby'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-2972273755382078896</id><published>2007-12-05T16:35:00.001+03:00</published><updated>2008-03-25T14:35:30.517+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='open3'/><category scheme='http://www.blogger.com/atom/ns#' term='hash'/><category scheme='http://www.blogger.com/atom/ns#' term='cmd'/><title type='text'>stderr for `cmd`</title><content type='html'>Порой, программируя на ruby, нужно получить не только стандартный вывод для консольной команды, но и перехватить сообщения об ошибках. Для этого можно прямо использовать Open3, но для простых операций можно использовать обертку:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; extensions.rb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;`&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;cmd&lt;/span&gt;)&lt;br /&gt; &lt;span class="Support"&gt;Open3&lt;/span&gt;.&lt;span class="Entity"&gt;popen3&lt;/span&gt;(cmd) &lt;span style="color:#CC7833;"&gt;do &lt;/span&gt;|&lt;span style="color:#D0D0FF;"&gt;stdin&lt;/span&gt;, &lt;span style="color:#D0D0FF;"&gt;stdout&lt;/span&gt;, &lt;span style="color:#D0D0FF;"&gt;stderr&lt;/span&gt;|&lt;br /&gt;   out, err &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; [stdout, stderr].&lt;span class="Entity"&gt;map&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;readlines&lt;/span&gt;&lt;br /&gt;   {&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;short_out&lt;/span&gt; =&amp;gt; out[&lt;span style="color:#DA4939;"&gt;0&lt;/span&gt;], &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;short_err&lt;/span&gt; =&amp;gt; err[&lt;span style="color:#DA4939;"&gt;0&lt;/span&gt;], &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;out&lt;/span&gt; =&amp;gt; out, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;err&lt;/span&gt; =&amp;gt; err, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;all&lt;/span&gt; =&amp;gt; out &lt;span style="color:#CC7833;"&gt;+&lt;/span&gt; err}&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Примечание: для того, чтобы работала сокращенная форма&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;[stdout, stderr].&lt;span class="Entity"&gt;map&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;readlines&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Необходимо, чтобы был определен метод to_proc для Symbol:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;Symbol&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;to_proc&lt;/span&gt;&lt;br /&gt;   &lt;span class="Support"&gt;Proc&lt;/span&gt;.&lt;span class="Entity"&gt;new&lt;/span&gt; { |&lt;span style="color:#D0D0FF;"&gt;obj&lt;/span&gt;, *&lt;span style="color:#D0D0FF;"&gt;args&lt;/span&gt;| obj.&lt;span class="Entity"&gt;send&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;self&lt;/span&gt;, &lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;args) }&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Теперь можно работать с консольными командами следующим образом:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;require&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;extensions&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;status &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm non-existent-file&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;p status[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;short_err&lt;/span&gt;] &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; "rm: non-existent-file: No such file or directory\n"&lt;/span&gt;&lt;br /&gt;p status[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;out&lt;/span&gt;]       &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; []&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Или сразу вытаскивать нужные потоки:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;out &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm existent-file&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;out&lt;/span&gt;]&lt;br /&gt;err &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm non-existent-file&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;err&lt;/span&gt;]&lt;br /&gt;all &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm any-file&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;all&lt;/span&gt;]&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Или, если использовать модифицированный хэш-аксессор  из предыдущего поста:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;short_out, full_out &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;ln -s&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;short_out&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;out&lt;/span&gt;]&lt;br /&gt;out, err &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm any-file&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;out&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;short_err&lt;/span&gt;]&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Также есть простой способ, с помощью которого без Open3 можно получить объединенный вывод для stderr и stdout. Для этого просто нужно указать в конце системного вызова 2&gt;&amp;amp;1 - то есть дописать в стандартный вывод все полученные сообщения об ошибках.&lt;br /&gt;Пример:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;p &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;rm non-existent-file 2&amp;gt;&amp;amp;1&lt;span style="color:#A5C261;"&gt;`&lt;/span&gt;&lt;/span&gt; &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; &amp;gt;&amp;gt; "rm: non-existent-file: No such file or directory\n"&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-2972273755382078896?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/2972273755382078896'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/2972273755382078896'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/stderr-for-cmd.html' title='stderr for `cmd`'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-5468517585704263987</id><published>2007-12-05T15:49:00.001+03:00</published><updated>2008-03-25T14:36:57.029+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='hash'/><title type='text'>Improved hash accessor</title><content type='html'>Ruby разрешает получить доступ только к одному значению хеша через []. К счастью, это легко исправить:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt;extensions.rb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;Hash&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;alias&lt;/span&gt; value_by_index []&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;[]&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;&lt;span style="color:#CC7833;"&gt;*&lt;/span&gt;keys&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color:#CC7833;"&gt;case&lt;/span&gt; (values &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; keys.&lt;span class="Entity"&gt;map&lt;/span&gt; { |&lt;span style="color:#D0D0FF;"&gt;key&lt;/span&gt;| value_by_index key }).&lt;span class="Entity"&gt;size&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833;"&gt;when&lt;/span&gt; &lt;span style="color:#DA4939;"&gt;1&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;then&lt;/span&gt; values.&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833;"&gt;when&lt;/span&gt; &lt;span style="color:#DA4939;"&gt;0&lt;/span&gt; &lt;span style="color:#CC7833;"&gt;then&lt;/span&gt; &lt;span style="color:#DA4939;"&gt;nil&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#CC7833;"&gt;else&lt;/span&gt; values &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Примеры,&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;require&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;extensions&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;hash &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; { &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;a&lt;/span&gt; =&amp;gt; &lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;b&lt;/span&gt; =&amp;gt; &lt;span style="color:#DA4939;"&gt;2&lt;/span&gt; }&lt;br /&gt;p hash[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;a&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;b&lt;/span&gt;] &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; [1, 2]&lt;/span&gt;&lt;br /&gt;p hash[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;a&lt;/span&gt;]     &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; 1&lt;/span&gt;&lt;br /&gt;p hash[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;d&lt;/span&gt;]     &lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; =&amp;gt; nil&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-5468517585704263987?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5468517585704263987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5468517585704263987'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/improved-hash-accessor.html' title='Improved hash accessor'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-5184577495111391621</id><published>2007-12-05T13:03:00.002+03:00</published><updated>2008-03-25T14:40:50.484+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='file'/><title type='text'>File helpers</title><content type='html'>Используя, fcaller из предыдущего поста, я расширил функциональность класса File удобными для меня методами:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;File&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.current_dir&lt;/span&gt;&lt;br /&gt;   &lt;span class="Entity"&gt;dirname&lt;/span&gt;(fcaller[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;])&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;self.in_current_dir&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;name&lt;/span&gt;)&lt;br /&gt;   &lt;span class="Entity"&gt;join&lt;/span&gt;(&lt;span class="Entity"&gt;dirname&lt;/span&gt;(fcaller[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;]), name)&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;class&lt;/span&gt; &lt;span class="JEntityNameType"&gt;String&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;in_current_dir&lt;/span&gt;&lt;br /&gt;   &lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;join&lt;/span&gt;(&lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;dirname&lt;/span&gt;(fcaller[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;]), &lt;span style="color:#D0D0FF;"&gt;self&lt;/span&gt;)&lt;br /&gt; &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;__DIR__&lt;/span&gt;&lt;br /&gt; &lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;dirname&lt;/span&gt;(fcaller[&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;])&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Гораздо читабельнее вместо&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;join&lt;/span&gt;(&lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;dir&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;__FILE__&lt;/span&gt;), &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;bar.rb&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;писать&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;in_current_dir&lt;/span&gt;(&lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;bar.rb&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;или&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;file.rb&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;.in_current_dir&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;И гораздо проще вместо&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span class="Support"&gt;File&lt;/span&gt;.&lt;span class="Entity"&gt;dirname&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;__FILE__&lt;/span&gt;)&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;писать&lt;br /&gt;&lt;pre style="background-color:#2B2B2B;color:#E6E1DC;padding:6px;overflow:auto;line-height:12px;font-size:12px;padding:6px;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;__DIR__&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-5184577495111391621?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5184577495111391621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/5184577495111391621'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/file-helpers.html' title='File helpers'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry><entry><id>tag:blogger.com,1999:blog-7401872276116867063.post-8920320934823949584</id><published>2007-12-05T00:42:00.001+03:00</published><updated>2008-03-25T14:43:41.763+03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel'/><category scheme='http://www.blogger.com/atom/ns#' term='caller'/><title type='text'>Pretty formatted caller</title><content type='html'>Известно, что стандартный caller в ruby возвращает инфу в некрасивом формате (eg, "prog:5:in `b'"). Но это можно исправить, написав обертку для него.&lt;div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;Работаем с ним как с обычным caller, но на выходе получаем удобноваримые результаты:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; extensions.rb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;fcallers&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;start&lt;span style="color:#CC7833;"&gt;=&lt;/span&gt;&lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt; chain &lt;span style="color:#CC7833;"&gt;=&lt;/span&gt; caller start &lt;span style="color:#CC7833;"&gt;+&lt;/span&gt; &lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;&lt;br /&gt; (chain &lt;span style="color:#CC7833;"&gt;||&lt;/span&gt; []).&lt;span class="Entity"&gt;map&lt;/span&gt; { |&lt;span style="color:#D0D0FF;"&gt;it&lt;/span&gt;|&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;if&lt;/span&gt; it[&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;(&lt;/span&gt;.*&lt;span class="StringRegexp"&gt;)&lt;/span&gt;&lt;/span&gt;:&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;(&lt;/span&gt;&lt;span class="StringRegexpSpecial"&gt;\d&lt;/span&gt;+&lt;span class="StringRegexp"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;(&lt;/span&gt;?::in `&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;(&lt;/span&gt;.+&lt;span class="StringRegexp"&gt;)&lt;/span&gt;&lt;/span&gt;'&lt;span class="StringRegexp"&gt;)&lt;/span&gt;&lt;/span&gt;?&lt;/span&gt;&lt;span class="StringRegexp"&gt;&lt;span class="StringRegexp"&gt;/&lt;/span&gt;&lt;/span&gt;]&lt;br /&gt;     {&lt;br /&gt;       &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;Regexp&lt;/span&gt;.&lt;span class="Entity"&gt;last_match&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;],&lt;br /&gt;       &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;line&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;Regexp&lt;/span&gt;.&lt;span class="Entity"&gt;last_match&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;2&lt;/span&gt;].&lt;span class="Entity"&gt;to_i&lt;/span&gt;,&lt;br /&gt;       &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;method&lt;/span&gt; =&amp;gt; &lt;span class="Support"&gt;Regexp&lt;/span&gt;.&lt;span class="Entity"&gt;last_match&lt;/span&gt;[&lt;span style="color:#DA4939;"&gt;3&lt;/span&gt;]&lt;br /&gt;     }&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;else&lt;/span&gt;&lt;br /&gt;     &lt;span style="color:#CC7833;"&gt;raise&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;Undefined format of caller&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt; }&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; foo.rb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;require&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;extensions&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;foobar&lt;/span&gt;&lt;br /&gt; p fcallers&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#BC9458;"&gt;&lt;span style="color:#BC9458;"&gt;#&lt;/span&gt; bar.rb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;require&lt;/span&gt; &lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;foo&lt;span style="color:#A5C261;"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;barfoo&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;&lt;/span&gt;) foobar &lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;barfoo&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Output:&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;[{&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;method&lt;/span&gt;=&amp;gt;&lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;barfoo&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;=&amp;gt;&lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;/Users/brainopia/ruby_apps/extensions/bar.rb&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;line&lt;/span&gt;=&amp;gt;&lt;span style="color:#DA4939;"&gt;3&lt;/span&gt;}, {&lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;method&lt;/span&gt;=&amp;gt;&lt;span style="color:#DA4939;"&gt;nil&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;file&lt;/span&gt;=&amp;gt;&lt;span style="color:#A5C261;"&gt;&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;/Users/brainopia/ruby_apps/extensions/bar.rb&lt;span style="color:#A5C261;"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span style="color:#DA4939;"&gt;&lt;span style="color:#DA4939;"&gt;:&lt;/span&gt;line&lt;/span&gt;=&amp;gt;&lt;span style="color:#DA4939;"&gt;5&lt;/span&gt;}]&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Но обычно при работе с caller нам достаточно проследить один вызов и вся цепочка нам не нужна, поэтому пишем еще маленькую обертку:&lt;br /&gt;&lt;br /&gt;&lt;pre   style="background-color:#2B2B2B;padding:6px;overflow:auto;line-height:12px;padding:6px;font-size:12px;color:#E6E1DC;"&gt;&lt;code&gt;&lt;pre class="sunburst"&gt;&lt;span style="color:#CC7833;"&gt;def&lt;/span&gt; &lt;span class="Entity"&gt;fcaller&lt;/span&gt;(&lt;span style="color:#D0D0FF;"&gt;start&lt;span style="color:#CC7833;"&gt;=&lt;/span&gt;&lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;&lt;/span&gt;)&lt;br /&gt; &lt;span class="Entity"&gt;fcallers&lt;/span&gt;(start&lt;span style="color:#CC7833;"&gt;+&lt;/span&gt;&lt;span style="color:#DA4939;"&gt;1&lt;/span&gt;).&lt;span class="Entity"&gt;first&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#CC7833;"&gt;end&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7401872276116867063-8920320934823949584?l=digging-ruby.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8920320934823949584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7401872276116867063/posts/default/8920320934823949584'/><link rel='alternate' type='text/html' href='http://digging-ruby.blogspot.com/2007/12/pretty-formatted-caller.html' title='Pretty formatted caller'/><author><name>brainopia</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.livejournal.com/userpic/54768686/11647071'/></author></entry></feed>
