<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Ruby on Rails c нуля!</title>
	
	<link>http://rubydev.ru</link>
	<description>- блог изучающего Ruby, Ruby on Rails и другие технологии</description>
	<lastBuildDate>Wed, 09 May 2012 11:11:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Ruby-on-Rails" /><feedburner:info uri="ruby-on-rails" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>RDRubyTutorial: Метапрограммный Ruby level 2</title>
		<link>http://feedproxy.google.com/~r/Ruby-on-Rails/~3/J8UdvkJXrPk/</link>
		<comments>http://rubydev.ru/2012/05/rubydev_ruby_tutorial_metaprogramming_ruby_2/#comments</comments>
		<pubDate>Wed, 09 May 2012 11:07:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Основы]]></category>
		<category><![CDATA[eigenclass]]></category>
		<category><![CDATA[metaprogramming]]></category>
		<category><![CDATA[singleton]]></category>
		<category><![CDATA[tuts]]></category>

		<guid isPermaLink="false">http://rubydev.ru/?p=1567</guid>
		<description><![CDATA[Предварительно рекомендую прочесть Метапрограммный Ruby. К моему удивлению не все Ruby программисты знают внутреннего устройства Ruby. Не в том, смысле, что Ruby&#8217;ст должен изучать исходники своего любимого языка программирования, но в том, что многие моменты не понятны. Например не понятно, чем класс отличается от объекта или что такое singleton&#8217;ы в Ruby. Эта статья призвана совершить [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rubydev.ru/wp-content/uploads/2011/03/ruby_tutorial.png"><img class="alignleft  wp-image-718" style="margin-right: 20px;" title="ruby_tutorial" src="http://rubydev.ru/wp-content/uploads/2011/03/ruby_tutorial-300x160.png" alt="" width="250" /></a>Предварительно рекомендую прочесть <a href="http://rubydev.ru/2011/10/rubydev_ruby_tutorial_metaprogramming_ruby/">Метапрограммный Ruby</a>.</p>
<p>К моему удивлению не все Ruby программисты знают внутреннего устройства Ruby. Не в том, смысле, что Ruby&#8217;ст должен изучать исходники своего любимого языка программирования, но в том, что многие моменты не понятны. Например не понятно, чем класс отличается от объекта или что такое singleton&#8217;ы в Ruby. Эта статья призвана совершить некоторую демистификацию Ruby. В простой манере и без влезания в код самого Ruby я расскажу почему что-то работает именно так, как работает. Статья ориентирована не на новичков, а на программистов более-менее среднего уровня, то есть достаточно хорошо знакомых с Ruby.</p>
<p>Статья будет иметь формат повествования, она будет лишена структуры, читайте ее просто как программистскую сказку.</p>
<p>Классы &#8212; это объекты, но только на половину. Классы являются экземплярами одного из базовых классов Class, однако они не являются &#171;классическими&#187; объектами.</p>
<p><span id="more-1567"></span></p>
<p><span style="color: #008000;">$ ruby -v</span><br />
<span style="color: #008000;"> ruby 1.9.3p191 (2012-04-19 revision 35398) [i686-linux]</span><br />
<span style="color: #008000;"> $ irb</span></p>
<pre class="brush:ruby">
class A
end

A.class #=&gt; Class
</pre>
<p>В Ruby объекты не могут иметь собственных методов. Объект &#8212; это просто набор данных. Например объект класса Human содержит данные об имени, росте, весе, цвете глаз и прочих параметрах человека. В этом смысле объект в Ruby не сильно отличается от ассоциативного массива (а в JavaScript &#8212; это и вовсе одно и то же). Поскольку объект не может хранить собственные методы, то его методы хранятся в классе. То, что класс хранит методы своих экземпляров &#8212; это основное отличие класса от обыкновенного объекта. Даже не то, что класс может создавать экземпляры, а то, что он хранит методы экземпляров, ведь мы можем используя техники метапрограммирования расширить обыкновенный объект до того, что он будет подобным классу в своем поведении, но методы своих экземпляров он хранить не сможет.</p>
<pre class="brush:ruby">
class A
  def hello
    puts 'hello'
  end
end

a = A.new

a.hello
# hello
</pre>
<p>Когда мы для a вызываем метод hello, то, на самом деле a передает сообщение об его вызове по цепочке наследования, сначала к своему singleton классу, затем к классу A и т.д. пока метод не будет найден. У самого же a нет методов!</p>
<p>Вот он singleton класс:</p>
<pre class="brush:ruby">
a.singleton_class
#=&gt; #&lt;Class:#&lt;A:0x82bf770&gt;&gt;

А вот еще один:

A.singleton_class
#=&gt; #&lt;Class:A&gt;
</pre>
<p>Любой объект в том числе и класс (который объект только на половину) имеет закрепленный за собой singletion класс. Singleton класс встраивается в цепочку наследования. Здесь он наследуется от класса A:</p>
<pre class="brush:ruby">
a.singleton_class
#=&gt; #&lt;Class:#&lt;A:0x82bf770&gt;&gt;
</pre>
<p>А здесь он наследуется от класса Class:</p>
<pre class="brush:ruby">
A.singleton_class
#=&gt; #&lt;Class:A&gt;
</pre>
<p>Таким образом Singleton класс &#8212; это незаметная ссылка между экземпляром класса и классом. Когда мы определяем объектам специальные методы, например так:</p>
<pre class="brush:ruby">
def a.bye
  puts 'bye'
end

a.bye
# bye
</pre>
<p>&#8230; или так:</p>
<pre class="brush:ruby">
def A.how_are_you
  puts 'How are you?'
end

A.how_are_you
# How are you?
</pre>
<p>&#8230; или так:</p>
<pre class="brush:ruby">
class A
  def self.what_is_your_name
    puts "What is your name?"
  end
end

A.what_is_your_name
# What is your name?
</pre>
<p>&#8230; или даже так:</p>
<pre class="brush:ruby">
class A
  class &lt;&lt; self
    def how_old_are_you
      puts 'How old are you?'
    end
  end
end

A.how_old_are_you
# How old are you?
</pre>
<p>&#8230; то мы не явно имеем дело с Singleton классами. Класс способен хранить методы своих экземпляров, но не свои собственные. Каждый класс имеет Singleton класс, который хранит уникальные методы класса. Стандартные методы класс, будучи экземпляром класса Class, хранит в классе Class и других базовых классах, например классе Object от которого он наследуется:</p>
<pre class="brush:ruby">
A.superclass #=&gt; Object
</pre>
<p>Все уникальные методы объектов, которые вы определяете хранятся в Singleton классах, в универсальные методы хранятся в их классах.</p>
<pre class="brush:ruby">
a.singleton_methods #=&gt; [:bye]
A.singleton_methods #=&gt; [:how_are_you, :what_is_your_name, :how_old_are_you]
A.methods.count #=&gt; 100
(A.methods - A.singleton_methods).count #=&gt; 97
</pre>
<p>Почему название такое &#8212; Singleton класс? &#8212; Дело в том, что этот класс может иметь только один объект:</p>
<pre class="brush:ruby">
a.singleton_class.new
TypeError: can't create instance of singleton class
</pre>
<p>Потому и название такое, хотя ме больше нравится название Eigenclass, которое, однако встречается значительно реже. С названием eigenclass не возникает путаницы так как существует еще такой паттерн как Singleton (&#171;Одиночка&#187;), который позволяет создавать классы, которые не могут иметь более одного экземпляра. Из-за того, что Eigenclass имеет только экземпляр &#8212; объект, за которым он закреплен, то и было решено использовать название Singleton, которое правда не описывает его предназначение и вносит путаницу с паттерном проектирования о котором говорилось выше. Название Eigenclass лучше отображает суть ведь в переводе с английского/немецкого оно означает &#171;собственный класс&#187;.</p>
<p><strong>Делаем выводы:</strong></p>
<ul>
<li>Объект, если рассматривать его совсем примитивно является просто хэшем, который хранит определенные данные.</li>
<li>Класс является объектом, который способен хранить методы своих экземпляров.</li>
<li>Singleton класс &#8212; это класс, экземпляром которого на самом деле является объект, который может обладать только одним экземпляром, и которых хранит все уникальные методы объекта.</li>
<li>Мы не говорим, что a наследуется от A и не смотря на наличие singleton класса &#8212; это правильно, так как singleton класс &#8212; это просто реализация, но не парадигма и его наличие ни на что не влияет.</li>
</ul>
<p>Люди часто не понимают, что делает следующий код:</p>
<pre class="brush:ruby">
class A
  class &lt;&lt; self
    def how_old_are_you
      puts 'How old are you?'
    end
  end
end
</pre>
<p>Этот код &#8212; это в некотором смысле синтаксический сахар. Выражение <span style="color: #333399;">class</span> нуждается в получении константы &#8212; имени класса. <span style="color: #333399;">self</span> &#8212; ссылка на текущий контекст, если мы не указываем приемник вызова метода явно, то предполагается, что им является self &#8212; объект в контексте которого осуществляется вызов. Когда мы используем <span style="color: #333399;">class &lt;&lt; self</span>, то это просто специальный синтаксис, через стрелку &#171;<span style="color: #333399;">&lt;&lt;</span>&#171; в котором мы как бы открываем контекст предка &#8212; singleton класса. В class мы не можем передать что-то иное, кроме константы, в этом случае возникнет синтаксическая ошибка:</p>
<pre class="brush:ruby">
class A
  class singleton_class
    def rubydev
      puts "RubyDev.ru"
    end
  end
end
</pre>
<p><span style="color: #ff0000;">SyntaxError: (irb):90: class/module name must be CONSTANT</span><br />
<span style="color: #ff0000;"> from /home/vladimir/.rvm/rubies/ruby-1.9.3-head/bin/irb:16:in `&lt;main&gt;&#8217;</span></p>
<p>Singleton классы являются безымянными (анонимными). Им не нужно имя хотя бы потому, что они сами по себе существовать не могу, с ними на прямую никто работать не должен, а если и возникает такая необходимость, то обратиться к ним можно через метод singleton_class объекта, за которым они закреплены.</p>
<p>Синтаксис <span style="color: #333399;">class &lt;&lt; self</span> просто обрабатывается иначе. Интерпретатор понимает его не как необходимость вызова для объекта <span style="color: #333399;">class</span> метода <span style="color: #333399;">&lt;&lt;</span> и передачи аргумента <span style="color: #333399;">self</span>, а как нечто иное &#8212; переключение в контекст singleton класса. Вот и все!</p>
<img src="http://feeds.feedburner.com/~r/Ruby-on-Rails/~4/J8UdvkJXrPk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://rubydev.ru/2012/05/rubydev_ruby_tutorial_metaprogramming_ruby_2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://rubydev.ru/2012/05/rubydev_ruby_tutorial_metaprogramming_ruby_2/</feedburner:origLink></item>
		<item>
		<title>Операторы, условия и циклы языка Си</title>
		<link>http://feedproxy.google.com/~r/Ruby-on-Rails/~3/kqgqODbt47M/</link>
		<comments>http://rubydev.ru/2012/05/operators-loops-and-conditions-in-c/#comments</comments>
		<pubDate>Sun, 06 May 2012 13:05:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Си и C++]]></category>
		<category><![CDATA[императивная парадигма]]></category>
		<category><![CDATA[операторы]]></category>
		<category><![CDATA[процедурные языки]]></category>
		<category><![CDATA[Си]]></category>

		<guid isPermaLink="false">http://rubydev.ru/?p=1555</guid>
		<description><![CDATA[Из серии: Введение в программирование на Си Переменные и типы данных в Си * Операторы, условия и циклы языка Си Си включает в себя всего 3 цикла и 2 условных оператора. Набор арифметических операторов и операторов сравнения стандартен. В данной статье мы сначала бегло пробежимся по арифметическим операторам и операторам сравнения, а затем перейдем к [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rubydev.ru/wp-content/uploads/2011/10/DYT-c-et-c-transformers-pub-1.jpg"><img class="alignleft  wp-image-1302" style="margin: 0 20px 0 0;" title="DYT-c-et-c-transformers-pub-1" src="http://rubydev.ru/wp-content/uploads/2011/10/DYT-c-et-c-transformers-pub-1-300x131.jpg" alt="" width="250" /></a><br />
<strong>Из серии:</strong></p>
<ol>
<li><a href="http://rubydev.ru/2012/05/introduction-to-programming-in-c/">Введение в программирование на Си</a></li>
<li><a href="http://rubydev.ru/2012/05/variables-and-data-types-in-c/">Переменные и типы данных в Си</a></li>
<li>* <a href="http://rubydev.ru/2012/05/operators-loops-and-conditions-in-c/">Операторы, условия и циклы языка Си</a>
</ol>
<p>Си включает в себя всего 3 цикла и 2 условных оператора. Набор арифметических операторов и операторов сравнения стандартен. В данной статье мы сначала бегло пробежимся по арифметическим операторам и операторам сравнения, а затем перейдем к изучению циклов и условий, в которых познакомимся с операторами еще более подробно. Операторы работы с бинарными данными мы рассмотрим в отдельной статье посвященной работе с битами и байтами.</p>
<p><span id="more-1555"></span></p>
<p><strong>Арифметические и логические операторы</strong><br />
<strong>=</strong> &#8212; присваивание (самый низкий приоритет),<br />
<strong>+</strong> &#8212; сложение,<br />
<strong>-</strong> &#8212; вычитание,<br />
<strong>*</strong> &#8212; умножение,<br />
<strong>/</strong> &#8212; деление,<br />
<strong>%</strong> &#8212; остаток от деления на цело,<br />
<strong>()</strong> &#8212; скобки имеют наивысший приоритет и используются для увеличения приоритета других действий, например сложения.</p>
<p>Пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b =10, c = 25, d = 100, result;

    printf("%d + %d = %d\n",  a, b, a + b);
    printf("%d - %d = %d\n",  a, b, a - b);
    printf("%d / %d = %d\n",  d, c, d / c);
    printf("%d * %d = %d\n",  c, a, c * a);
    printf("%d %% %d = %d\n", c, b, c % b);

    result = (c + d) / a * b;

    printf("result is: %d\n", result);
}
</pre>
<p>Результат:</p>
<p><span style="color: #008000;">5 + 10 = 15</span><br />
<span style="color: #008000;">5 &#8212; 10 = -5</span><br />
<span style="color: #008000;">100 / 25 = 4</span><br />
<span style="color: #008000;">25 * 5 = 125</span><br />
<span style="color: #008000;">25 % 10 = 5</span><br />
<span style="color: #008000;">result is: 250</span></p>
<p>К логическим операторам относятся следующие:<br />
<strong>&gt;</strong> &#8212; больше,<br />
<strong>&lt;</strong> &#8212; меньше,<br />
<strong>&gt;=</strong> &#8212; больше или равно,<br />
<strong>&lt;=</strong> &#8212; меньше или равно,<br />
<strong>==</strong> &#8212; равно,<br />
<strong>!=</strong> &#8212; не равно</p>
<p>Соединители логических условий:<br />
<strong>&amp;&amp;</strong> &#8212; И,<br />
<strong>||</strong> &#8212; ИЛИ.<br />
<strong>!</strong> &#8212; НЕ</p>
<p>Пример использования в условии IF:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b =10, c = 25, d = 100, result;

    if (b &gt; a)
        printf("b &gt; a\n");

    if (a &gt;= b || b &lt;= c)
        printf("a &gt;= b OR b &lt;= c\n");

    if (a == c / a &amp;&amp; (c % a) == 0) {
        printf("c = a * a\n");
    }

    return 0;
}
</pre>
<p>Данная программа в результате выполнения напечатает следующее:</p>
<p><span style="color: #008000;">b &gt; a</span><br />
<span style="color: #008000;">a &gt;= b OR b &lt;= c</span><br />
<span style="color: #008000;">c = a * a</span></p>
<p><strong>Условные операторы</strong><br />
После знакомства с арифметическими и логическими операторами пора познакомиться и с операторами позволяющими создавать условия. С одним вы уже познакомились выше &#8212; это условие IF (&#171;ЕСЛИ&#187;) которое выполняет следующую после него единственную строку кода или блок кода, если условие в круглых скобках верно.</p>
<p>У условия с <strong>IF</strong> имеется еще альтернативная форма  <strong>IF-ELSE</strong> (ЕСЛИ-ИНАЧЕ) Пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b =10, c = 25, d = 100, result;

    if (b &gt; a) {
        printf("b &gt; a\n");
    } else {
        printf("b &lt; a\n");
    }

    return 0;
}
</pre>
<p>А вот еще один пример, только на этой раз <strong>IF-ELSE IF-ELSE</strong>:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    if (b &gt; a) {
        printf("b &gt; a\n");
    } else if (b == a) {
        printf("b == a\n");
    } else {
        printf("b &lt; a\n");
    }

    return 0;
}
</pre>
<p>Последний пример позволяет выполнить только дно из трех действий (один из блоков кода), а следующие после этого действия проверки игнорируются. Так, если b &gt; a, то проверка на то, равно ли b == a производиться не будет.</p>
<p>Другой способ создать проверку условия &#8212; это использовать конструкцию <strong>SWITCH-CASE-DEFAULT</strong>. Ниже приведен пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    switch (d) {
        case 5:
            printf("d = 5\n");
            break;
        case 10: case 25:
            printf("d = 10 or 25\n");
            break;
        case 100:
            printf("d = 100\n");
            break;
        default:
            printf("d = d");
            /* здесь break не обязателен */
            break;
    }

    return 0;
}
</pre>
<p>Оператор switch принимает в качестве аргумента какое-либо значение, значение которой необходимо проверить. case 5:, case 10:, case 25: case 100: default: &#8212; являются метками, которые используются в операторе switch и goto для перемещения по коду. Конкретно метки case и default используются в switch, оператор ищет их и проверяет их соответствие значению переменного аргумента. В нашем случае значению 100 переменной d соответствует метка case 100:. Когда найдена соответствующая метка, программа выполняет ассоциируемый с нею код, то есть будет выполнена функция printf() и оператор break. Если ни одна метка не будет соответствовать значению аргумента, то будет выполнен код метки default:. Метка default: не обязательна, вы можете ее не использовать в тех случаях, когда она будет лишней.</p>
<p><strong>Цикл WHILE</strong></p>
<p>while является самым простым циклом, с его помощью можно заменить любой другой, правда их в Си всего 3 штуки. Пример while цикла:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    while (a &lt;= d) {
        if (a % 10 == 0)
            printf("%d ", a);

        a += 5;
    }

    printf("\n");

    return 0;
}
</pre>
<p>Результат:</p>
<p><span style="color: #008000;">10 20 30 40 50 60 70 80 90 100</span></p>
<p>Цикл while принимает условие и выполняет блок кода до тех пор, пока условие верно. Мы обязаны каждый каждый раз увеличивать значение переменной a, которая фигурирует в условии, иначе мы получим бесконечный цикл.</p>
<p><strong>Цикл DO&#8230;WHILE</strong><br />
Цикл do&#8230;while очень похож на цикл while, однако он является циклом с пост-условием. То есть условие выполнения блока кода проверяется после выполнения, а не до, что гарантирует то, что код выполнится минимум один раз. Ниже приведен пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    do {
        printf("%d ", a);
    } while (a &gt;= d);

    printf("\n");

    return 0;
}
</pre>
<p>По условиям while блок кода не должен выполнится, однако он выполнится один раз потому, что мы используем цикл do&#8230;while. Реализовать цикл do&#8230;while через while очень просто &#8212; достаточно выполнить функцию или содержимое блок кода перед использованием цикла, а затем использовать их в цикле.</p>
<p><strong>Цикл FOR</strong></p>
<p>Цикл for является продвинутой версией циклов. for сразу заботится об инициализации и инкременте счетчика. Пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    for(int i = 0; i &lt;= d; i += 10) {
        printf("%d ", i);
    }

    printf("\n");

    return 0;
}
</pre>
<p>Результат:</p>
<p><span style="color: #008000;">0 10 20 30 40 50 60 70 80 90 100</span></p>
<p>Как видите, мы сразу объявляем, что счетчик цикла должен увеличиваться после каждой итерации.</p>
<p>После знакомства с циклами и условными операторами давайте вернемся к упомянутому ранее break.</p>
<p><strong>Оператор BREAK</strong></p>
<p>Оператор break занимается прерыванием. В случае со switch мы используем его для кода каждой метки с той целью, чтобы следующие метки были проигнорированы, в противном случае switch проверит соответствие переданного ему значения всем меткам, точнее будет проверять пока не наткнется на break. Пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;

int main(void) {
    int a = 5, b = 10, c = 25, d = 100, result;

    switch (d) {
        case 5:
            printf("d = 5\n");
        case 10: case 25:
            printf("d = 10 or 25\n");
        case 100:
            printf("d = 100\n");
        default:
            printf("d = d\n");
    }

    return 0;
}
</pre>
<p>Результат:<br />
<span style="color: #008000;">d = 100</span><br />
<span style="color: #008000;">d = d</span></p>
<p>Еще break очень полезен в ситуациях, когда мы не знаем точно когда необходимо завершить работу цикла. В таком случае принято использовать концепцию &#171;стоп слов&#187; -значений, которые позволяют программе понять, что цикл необходимо завершить. Пример:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main(void) {
    char str[100];

    while (1) {
        printf("Введите слово: ");
        scanf("%s", str);
        printf("\n");

        if (strcmp(str, "exit") != 0) {
            printf("&gt;&gt; %s\n", str);
        } else {
            printf("bye!\n");
            break;
        }
    }

    return 0;
}
</pre>
<p>Пример работы:</p>
<p><span style="color: #008000;">$ ./a.out</span><br />
<span style="color: #008000;">Введите слово: Hello!</span></p>
<p><span style="color: #008000;">&gt;&gt; Hello!</span><br />
<span style="color: #008000;">Введите слово: RubyDev</span></p>
<p><span style="color: #008000;">&gt;&gt; RubyDev</span><br />
<span style="color: #008000;">Введите слово: exit</span></p>
<p><span style="color: #008000;">bye!</span></p>
<p><strong>Оператор CONTINUE</strong><br />
Оператор continue похож на оператор break. Отличием continue от break является то, что если break останавливает выполнение кода (например цикла), то continue позволяет остановить только текущую итерацию и перейти к следующей. Перепишем пример выше с использованием continue:</p>
<pre class="brush:c">
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main(void) {
    char str[100];

    while (1) {
        printf("Введите слово: ");
        scanf("%s", str);
        printf("\n");

        if (strcmp(str, "exit") != 0) {
            printf("&gt;&gt; %s\n", str);
        } else {
            continue;
            /* выполнено не будет */
            printf("bye!\n");
        }
    }

    return 0;
}
</pre>
<p>Пример работы:</p>
<p><span style="color: #008000;">$ ./a.out</span><br />
<span style="color: #008000;">Введите слово: exit</span></p>
<p><span style="color: #008000;">Введите слово: exit</span></p>
<p><span style="color: #008000;">Введите слово: RubyDev</span></p>
<p><span style="color: #008000;">&gt;&gt; RubyDev</span><br />
<span style="color: #008000;">Введите слово:</span></p>
<p>На этом знакомство с операторами в Си закончем. По goto, как и по работе с битами будет отдельная статья.</p>
<img src="http://feeds.feedburner.com/~r/Ruby-on-Rails/~4/kqgqODbt47M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://rubydev.ru/2012/05/operators-loops-and-conditions-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://rubydev.ru/2012/05/operators-loops-and-conditions-in-c/</feedburner:origLink></item>
		<item>
		<title>QuasarLog: Запись вторая. Обход полиморфного HMT</title>
		<link>http://feedproxy.google.com/~r/Ruby-on-Rails/~3/8r3vzvDKu1o/</link>
		<comments>http://rubydev.ru/2012/05/quasar-log-2-has_many-through-polymorphic/#comments</comments>
		<pubDate>Sun, 06 May 2012 08:41:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[CMS]]></category>
		<category><![CDATA[QuasarLog]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Ruby on Rails 3]]></category>

		<guid isPermaLink="false">http://rubydev.ru/?p=1551</guid>
		<description><![CDATA[Что было сделано? Удалена сущность Document, а вместе с тем и понятие документов. В Quasar будут присутствовать ресурсы, например статья, продукт или топик форума &#8212; это ресурсы. Здесь понятие ресурс несколько отличается от ресурса REST архитектуры, точнее первое множество входит во второе. В общем, в Quasar вместо документов теперь ресурсы. Был добавлен первый ресурс &#8212; [...]]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://rubydev.ru/wp-content/uploads/2011/08/q2.jpg"><img class="alignleft  wp-image-1068" style="margin: 0 20px 0 0;" title="quasar" src="http://rubydev.ru/wp-content/uploads/2011/08/q2-300x228.jpg" alt="" width="200" /></a>Что было сделано?</strong></p>
<ul>
<li>Удалена сущность <span style="color: #333399;">Document</span>, а вместе с тем и понятие документов. В <strong>Quasar</strong> будут присутствовать ресурсы, например статья, продукт или топик форума &#8212; это ресурсы. Здесь понятие ресурс несколько отличается от ресурса REST архитектуры, точнее первое множество входит во второе. В общем, в Quasar вместо документов теперь ресурсы.</li>
<li>Был добавлен первый ресурс &#8212; <span style="color: #333399;">Article</span> (статья). Он представляет собой какую-то совсем простую сущность, например пост в блоге или статью в новостном сайте. Для начала достаточно этой единственной сущности (ресурса), а затем мы добавим, например Product и Topic.</li>
<li>Добавлена константа <strong>RESTYPES</strong>, которая хранит имена моделей &#8212; ресурсов Quasar CMS. Эти модели должны храниться в директории app/models/resources.</li>
<li>Добавлена модель AttachmentLink, которая должна перелинковывать между собой ресурсы, точнее хранить связи между ресурсом и его вложениями (вложения &#8212; также ресурсы). Здесь и обнаружилась интересная проблема, о которой рассказано далее.</li>
<li>Добавлены счетчики для attached/master ресурсов.</li>
</ul>
<p><span id="more-1551"></span><br />
<strong>Проблема и ее рашение</strong><br />
Оказывается в ActiveRecord нельзя создавать полиморфные <span style="color: #ff0000;">has_many :trough =&gt; &#8230; (HMT)</span> ассоциации. Ниже приведенный упрощенный код возвращает ошибку:</p>
<p><span style="color: #ff0000;"><strong> ActiveRecord::HasManyThroughAssociationPolymorphicSourceError</strong>:</span><br />
<span style="color: #ff0000;">       Cannot have a has_many :through association &#8216;Article#attachments&#8217; on the polymorphic object &#8216;Attachment#attachment&#8217;.</span></p>
<pre class="brush:ruby">
#app/models/attachment_link.rb
class AttachmentLink &lt; ActiveRecord::Base
  #...

  belongs_to :master,     polymorphic: true
  belongs_to :attachment, polymorphic: true
end

#app/models/resources/article.rb
class Article &lt; ActiveRecord::Base
#...

  has_many :attachment_links, as: :master,     dependent: :destroy
  has_many :master_links,     as: :attachment, dependent: :destroy, class_name: "AttachmentLink"
  has_many :attachments, through: :attachment_links
  has_many :masters,     through: :master_links

  def attach(attachment)
    attlink = self.attachment_links.new
    attlink.attachment = attachment
    attlink.save
  end
end
</pre>
<p>К сожалению, такое решение не работает. Для реализации связывания типа master -&gt; attachment было решено добавить новую сущность &#8212; Resource. Resource хранит список всех ресурсов (Article, Product, Topic и т.д.) и является промежуточным звеном связывания. Resource будет:</p>
<pre class="brush:ruby">
has_many   :attachment_links, as: :master, dependent: :destroy
has_many   :attachments, through: :attachment_links
belongs_to :real_resource, polymorphic: true
</pre>
<p>А ресурсы вроде Article будут:</p>
<pre class="brush:ruby">
has_many :master_links,     as: :attachment,    dependent: :destroy, class_name: "AttachmentLink"
has_many :masters,     through: :master_links

has_one  :resource,         as: :real_resource, dependent: :destroy
has_many :attachments, through: :resource
</pre>
<p>К сожалению, и этот способ не помог, была выброшена все так же ошибка &#8212; <span style="color: #ff0000;">ActiveRecord::HasManyThroughAssociationPolymorphicSourceError</span>. Немного  в исходниках Rails я нашел вот такой код:</p>
<pre class="brush:ruby">
if through_reflection.options[:polymorphic]
  raise HasManyThroughAssociationPolymorphicThroughError.new(active_record.name, self)
end
</pre>
<p>То есть, при любая HMT ассоциация с полиморфной сущностью невозможна. Странно конечно, что это не реализовано, ну да ладно. Данный код находится в методе ActiveRecord::Reflection::ThroughReflection.check_validity!. Я не стал сильно вникать в то, зачем необходима такая проверка ассоциации, но видимо она там не зря. Разумеется, можно переписать кусок Rails своим кодом, который, возможно, будет пораждать множество конфликтов.</p>
<p>Я решил пойти другим путем. Я решил реализовать ассоциацию с вложениями вручную, то есть без has_many. Например, списки ссылок на master/attached ресурсы получаются через такой код:</p>
<pre class="brush:ruby">
def attachment_links()
  @attachment_links ||= AttachmentLink.where("master_id = ? AND master_type = ?", id,  class_name).limit(attachments_count)
end

def master_links()
  @master_links ||= AttachmentLink.where("attachment_id = ? AND attachment_type = ?", id,  class_name).limit(masters_count)
end
</pre>
<p>Хеш присоединенных ресурсов получаем вот так:</p>
<pre class="brush:ruby">
def attachments()
  @attachments ||= {}

  if @attachments.empty?
    attachment_links.each do |attlink|
      attclass_name = attlink.attachment_type
      attclass = attclass_name.constantize
      attachment = attclass.where(id: attlink.attachment_id).limit(1)
      @attachments[attclass_name] ||= []

      unless @attachments[attclass_name].include? attachment
        @attachments[attclass_name] &lt;&lt; attachment
      end
    end
  end

  return @attachments
end
</pre>
<p>Новый attachment добавляется вот так:</p>
<pre class="brush:ruby">
def attach(attachment)
  if new_attlink(attachment).save
    increment_attachments_count
    reload_attachments_with attachment
    attachment.increment_masters_count
  end
end

def new_attlink(attachment = nil)
  AttachmentLink.new do |attlink|
    attlink.master_id   = self.id
    attlink.master_type = class_name

    if attachment.present?
      attlink.attachment_id   = attachment.id
      attlink.attachment_type = attachment.class_name
    end
  end
end
</pre>
<p>Разумеется этот код не совершенен ии будет еще улучшаться, но на первое время он вполне годится.<br />
Напомню, что у нас есть группа во Вконтакте: <a href="http://vk.com/rubydevclub">RubyDevClub</a>, а еще за QuasarCMS можно следить на  <a href="https://plus.google.com/b/117050244523917891866/117050244523917891866/posts">странице в Google +</a>.</p>
<img src="http://feeds.feedburner.com/~r/Ruby-on-Rails/~4/8r3vzvDKu1o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://rubydev.ru/2012/05/quasar-log-2-has_many-through-polymorphic/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://rubydev.ru/2012/05/quasar-log-2-has_many-through-polymorphic/</feedburner:origLink></item>
	</channel>
</rss>

