<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2russianfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Блог разработчика веба</title>
	
	<link>http://rotuka.com</link>
	<description>Rotuka про Ruby on Rails и Ubuntu</description>
	<lastBuildDate>Fri, 30 Oct 2009 00:51:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<image>
  <link>http://rotuka.com</link>
  <url>http://rotuka.com/favicon.ico</url>
  <title>Блог разработчика веба</title>
</image>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/rotuka" type="application/rss+xml" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.feedburner.com/rotuka" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://lenta.yandex.ru/settings.xml?name=feed&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://lenta.yandex.ru/i/addfeed.gif">?????? ? ??????.?????</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Frotuka" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Метапрограммирование в Ruby</title>
		<link>http://rotuka.com/ruby-metaprogramming/</link>
		<comments>http://rotuka.com/ruby-metaprogramming/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 09:33:35 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Переводы]]></category>
		<category><![CDATA[metaprogramming]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=713</guid>
		<description><![CDATA[Что такое метапрограммирование?
Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime. In many cases, this allows programmers to get more done in the same amount of time as they [...]]]></description>
			<content:encoded><![CDATA[<h2>Что такое метапрограммирование?</h2>
<blockquote><p>Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually, or it gives programs greater flexibility to efficiently handle new situations without recompilation. (via Wikipedia)</p></blockquote>
<p>Это руководство перечисляет все стандартные методы Ruby, используемые для метапрограммирования, а так же приводит примеры их обычного употребления. В конце мы получим пример использования метапрограммирования для динамического создания классов, соответствующих таблицам в БД, включающих методы, соответствующие полям таблицы, на манер <code class="ruby">ActiveRecord</code>.<br />
<span id="more-713"></span></p>
<h2>Инструментарий метапрограммиста</h2>
<p>Ruby содержит множество методов для динамического создания кода. Ознакомимся с ними:</p>
<h3>Получение, установка и удаление переменных</h3>
<ul>
<li><code class="ruby">Object#instance_variable_get</code></li>
<li><code class="ruby">Object#instance_variable_set</code></li>
<li><code class="ruby">Object#remove_instance_variable</code></li>
<li><code class="ruby">Module#class_variable_get</code></li>
<li><code class="ruby">Module#class_variable_set</code></li>
<li><code class="ruby">Module#remove_class_variable</code></li>
</ul>
<h3>Получение, установка и удаление констант (и классов)</h3>
<ul>
<li><code class="ruby">Module#const_get</code></li>
<li><code class="ruby">Module#const_set</code></li>
<li><code class="ruby">Module#remove_const</code></li>
</ul>
<h3>Объявление и удаление методов</h3>
<ul>
<li><code class="ruby">Module#define_method</code></li>
<li><code class="ruby">Module#remove_method</code></li>
</ul>
<h3>Выполнение кода, построенного «на лету»</h3>
<ul>
<li><code class="ruby">Object#send</code></li>
<li><code class="ruby">Object#instance_eval</code></li>
<li><code class="ruby">Module#module_eval (синоним Module#class_eval)</code></li>
<li><code class="ruby">Kernel#eval</code></li>
<li><code class="ruby">Kernel#method_missing</code></li>
</ul>
<h3>Методы интроспекции (рефлексии, отражения)</h3>
<p>Интроспекция — важная часть метапрограммирования, позволяющая изучать объекты, получая их структуру и данные</p>
<ul>
<li><code class="ruby">Object#class</code></li>
<li><code class="ruby">Object#instance_variables</code></li>
<li><code class="ruby">Object#methods</code></li>
<li><code class="ruby">Object#private_methods</code></li>
<li><code class="ruby">Object#public_methods</code></li>
<li><code class="ruby">Object#singleton_methods</code></li>
<li><code class="ruby">Module#class_variables</code></li>
<li><code class="ruby">Module#constants</code></li>
<li><code class="ruby">Module#included_modules</code></li>
<li><code class="ruby">Module#instance_methods</code></li>
<li><code class="ruby">Module#name</code></li>
<li><code class="ruby">Module#private_instance_methods</code></li>
<li><code class="ruby">Module#protected_instance_methods</code></li>
<li><code class="ruby">Module#public_instance_methods</code></li>
</ul>
<h2>Выполнение кода в строках и блоках</h2>
<p>Вы могли слышать о методе eval, позволяющем выполнять строку или блок как код на Ruby. Когда нужно выполнить код внутри контекста какого-то объекта, можно использовать методы <code class="ruby">instance_eval</code> и <code class="ruby">module_eval</code> (синоним <code class="ruby">class_eval</code>).</p>
<p>Метод <code class="ruby">instance_eval</code> выполняет код в контексте существующего объекта.</p>
<pre><code class="ruby">[1, 2, 3, 4].instance_eval('size') # вернёт 4</code></pre>
<p>В примере мы передали методу <code>instance_eval</code> строку «size», что интерпретировалось как получение метода «size» массивом. Это эквивалентно следующему вызову:</p>
<pre><code class="ruby">[1, 2, 3, 4].size</code></pre>
<p>Кроме того, вы можете передавать методу <code>instance_eval</code> блок.</p>
<pre><code class="ruby"># Получаем среднее арифметическое чисел в массиве
[1, 2, 3, 4].instance_eval { inject(:+) / size.to_f } # вернёт 2.5</code></pre>
<p><code class="ruby">Методы inject(:+)</code>и <code class="ruby">size.to_f</code> вроде бы «висят в воздухе» и не относятся ни к какому объекту, однако они выполняются в блоке, в контексте объекта, поэтому они интерпретируются как <code class="ruby">self.inject(:+)</code> / <code class="ruby">self.size.to_f</code> где self — наш массив.</p>
<p>В то время как <code class="ruby">instance_eval</code> выполняет код в контексте объекта, метод <code class="ruby">module_eval</code> выполняет код в контексте модуля или класса.</p>
<pre><code class="ruby">Fixnum.module_eval do
  def to_word
    if (0..3).include? self
      ['ничего', 'один', 'пара', 'несколько'][self]
    elsif self &gt; 3
      'много'
    elsif self &lt; 0
      'отрицательно'
    end
  end
end
1.to_word # вернёт 'один'
2.to_word # вернёт 'пара'
</code></pre>
<p>Мы видим, как <code class="ruby">module_eval</code> заново открывает существующий класс <code class="ruby">Fixnum</code> и добавляет в него новый метод. Само по себе это не очень интересно, и мы можем сделать это иначе:</p>
<pre><code class="ruby">class Fixnum
  def to_word
    ..
  end
end</code></pre>
<p>Лучшее применение этому методу мы найдём при динамическом генерировании кода. Добавим метод <code class="ruby">create_multiplier</code>, который позволит динамически генерировать методы-умножители с теми именами, которые вы захотите.</p>
<pre><code class="ruby">class Fixnum
  def self.create_multiplier(name, num)
    module_eval "def #{name}; self * #{num}; end"
  end
end

Fixnum.create_multiplier('multiply_by_pi', Math::PI)
4.multiply_by_pi # вернёт 12.5663706143592 </code></pre>
<p>Пример выше создаёт метод класса (или  «метод-синглетон») <code class="ruby">create_multiplier</code>, с помощью которого мы сможем создавать методы, применимые к любому объекту класса <code class="ruby">Fixnum</code>.</p>
<h2>Использование <code class="ruby">send</code></h2>
<p>Метод <code class="ruby">send</code> работает почти как <code class="ruby">instance_eval</code>, поскольку вызывает метод объекта, переданный в качестве параметра. Он удобен, когда мы динамически получаем имя необходимого метода в виде строки или символа.</p>
<pre><code class="ruby">method_name = 'size'
[1, 2, 3, 4].send(method_name) # вернёт 4</code></pre>
<p>Мы можем передать имя метода в виде строки <code class="ruby">'size'</code> или символа <code class="ruby">:size</code></p>
<p>Полезное свойство метода <code class="ruby">send</code> — возможность вызывать приватные методы, как например метод <code class="ruby">Module#define_method</code>.</p>
<pre><code class="ruby">Array.define_method(:ducky) { puts 'ducky' }
# NoMethodError: private method `define_method' called for Array:Class</code></pre>
<p>Используя <code class="ruby">send</code> получаем:</p>
<pre><code class="ruby">Array.send(:define_method, :ducky) { puts 'ducky' }</code></pre>
<h2>Создание методов</h2>
<p>Как мы видим в примере выше, мы можем создавать методы классов с помощью <code class="ruby">define_method</code>.</p>
<pre><code class="ruby">class Array
  define_method(:multiply) do |arg|
    collect{|i| i * arg}
  end
end

[1, 2, 3, 4].multiply(16) # returns [16, 32, 48, 64]</code></pre>
<h2>method_missing</h2>
<p>Метод <code class="ruby">method_missing</code>, объявленный в классе, вызывается в случае получения экземпляром класса несуществующего метода. Это может быть использовано для выполнения этих отсутвующих методов, вместо отправки ошибки <code class="ruby">NoMethodError</code>.</p>
<pre><code class="ruby">class Fixnum
  def method_missing(meth)
    method_name = meth.id2name
    if method_name =~ /^multiply_by_(\d+)$/
      self * $1.to_i
    else
      raise NoMethodError, "undefined method `#{method_name}' for #{self}:#{self.class}"
    end
  end
end

16.multiply_by_64 # вернёт 1024
16.multiply_by_x # ошибка NoMethodError</code></pre>
<h2>Как работает метод <code class="ruby">attr_accessor</code>?</h2>
<p>Многие из нас используют <code class="ruby">attr_accessor</code> в классах, однако не все понимают, какую работу он за нас выполняет. <code class="ruby">attr_accessor</code> динамически генерирует <em>getter</em> и <em>setter</em> для переменной экземпляра. Давайте посмотрим на примере.</p>
<pre><code class="ruby">class Person
  attr_accessor :first_name
end

john = Person.new
john.first_name = 'John'
john.instance_variables # вернёт ["@first_name"]
john.methods.grep /first_name/ # вернёт ["first_name", "first_name="]</code></pre>
<p>Также мы видим,  что <code class="ruby">attr_accessor</code> создаёт переменную экземпляра <code class="ruby">@first_name</code> и два метода: <em>getter</em> <code>first_name</code>и <em>setter</em> <code class="ruby">first_name=</code></p>
<h3>Реализация</h3>
<p>Все классы наследуют методы <code class="ruby">Module</code>, поэтому мы поместим методы сюда.</p>
<pre><code class="ruby">class Module
  # First using define_method
  def attr1(symbol)
    instance_var = ('@' + symbol.to_s)
    define_method(symbol) { instance_variable_get(instance_var) }
    define_method(symbol.to_s + "=") { |val| instance_variable_set(instance_var, val) }
  end

  # Second using module_eval
  def attr2(symbol)
    module_eval "def #{symbol}; @#{symbol}; end"
    module_eval "def #{symbol}=(val); @#{symbol} = val; end"
  end
end

class Person
  attr1 :name
  attr2 :phone
end

person = Person.new
person.name = 'John Smith'
person.phone = '555-2344'
person # returns</code></pre>
<p><code class="ruby">define_method</code> и <code class="ruby">module_eval</code> оба вернут один и тот же результат.</p>
<h2>Пример использования: Active Record для бедных</h2>
<p>Те, кто знаком с Ruby on Rails, уже догадываются, как можно реализовать класс <code class="ruby">ActiveRecord</code>, который пройдётся по полям таблицы и добавит классу соответствующие методы <em>getter</em> и <em>setter</em> для полей таблицы.</p>
<p>Мы можем пойти дальше и динамически создать классы, соответствующие таблицам.</p>
<p>В этом примере мы создадим <code class="ruby">ActiveRecord</code> для бедных. Этот класс соединится с базой данных MySQL, создаст динамически классы, соответствующие каждой таблице, а так же наполнит эти классы методами <em>getter</em> и <em>setter</em>, соответсвующими полям таблицы.</p>
<pre><code class="ruby">require 'rubygems'
require 'mysql'

class PoorMan
  # сохраним список сгенерированных классов в переменной класса
  class &lt;&lt; self; attr_reader :generated_classes; end
  @generated_classes = []

  def initialize(attributes = nil)
    if attributes
      attributes.each_pair do |key, value|
        instance_variable_set('@' + key, value)
      end
    end
  end

  def self.connect(host, user, password, database)
    @@db = Mysql.new(host, user, password, database)

    # пройдёмся по списку таблиц и создадим классы для них
    @@db.list_tables.each do |table_name|
      class_name = table_name.split('_').collect { |word| word.capitalize }.join

      # создаём класс для таблицы, используя Module#const_set
      @generated_classes &lt;&lt; klass = Object.const_set(class_name, Class.new(PoorMan))
      klass.module_eval do
        @@fields = []
        @@table_name = table_name

        def fields; @@fields; end
      end

      # пройдёмся по списку полей таблицы и создадим методы getter и setter для них
      @@db.list_fields(table_name).fetch_fields.each do |field|
        # добавляем getter и setter
        klass.send :attr_accessor, field.name

        # добавляем имя поля в список полей
        klass.module_eval { @@fields &lt;&lt; field.name }
      end
    end
  end

  # получаем строку таблицы по идентификатору
  def self.find(id)
    result = @@db.query("select * from #{@@table_name} where id = #{id} limit 1")
    attributes = result.fetch_hash
    new(attributes) if attributes
  end

  # получаем все строки
  def self.all
    result = @@db.query("select * from #{@@table_name}")
    found = []
    while(attributes = result.fetch_hash) do
      found &lt;&lt; new(attributes)
    end
    found
  end
end

# соединяем класс PoorMan с базой данных, всё остальное он сделает самостоятельно
PoorMan::connect('host', 'user', 'password', 'database')

# печатаем список сгенерированных классов
p PoorMan::generated_classes

# получаем пользователя с идентификатором 1
user = Users.find(1)

# получаем всех пользователей
Users.all</code></pre>
<p>Оригинал статьи: <a href="http://weare.buildingsky.net/2009/08/25/rubys-metaprogramming-toolbox">Ruby’s metaprogramming toolbox</a>, автор — Corban Brook</p>
<p>Некоторые примеры могут не работать на Ruby &lt; 1.8.7</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=NBSHRmLZYRw:refZWot9N-c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=NBSHRmLZYRw:refZWot9N-c:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=NBSHRmLZYRw:refZWot9N-c:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/ruby-metaprogramming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Интеграция WYSiWYG-редактора TinyMCE в рельсовые приложения</title>
		<link>http://rotuka.com/tinymce-integration-ruby-on-rails/</link>
		<comments>http://rotuka.com/tinymce-integration-ruby-on-rails/#comments</comments>
		<pubDate>Tue, 15 Sep 2009 16:42:28 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[RubyGems]]></category>
		<category><![CDATA[TinyMCE]]></category>
		<category><![CDATA[WYSIWYG]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=793</guid>
		<description><![CDATA[Вчера закончил работу (ну, её было не очень много) по переделыванию плагина TinyMCE для рельсов в полноценный gem. Теперь редактировать текстовые данные в рельсовых приложениях ещё проще.
Достаточно вставить в environment.rb:
config.gem 'tiny_mce', :source =&#62; 'http://gemcutter.org/'
В нужный контроллер:
uses_tiny_mce :only =&#62; [:new, :create, :edit, :update]
В обёртку:
= include_tiny_mce_if_needed
А в представлении указать у нужного поля текста класс mceEditor:
- form_for @page do [...]]]></description>
			<content:encoded><![CDATA[<p>Вчера закончил работу (ну, её было не очень много) по переделыванию <a title="Плагин TinyMCE для Ruby on Rails" href="http://github.com/kete/tiny_mce">плагина TinyMCE для рельсов</a> в <a title="гем tiny_mce на GemCutter" href="http://gemcutter.org/gems/tiny_mce">полноценный gem</a>. <span style="background-color: #ffffff;">Теперь редактировать текстовые данные в рельсовых приложениях ещё проще.</span></p>
<p>Достаточно вставить в <code>environment.rb</code>:</p>
<pre><code class="ruby">config.gem 'tiny_mce', :source =&gt; 'http://gemcutter.org/'</code></pre>
<p>В нужный <em>контроллер</em>:</p>
<pre><code class="ruby">uses_tiny_mce :only =&gt; [:new, :create, :edit, :update]</code></pre>
<p>В <em>обёртку</em>:</p>
<pre><code class="ruby">= include_tiny_mce_if_needed</code></pre>
<p>А в <em>представлении</em> указать у нужного поля текста класс <code>mceEditor</code>:</p>
<pre><code class="ruby">- form_for @page do |f|
  = f.text_area :content, :class =&gt; 'mceEditor'</code></pre>
<p>После этого остановите свой проект, наберите в командной строке <code>rake gems:install</code>, запустите проект снова — файлы для TinyMCE автоматически установятся в нужное место. Если вы обновите гем (например, в связи с обновлением кода TinyMCE его авторами) — удалите <code>public/javascript/tiny_mce</code>, перезапустите приложение и новые файлы лягут в нужное место.</p>
<p>Всё, теперь пользователи вашего сайта смогут вытворять всякие ужасы с текстом, а так же рвать вашу вёрстку и делать прочие непотребности. <em>Наслаждайтесь!</em></p>
<p><strong>Ссылки проекта:</strong></p>
<ul>
<li><span style="background-color: #ffffff;"><a title="tiny_mce на ГитХабе" href="http://github.com/krasivotokak/tiny_mce">Код</a></span></li>
<li><span style="background-color: #ffffff;"><a title="tiny_mce на RDoc" href="http://rdoc.info/projects/krasivotokak/tiny_mce/">Документация</a></span></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=NY-J1yHOGYw:2H9UJS4lAwc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=NY-J1yHOGYw:2H9UJS4lAwc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=NY-J1yHOGYw:2H9UJS4lAwc:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/tinymce-integration-ruby-on-rails/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Удаление программ с помощью setup.py</title>
		<link>http://rotuka.com/setup-py-uninstall/</link>
		<comments>http://rotuka.com/setup-py-uninstall/#comments</comments>
		<pubDate>Mon, 03 Aug 2009 17:51:49 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Памятки]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[checkinstall]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[setup.py]]></category>
		<category><![CDATA[uninstall]]></category>
		<category><![CDATA[памятка]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=583</guid>
		<description><![CDATA[Некоторые программы написанные на Питоне (например, Lekhonee) поставляются с файликом setup.py, с помощью которого довольно просто устанавливаются
python setup.py build
sudo python setup.py install
А вот удалить такую программу достаточно сложно, ибо команды sudo python setup.py uninstall нету. Ну, не предусмотрели его любители красивого кода на питоне. Красивое, ведь, лучше, чем некрасивое, ага? А код на Питоне, видимо, [...]]]></description>
			<content:encoded><![CDATA[<p>Некоторые программы написанные на Питоне (например, <a href="https://fedorahosted.org/lekhonee/">Lekhonee</a>) поставляются с файликом <a title="The Setup Script" href="http://docs.python.org/distutils/setupscript.html">setup.py</a>, с помощью которого довольно просто устанавливаются</p>
<pre><code class="bash">python setup.py build
sudo python setup.py install</code></pre>
<p>А вот удалить такую программу достаточно сложно, ибо команды <code class="bash">sudo python setup.py uninstall</code> нету. Ну, не предусмотрели его любители красивого кода на питоне. Красивое, ведь, лучше, чем некрасивое, ага? А код на Питоне, видимо, настолько красивый, что удалять его со своего компьютера — грех смертный.</p>
<p>Тем не менее, способ удаления таких программ есть, и он довольно прост:</p>
<pre><code class="bash">sudo python setup.py install --record files.txt
cat files.txt | sudo xargs rm -rf
</code></pre>
<p>На самом деле, неприятно удивляет это питоновское стандартное средство установки программ. Но, оказывается, бывает и такое.</p>
<h2>А если подумать перед установкой…</h2>
<p>…то можно использовать уже упоминавшийся в блоге checkinstall:</p>
<pre><code class="bash">sudo checkinstall python setup.py install</code></pre>
<p>Тогда деинсталлировать это приложение можно будет как обычно, с помощью apt:</p>
<pre><code class="bash">sudo apt-get purge lekhonee</code></pre>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=EGK9y0Xa7fg:A_2fdkhYm6A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=EGK9y0Xa7fg:A_2fdkhYm6A:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=EGK9y0Xa7fg:A_2fdkhYm6A:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/setup-py-uninstall/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Сколько стоит Ubuntu?</title>
		<link>http://rotuka.com/ubuntu-price/</link>
		<comments>http://rotuka.com/ubuntu-price/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 00:15:16 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[GIMP]]></category>
		<category><![CDATA[iLife]]></category>
		<category><![CDATA[Inkscape]]></category>
		<category><![CDATA[iWord]]></category>
		<category><![CDATA[KOffice]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Microsoft Office]]></category>
		<category><![CDATA[OpenOffice]]></category>
		<category><![CDATA[PhotoShop]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=223</guid>
		<description><![CDATA[Да, я знаю что Ubuntu распространяется бесплатно. Сегодня меня заинтересовало другое. Сколько стоила бы аналогичная система, построенная из платных аналогов.
Посмотрим, что мы получаем в комплекте с Ubuntu:

операционную систему на базе ядра GNU/Linux;
приятную, расширяемую и настраиваемую графическую оболочку;
набор Офисных приложений:

редактор текстов (который в платных аналогах любят называть текстовым процессором);
приложение электронных таблиц;
редактор презентаций;
мощное приложение для ведения переписки, [...]]]></description>
			<content:encoded><![CDATA[<p>Да, я знаю что Ubuntu распространяется бесплатно. Сегодня меня заинтересовало другое. Сколько стоила бы аналогичная система, построенная из платных аналогов.</p>
<p>Посмотрим, что мы получаем в комплекте с Ubuntu:</p>
<ul>
<li>операционную систему на базе ядра GNU/Linux;</li>
<li>приятную, расширяемую и настраиваемую графическую оболочку;</li>
<li>набор Офисных приложений:
<ul>
<li>редактор текстов (который в платных аналогах любят называть текстовым процессором);</li>
<li>приложение электронных таблиц;</li>
<li>редактор презентаций;</li>
<li>мощное приложение для ведения переписки, календаря и заметок + ещё одно, исключительно для заметок но более удобное;</li>
</ul>
</li>
<li>два графических редактора: растровый и векторный;</li>
<li>кучу игрушек и прочих приятных мелочей.</li>
</ul>
<p>Внушительный список, не правда ли? Сколько вы готовы заплатить за такой набор? А теперь посчитаем, что нам предлагают производители коммерческого <abbr title="программного обеспечения">ПО</abbr>:</p>
<table border="0">
<thead>
<tr>
<th>Категория ПО</th>
<th colspan="2">Ubuntu</th>
<th colspan="2">Windows</th>
<th colspan="2">Mac OS X</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Итого:</th>
<td colspan="2">0</td>
<td colspan="2">1687,45 $</td>
<td colspan="2">1506 $</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Ядро системы</td>
<td>GNU/Linux</td>
<td>0</td>
<td>Windows Vista Home Premium</td>
<td>239.95 $<sup><a id="win_price_holder" href="#microsoft_price">1</a></sup></td>
<td>Mac OS X 1.5.6</td>
<td>129 $</td>
</tr>
<tr class="even">
<td>Офисный пакет</td>
<td>OpenOffice, Evolution или KOffice, Kontact</td>
<td>0, 0</td>
<td>Office Home and Student 2007</td>
<td>149,95 $<sup><a id="office_price_holder" href="#microsoft_price">2</a></sup></td>
<td>iWork 09</td>
<td>79 $</td>
</tr>
<tr>
<td>Растровый графический редактор</td>
<td>GIMP или Krita (из KOffice)</td>
<td>0, 0</td>
<td>Adobe Photoshop CS4</td>
<td>699 $</td>
<td>Adobe Photoshop CS4</td>
<td>699 $</td>
</tr>
<tr class="even">
<td>Векторный графический редактор</td>
<td>Draw (из OpenOffice), Inkscape или Karbon (из KOffice)</td>
<td>0, 0</td>
<td>Adobe Illustrator CS4</td>
<td>599 $</td>
<td>Adobe Illustrator CS4</td>
<td>599 $</td>
</tr>
</tbody>
</table>
<p>Берём среднее арифметическое от стоимости комплектов под Windows и Mac OS X и получаем 1596,725 $. Можно сколько угодно говорить о неточном соответствии возможностей тех или иных программ, представленных в сравнении, однако потребности большинства пользователей «ВКонтакте» и «Одноклассников» Ubuntu легко покрывает. У меня нету лишних полутора тысяч долларов, которые я отдал бы за ту толику функциональности, которая не предоставлена бесплатными аналогами. А вы?</p>
<h2>Примечания:</h2>
<ol>
<li id="microsoft_price">На русском сайте корпорации Microsoft найти цену на какие-либо продукты <em>нереально</em>! <a href="#win_price_holder">↑1</a> <a href="#office_price_holder">↑2</a></li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=oiWcUkpTIkI:tnYlpvvksiY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=oiWcUkpTIkI:tnYlpvvksiY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=oiWcUkpTIkI:tnYlpvvksiY:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/ubuntu-price/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>rotuka @ Ubuntu Russian Translators</title>
		<link>http://rotuka.com/rotuka-ubuntu-russian-translators/</link>
		<comments>http://rotuka.com/rotuka-ubuntu-russian-translators/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 14:26:48 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu на Нетбуке]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Ubuntu Loco Team]]></category>
		<category><![CDATA[русский язык]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=144</guid>
		<description><![CDATA[Сегодня пришло письмо, что меня утвердили в группе переводчиков Ubuntu на русский. Приятно.
И я даже отличился в свежевыходящем Зайцелопе. В апплете-индикаторе новых сообщений я указан, как один из переводчиков.
]]></description>
			<content:encoded><![CDATA[<p>Сегодня пришло письмо, что <a href="http://launchpad.net/~rotuka">меня</a> утвердили в <a href="https://launchpad.net/~ubuntu-l10n-ru">группе переводчиков Ubuntu на русский</a>. Приятно.</p>
<p>И я даже отличился в свежевыходящем Зайцелопе. В апплете-индикаторе новых сообщений я указан, как один из переводчиков.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=pKbFLgZLLWA:LORzOct2Hyw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=pKbFLgZLLWA:LORzOct2Hyw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=pKbFLgZLLWA:LORzOct2Hyw:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/rotuka-ubuntu-russian-translators/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Совместное использование Cucumber и Factory_Girl или роковая ошибка create_time_zone_conversion_attribute?</title>
		<link>http://rotuka.com/using-cucumber-with-fatory_girl-or-create_time_zone_conversion_attribute-epic-fail/</link>
		<comments>http://rotuka.com/using-cucumber-with-fatory_girl-or-create_time_zone_conversion_attribute-epic-fail/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 02:37:12 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[factory_girl]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=126</guid>
		<description><![CDATA[Недавно открыл для себя Cucumber — утилиту для описания поведения вашего приложения. Весьма хорошая штука, доложу вам. Но о ней конкретно я расскажу как-нибудь потом.
Ещё я использую вместо стендовых данных (известных также как fixtures) замечательный гем от ThoughtBot под названием Factory Girl — он позволяет делать «заготовки» моделей и ваще очень крут (о нём — [...]]]></description>
			<content:encoded><![CDATA[<p>Недавно открыл для себя <a title="Cucumber — making BDD fun!" href="http://cukes.info/">Cucumber</a> — утилиту для описания поведения вашего приложения. Весьма хорошая штука, доложу вам. Но о ней конкретно я расскажу как-нибудь потом.</p>
<p>Ещё я использую вместо стендовых данных (известных также как fixtures) замечательный гем от <a href="http://thoughtbot.com/">ThoughtBot</a> под названием <a href="http://thoughtbot.com/projects/factory_girl">Factory Girl</a> — он позволяет делать «заготовки» моделей и ваще очень крут (о нём — как вы, может быть, уже догадались — тоже в другой раз).</p>
<p>Но вот соединить их при тестировании одного проекта оказалось не так-то просто! При тестировании функционала каждый сценарий, начиная со второго использования метода Factory.create вылетал с ошибкой. Как показал бэктрэйс — ошибка случалась в функции ActiveRecord::Base.create_time_zone_conversion_attribute? Гугл рассказал мне, что разработчики рельсов <a href="https://rails.lighthouseapp.com/projects/8994/tickets/785-caching-models-fails-in-development">решают эту проблему</a> уже <a href="https://rails.lighthouseapp.com/projects/8994/tickets/1339">очень долго</a>, и хотя <a href="https://rails.lighthouseapp.com/attachments/60054/prevent_class_method_and_variable_nukeing_on_AR_reset_subclasses.diff">патч, решающий её</a>, давно найден — всё никак не вольют его в основной код. И на то есть веские причины, а именно — утечка <del>мозгов</del> <ins>памяти</ins> в production-режиме.</p>
<p>Тем не менее, при тестировании функционала эта утечка памяти не так критична, потому как тестовый сервер Cucumber&#8217;а запускается и останавливается регулярно — при каждом прогоне, а сервер приложения висит довольно долго и может отъесть довольно большой кусок памяти и подавиться им. Ну, надоели вступительные слова, вот…</p>
<h2>…решение проблемы:</h2>
<p>Необходимо поместить в директорию <code>lib</code> файл <code>activerecord_reset_sublass_fix.rb</code>, а так же добавить его вызов в файл <code>config/environments/test.rb</code> <a title="fix for create_time_zone_conversion_attribute? problem" href="http://gist.github.com/88826">следующим образом</a>:<br />
<script src="http://gist.github.com/88826.js" type="text/javascript"></script></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/rotuka?a=gHJrXVUEHqE:-Vq6Sk2S2nw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/rotuka?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/rotuka?a=gHJrXVUEHqE:-Vq6Sk2S2nw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/rotuka?i=gHJrXVUEHqE:-Vq6Sk2S2nw:D7DqB2pKExk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/using-cucumber-with-fatory_girl-or-create_time_zone_conversion_attribute-epic-fail/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ubuntu + Compiz — удобно и красиво!</title>
		<link>http://rotuka.com/ubuntu-compiz/</link>
		<comments>http://rotuka.com/ubuntu-compiz/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 00:59:55 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Compiz Fusion]]></category>
		<category><![CDATA[удобство]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=84</guid>
		<description><![CDATA[Очень давно не писал в блог. Сегодня взглянул в очередной раз на черновики и решил, что буду их выкладывать потихоньку. Ну и что, что недописано (и вообще, пора менять слова «компиз фьюжн» на просто «компиз»). Будет рассказ по-частям :-)
Расскажу о композитном менеджере окон Compiz Fusion. Его историю можете прочитать на сайте проекта, а меня интересует конкретно его применение.
 
Для начала, разберёмся, что же это вообще такое? Компиз — это менеджер [...]]]></description>
			<content:encoded><![CDATA[<p>Очень давно не писал в блог. Сегодня взглянул в очередной раз на черновики и решил, что буду их выкладывать потихоньку. Ну и что, что недописано (и вообще, пора менять слова «компиз фьюжн» на просто «компиз»). Будет рассказ по-частям :-)</p>
<p>Расскажу о композитном менеджере окон <a title="Compiz Fusion" href="http://compiz-fusion.org/">Compiz Fusion</a>. Его историю можете прочитать на сайте проекта, а меня интересует конкретно его применение.</p>
<p><span id="more-84"></span> </p>
<p>Для начала, разберёмся, что же это вообще такое? Компиз — это менеджер окон, использующий для отрисовки OpenGL и повзоляющий производить над окнами всякие визуальные преобразования. За <a title="Compiz Fusion Wiki" href="http://wiki.compiz-fusion.org/">кратким обзором и скриншотами</a> опять отправляю на сайт проекта. А с теми, кого скриншоты уже порадовали, приступим к установке:</p>
<pre lang="bash">sudo apt-get update
sudo apt-get install compiz compizconfig-settings-manager simple-ccsm emerald fusion-icon</pre>
<p>После того, как всё установится, необходимо запустить Fusion Icon (Приложения -&gt; Системные -&gt; Compiz Fusion Icon). В вашем системном лотке (трее) появится иконка с логотипом Compiz Fusion (эдакий синенький кубик со стрелочкой). По нажатию на нём правой кнопкой выпадает менюшка, из которой вы можете выбрать менеджер окон (Select Window Manager), декоратор (Select Window Decorator), а так же быстро перезагрузить менеджер окон, изменить несколько параметров прямо из меню, либо открыть менеджер настроек Compiz Fusion (и офигеть от их обилия (-; ), а так же открыть менеджер тем Emerald. Советую сразу добавить это приложение в автозапуск (Система -&gt; Параметры -&gt; Сеансы -&gt; Добавить; Имя: Compiz Fusion Icon, Команда: fusion-icon, Комментарий: иконка для запуска и управления Compiz Fusion). Теперь, выбирайте менеджер окон Compiz и декоратор Emerald и мы быстро пробежимся по появившимся у вас возможностям. Кстати, когда вы впервые выберете Compiz в качестве менеджера, экран меркнёт и появится окошко с предложением сохранить настройки, но без&#8230; заголовка и кнопок закрытия. Не пугайтесь, согласитесь, оно хорошее (-; Заголовок появится буквально через пару-тройку секунд и останется с вами надолго (-;</p>
<h2>С первого взгляда&#8230;</h2>
<ul>
<li>&#8230;мы увидим, что у панелей появились тени. Ну, это конечно круто, но не сильно увеличивает удобство пользования системой, да?</li>
<li>Тогда нажмите на <strong>Alt+Tab</strong> и вы увидите, что стандартное переключение приложений заменено на новый, красивый, улучшенный переключатель, изображающий превьюшки запущенных приложений. Вы можете перематывать его и вперёд и назад (если нажимать <strong>Alt+Shift+Tab</strong> [Внимание!!! Данное утверждение верно в том, случае, если у вас не заняты системой кнопкосочетания <strong>Alt+Shift</strong> либо <strong>Shift+Tab</strong>]).<br />
<img class="size-medium wp-image-139 alignnone" title="Переключатель приложений показывает уменьшенные окна приложений" src="http://rotuka.com/wp-content/uploads/2009/04/application-switcher-300x135.png" alt="Показывает уменьшенное окно приложения" width="300" height="135" /><br />
Кстати, если вы хотите пролистывать в переключателе также приложения, открытые на других ваших рабочих местах, добавьте <strong>Ctrl</strong> к описанным выше клавишам. Что же ещё интересного появилось у вас?</li>
<li>Попробуйте нажать <strong>Alt+Ctrl+→</strong> или <strong>Alt+Ctrl+←</strong> и снова будете приятно удивлены (-: Переход на другое рабочее место будет очень плавным и симпатичным. Кроме того, вы можете одновременно переходить на другое рабочее место и тащить за собой туда же окно приложения, активное в данный момент. Для этого стоит всего-лишь зажать ещё и кнопку Shift (т. е. получится <strong>Shift+Alt+Ctrl+→</strong> или <strong>Shift+</strong><strong>Alt+Ctrl+←</strong>). Остальные окна при этом останутся на своих местах. Если вам удобнее управляться с окнами мышкой (поначалу, у всех так, со временем вы можете изменить своё мнение), просто тащите окошко к правому краю экрана, и когда оно окажется за краем больше, чем наполовину, рабочая область сдвинется вправо, вслед за вашим окном.</li>
<li>Продолжим далее. Допустим, мы поработали в нескольких приложениях на разных рабочих местах, и забыли, где же конкретно открыто окно&#8230; скажем, Пиджина. Стоит нажать <strong><abbr title="Если кто не знал, так линуксоиды называют кнопочку Win (с таким корявым окошком)">Super</abbr>+e</strong> и ваше рабочее место отодвинется вглубь монитора так, что вы сможете увидеть сразу все рабочие места. Вы даже сможете передвигать окна между ними. Не верите? Просто попробуйте! (-;<br />
<img class="size-medium wp-image-140 alignnone" title="Экспозиция отображает открытые приложения на всех рабочих местах" src="http://rotuka.com/wp-content/uploads/2009/04/expo-300x187.png" alt="Открытые приложения на всех рабочих местах" width="300" height="187" /><br />
Чтобы вернуться к какому-либо рабочему месту, вам нужно всего лишь щёлкнуть по нему мышкой. Или прокрутить скролл, пока оно не окажется подсвеченным. Или выбрать стрелочками. Чтобы вернуться на старое рабочее место, можете нажать Esc или щёлкнуть правой кнопкой мыши.</li>
<li>Есть и другой способ быстро найти окно — нажать <strong>Shift+Alt+↑</strong>. При этом, на экране появятся все открытые вами окна, разбросанные мозайкой по всех поверхности экрана. Стрелками или мышкой вы можете выбрать любое из этих окон и после этого отпустить <strong>Shift+Alt</strong>.<br />
<img class="size-medium wp-image-141 alignnone" title="Окна всех запущенных приложений" src="http://rotuka.com/wp-content/uploads/2009/04/scale-300x187.png" alt="Окна всех запущенных приложений" width="300" height="187" /></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/rotuka?a=pkj0DEW9"><img src="http://feeds.feedburner.com/~f/rotuka?d=41" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/rotuka?a=R9Z3xgP9"><img src="http://feeds.feedburner.com/~f/rotuka?i=R9Z3xgP9" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/ubuntu-compiz/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Сборка приложений из исходного кода в Ubuntu</title>
		<link>http://rotuka.com/sborka-prilozheniy-iz-iskhodnogo-koda-v-ubuntu/</link>
		<comments>http://rotuka.com/sborka-prilozheniy-iz-iskhodnogo-koda-v-ubuntu/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 02:26:21 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[auto-apt]]></category>
		<category><![CDATA[checkinstall]]></category>
		<category><![CDATA[configure]]></category>
		<category><![CDATA[make]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=105</guid>
		<description><![CDATA[Вообще, в производных от Debian системах, в число которых входит и Ubuntu, не принято собирать приложения из исходных кодов. Этого, зачастую, можно избежать, потому как в репозиториях полно различных приложений, на все случаи жизни. По некоторым сведениям, их больше, чем во всех остальных распространённых дистрибутивах линукса.
Два простых пути для установки приложений из меню, мышкой:

Приложения → [...]]]></description>
			<content:encoded><![CDATA[<p>Вообще, в производных от Debian системах, в число которых входит и Ubuntu, не принято собирать приложения из исходных кодов. Этого, зачастую, можно избежать, потому как в репозиториях полно различных приложений, на все случаи жизни. По некоторым сведениям, их больше, чем во всех остальных распространённых дистрибутивах линукса.</p>
<p>Два простых пути для установки приложений из меню, мышкой:</p>
<ul>
<li><strong>Приложения</strong> → <strong>Установка/удаление…</strong></li>
<li><strong>Система</strong> → <strong>Админинстрирование</strong> → <strong>Программа управления пакетами Synaptic</strong></li>
</ul>
<p>В первом интерфейсе все приложения снабжены своей иконкой, а так же небольшим сопроводительным текстом-описанием и рейтингом (статистика собирается анонимно со всех пользователей, которые разрешили использовать их данные). Во втором интерфейсе есть <strong>абсолютно все</strong> пакеты, однако в нём проще запутаться и поставить или удалить не то, что требуется.</p>
<p>Однако, бывают случаи, когда необходимое вам приложение отсутствует в репозитории, например потому, что оно ещё не стабильно, либо распространяется <strong>только</strong> в исходных кодах, либо его написал ваш сосед-программист, ну или по какой-то другой причине. Тогда придётся собирать его из исходников. Если вы обратитесь к любому руководству по сборке приложений, вы увидите три строки, известных (почти) любому пользователю линукса со стажем более полугода. А именно:</p>
<pre lang="bash">./configure
make
sudo make install</pre>
<p>Кратко о каждой из этих команд</p>
<h2>./configure</h2>
<p>Эта команда подготавливает исходные коды к компиляции под конкретную платформу, а именно в вашей операционной системе. Она проверяет налицие необходимых программ (компиляторов, сборщиков и т. п.), библиотек, а так же заголовочных файлов (something.h). Достаточно часто случается, что в вашей системе недостаёт какого-нибудь необходимого приложения, либо файла заголовков, необходимого для компиляции программы. В таком случае, эта команда выведет сообщение об ошибке. Если у вас достаточный опыт, то вы, конечно же, легко определите, что заголовочный файл some_extra_thing.h находится в пакете extra_things_for_cool_nerds-dev, однако не всегда просто определить, что именно хочет от вас программа, чего ей не хватает.</p>
<p>Тогда нам на помощь придёт утилита под названием <a href="apt://auto-apt"><strong>auto-apt</strong></a>. Она хранит информацию о заголовочных файлах, которые имеются в репозиториях и поможет вам найти, в каком пакете хранится тот или иной заголовочный файл.</p>
<p>Если ./configure вывела вам сообщение о недостаче заголовочного файла <em>Xlib.h</em>, воспользуйтесь командой</p>
<pre lang="bash">auto-apt search Xlib.h</pre>
<p>Она ответит вам следующим:</p>
<pre lang="bash">usr/include/X11/Xlib.h	libdevel/libx11-dev</pre>
<p>Это обозначает, что нужный вам файл содержится в пакете libx11-dev, относящемся к категории libdevel (пакеты для разработки) и после установки пакета (<strong>sudo apt-get install libx11-dev</strong>) будет лежать по адресу usr/include/X11/Xlib.h</p>
<p>Есть ещё более простой путь вызова ./configure, который сам предложит вам установить все необходимые пакеты</p>
<pre lang="bash">auto-apt run ./configure</pre>
<p>Вам нужно будет только следить за процессом установки и изредка нажимать <strong>Y</strong> для установки необходимых пакетов.</p>
<h2>make</h2>
<p>Это вторая и, пожалуй, главная команда из этой триады. Она выполняет компиляцию и сборку всех необходимых компонентов системы. Если ошибка появляется во время выполнения этой команды, скорее всего ошибка в коде, который вы пытаетесь собрать. В таком случае, остаётся только обратиться к разработчику программы. Но обычно, после успешного выполнения ./configure, здесь ошибок не бывает.</p>
<h2>make install</h2>
<p>Этой командой вы устанавливаете приложение. Если вы хотите установить её для всех пользователей, общесистемно, вам необходимы права пользователя <strong>root</strong>. В Ubuntu это решается вызовом этой команды после <strong>sudo</strong>, то есть</p>
<pre lang="bash">sudo make install</pre>
<p><strong>НО! При установке этим путём, вы можете нарушить целостность системы, поскольку эта команда не сохранит данные о том, какие файлы и куда были установлены.</strong> Таким образом, удаление этой программы сможет принести вам много мороки. Чтобы облегчить возможноые страдания, была написана утилита под названием <a href="apt://checkinstall"><strong>checkinstall</strong></a>. Она проверяет, что и как хочет сделать команда <strong>make install</strong>, а потом собирает по полученным сведениям deb-пакет и устанавливает его в систему (то есть, для удачного выполнения этой команды ей так же нужны права суперпользователя). Благодаря этому, вы сможете потом легко удалить ненужное вам более приложение, используя например Synaptic, упоминавшийся в начале статьи.</p>
<h2>Установка программ в пользовательский каталог</h2>
<p>Бывает, что некоторые программы не нужны общесистемно, тогда нужно на этапе конфигурирования указать, что программа будет устанавливаться в пользовательский (или иной) каталог. Для этого, обычно, первая команда видоизменяется следующим образом:</p>
<pre lang="bash">./configure --prefix=/home/$USER</pre>
<p>Тогда команду <strong>make install</strong> нужно вызывать без префикса <strong>sudo</strong>.</p>
<h2>Выводы</h2>
<p>Для упрощения установки программы из исходных кодов, в Ubuntu вы можете воспользоваться немного изменённым набором команд:</p>
<pre lang="bash">auto-apt run ./configure
make
sudo checkinstall</pre>
<p>для установки общесистемной, либо:</p>
<pre lang="bash">auto-apt run ./configure --prefix=/home/$USER
make
make install</pre>
<p>для установки в пользовательский каталог.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/rotuka?a=JUj1kjJq"><img src="http://feeds.feedburner.com/~f/rotuka?d=41" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/rotuka?a=kXSPPjuF"><img src="http://feeds.feedburner.com/~f/rotuka?i=kXSPPjuF" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/sborka-prilozheniy-iz-iskhodnogo-koda-v-ubuntu/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Разработка сайтов в Ubuntu или LAMP = Ubuntu + Apache + MySQL + PHP</title>
		<link>http://rotuka.com/lamp-ubuntu-apache-mysql-php/</link>
		<comments>http://rotuka.com/lamp-ubuntu-apache-mysql-php/#comments</comments>
		<pubDate>Sun, 19 Oct 2008 07:20:02 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=92</guid>
		<description><![CDATA[Ubuntu &#8211; это линукс для людей. Поэтому, установка набора для веб-разработчика в нём производится одной командой:
sudo tasksel install lamp-server
После её выполнения, на вашем компьютере обоснуются Apache, MySQL и PHP. А мы сразу же займёмся созданием первого сайта.
Все сайты, над которыми тружусь, я храню в папках вида ~/Sites/www.example.com.dev/. Это удобно, потому как не приходится настраивать права [...]]]></description>
			<content:encoded><![CDATA[<p>Ubuntu &#8211; это линукс для людей. Поэтому, установка набора для веб-разработчика в нём производится одной командой:</p>
<pre><code class="bash">sudo tasksel install lamp-server</code></pre>
<p>После её выполнения, на вашем компьютере обоснуются Apache, MySQL и PHP. А мы сразу же займёмся созданием первого сайта.</p>
<p>Все сайты, над которыми тружусь, я храню в папках вида <code>~/Sites/www.example.com.dev/</code>. Это удобно, потому как не приходится настраивать права доступа к файлам и придумывать структуру папок в <code>/var/www/</code>, а так же каждому из них можно выделить человекочитаемое имя, оканчивающееся на .dev (которое соответствует названию папки), и при разработке и тестировании набирать в адресной строке браузера www.rotuka.com.dev и попадать на локальную версию вашего сайта.</p>
<h2>Создание и настройка текстового сайта</h2>
<p>Допустим, мы приступаем к разработке сайта <a title="Блог разработчика веба" href="http://rotuka.com/">rotuka.com</a>, тогда создадим для него личную папку</p>
<pre><code class="bash">mkdir -p ~/Sites/rotuka.com.dev/public</code></pre>
<p>Теперь, нам нужно рассказать нашему локальному апачу об этом сайте. Создаём файлик для этого сайта:</p>
<pre><code class="bash">sudo gedit /etc/apache2/sites-available/rotuka.com.dev</code></pre>
<p>и вписываем в него следующие строки:</p>
<pre><code>&lt;VirtualHost *:80&gt;
    ServerName rotuka.com.dev
    ServerAlias www.rotuka.com.dev
    DocumentRoot /home/$USER/Sites/rotuka.com.dev/public
&lt;/VirtualHost&gt;</code></pre>
<p>где <code>$USER</code> нужно заменить на ваше имя пользователя.</p>
<p>Сохраняем файл, закрываем gedit и говорим апачу, что этот сайт теперь нужно обслуживать:</p>
<pre><code class="bash">sudo a2ensite rotuka.com.dev</code></pre>
<p>При выполнении, эта команда скажет вам, что апачу необходимо перезагрузить данные конфигурации, что мы и сделаем:</p>
<pre><code class="bash">sudo /etc/init.d/apache2 reload</code></pre>
<p>Теперь, настроим удобное обращение к сайту. Для этого пропишем, что хост rotuka.com.dev обслуживается на нашем компьютере, локально. Открываем файл <code>/etc/hosts</code></p>
<pre><code class="bash">sudo gedit /etc/hosts</code></pre>
<p>находим там строку, начинающуюся на 127.0.0.1 (обычно, это первая строка) и вписываем в её конец, через пробел от предыдущих данных, <code>rotuka.com.dev</code>. Сохраняем файл, закрываем редактор.</p>
<p>Теперь кидаем какой-нибудь файлик index.html в папочку нашего сайта (<code>/home/$USER/Sites/www.rotuka.com.dev/public</code>) или выполняем команду</p>
<pre><code class="bash">echo -e "&lt;html&gt;\n  &lt;head&gt;\n    &lt;meta http-equiv="Content-type" content="text/html;
charset=utf-8" /&gt;\n    &lt;title&gt;Тестовый сайт&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n
&lt;h1&gt;Тестовый сайт&lt;/h1&gt;\n    &lt;p&gt;Привет, веб-разработчик&lt;/p&gt;\n  &lt;/body&gt;\n&lt;/html&gt;\n"
&gt; /home/$USER/Sites/rotuka.com.dev/index.html</code></pre>
<p>Всё, теперь уже можно вписать в адресную строку браузера http://rotuka.com.dev/ и увидеть, что сайт вас приветствует (-:</p>
<h2>Ссылки по-теме:</h2>
<ul>
<li><a href="http://www.tux.in.ua/articles/1169">Пошаговое руководство по установке LAMP сервера в Ubuntu</a> — очень подробно, с нюансами конфигурации</li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/rotuka?a=xr2JkqRa"><img src="http://feeds.feedburner.com/~f/rotuka?d=41" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/rotuka?a=phgGaPLk"><img src="http://feeds.feedburner.com/~f/rotuka?i=phgGaPLk" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/lamp-ubuntu-apache-mysql-php/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Wacom Bamboo One + Ubuntu. Установка и решение проблем</title>
		<link>http://rotuka.com/wacom-bamboo-one-ubuntu-ustanovka-i-reshenie-problem/</link>
		<comments>http://rotuka.com/wacom-bamboo-one-ubuntu-ustanovka-i-reshenie-problem/#comments</comments>
		<pubDate>Sun, 05 Oct 2008 18:04:36 +0000</pubDate>
		<dc:creator>Александр Семёнов</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Wacom Bamboo One]]></category>

		<guid isPermaLink="false">http://rotuka.com/?p=74</guid>
		<description><![CDATA[Вчера мне в руки попал планшетик Wacom Bamboo One. Забавная вещица. Если её установить (-;
Страница руководства, посвящённая Wacom посылает нас на довольно подробное руководство по установке и настройке последних драйверов для линейки Bamboo, которое приведёт вас к вполне рабочему тандему Бамбук+Убунту, однако если вы используете терминал, либо постраничный поиск в файрфоксе, либо вы просто любите [...]]]></description>
			<content:encoded><![CDATA[<p>Вчера мне в руки попал планшетик <a title="Wacom Bamboo One" href="http://www.wacom.ru/bamboo_one.html">Wacom Bamboo One</a>. Забавная вещица. Если её установить (-;</p>
<p><a title="Wacom in Ubuntu" href="https://help.ubuntu.com/community/Wacom">Страница руководства</a>, посвящённая Wacom посылает нас на довольно <a href="http://ubuntuforums.org/showthread.php?t=765915">подробное руководство по установке и настройке</a> последних драйверов для линейки Bamboo, которое приведёт вас к вполне рабочему тандему Бамбук+Убунту, однако если вы используете терминал, либо постраничный поиск в файрфоксе, либо вы просто любите системный звук ошибки &#8211; вы получите много проблем. Ибо теперь каждый вызов системного сигнала будет приводить к перезагрузке <a href="http://x.org/">иксов</a>.</p>
<p>Решения этой проблемы гугл не знает. Яндекс, кстати, тоже. И лишь кустарные методы позволят использовать. Чтобы лишить себя проблем (хотя бы временно), выполните следующие действия:</p>
<ol>
<li>Откройте настройку звука (<strong>Система</strong> -&gt; <strong>Параметры</strong> -&gt; <strong>Звук</strong>) и на вкладе &laquo;<strong>Системный сигнал</strong>&raquo; снимите галочку с параметра &laquo;<strong>Включить системный сигнал</strong>&raquo; и поставьте галочку &laquo;<strong>Визуальный системный сигнал</strong>&laquo;, чтобы вместо звука сигнал был произведён путём мигания какой-либо области экрана.</li>
<li>Запустите терминал (<strong>Приложения</strong> -&gt; <strong>Стандартные</strong> -&gt; <strong>Терминал</strong>), выберите в меню <strong>Правка</strong> -&gt; <strong>Текущий профиль&#8230;</strong> и снимите галочку с параметра &laquo;<strong>Подавать гудок</strong>&laquo;</li>
<li>Запустите Firefox (<strong>Приложения</strong> -&gt; <strong>Интернет</strong> -&gt; <strong>Firefox Web Browser</strong>) и введите в адресной строке <strong>about:config</strong>. Затем найдите параметр <strong>accessibility.typeaheadfind.enablesound</strong> и поставьте ему значение <strong>false</strong>.</li>
</ol>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~f/rotuka?a=xgyJBRVk"><img src="http://feeds.feedburner.com/~f/rotuka?d=41" border="0"></img></a> <a href="http://feeds.feedburner.com/~f/rotuka?a=e3VzrqKo"><img src="http://feeds.feedburner.com/~f/rotuka?i=e3VzrqKo" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://rotuka.com/wacom-bamboo-one-ubuntu-ustanovka-i-reshenie-problem/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
