<?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>Вредный и его заметки</title>
	
	<link>http://vredniy.ru</link>
	<description>все о веб-программировании</description>
	<lastBuildDate>Wed, 25 Apr 2012 17:59:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/vredniy-ru" /><feedburner:info uri="vredniy-ru" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Rails Полиморфная связь и TokenInput jQuery</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/gFHDAqwqbu8/</link>
		<comments>http://vredniy.ru/2012/04/polymorphic-relations-and-token-input-jquery/#comments</comments>
		<pubDate>Wed, 18 Apr 2012 19:26:02 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=916</guid>
		<description><![CDATA[Представьте ситуацию, что у вас имеется некая модель, к которой вы хотите добавлять по средствам связей другие модели. Хорошо, когда данную связь можно описать обычным has_many, другое дело, когда нужно привязать разнородные модели, к примеру, у вас имеется модель вопросов, к которой нужно привязать город или страну (не очень наглядный пример, вряд ли он вам [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F04%2Fpolymorphic-relations-and-token-input-jquery%2F"><br />
				<img class="colorbox-916"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F04%2Fpolymorphic-relations-and-token-input-jquery%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=jQuery,rails&amp;b=2" height="61" width="50" title="Rails Полиморфная связь и TokenInput jQuery" alt=" Rails Полиморфная связь и TokenInput jQuery" /><br />
			</a>
		</div>
<p>Представьте ситуацию, что у вас имеется некая модель, к которой вы хотите добавлять по средствам связей другие модели. Хорошо, когда данную связь можно описать обычным <strong>has_many</strong>, другое дело, когда нужно привязать разнородные модели, к примеру, у вас имеется модель вопросов, к которой нужно привязать город или страну <span id="more-916"></span>(не очень наглядный пример, вряд ли он вам в жизни встретится, но я поделюсь своим опытом).</p>
<h3>Инструментарий</h3>
<p>Как вы, наверное, догадались, основным инструментом будет выступать ruby an rails. Из гемов будем использовать <strong>simple_form</strong> для удобного создания форм, <strong>inherited_resources</strong>, чтобы писать намного меньше кода в контроллерах (сейчас не представляю без этого гема жизни). </p>
<p>Также нам понадобится плагин для jQuery <a href="http://loopj.com/jquery-tokeninput/" rel="nofollow">tokenInput</a>, который будет отображать выпадающий список с autoComplete&#8217;ом, из которого мы сможем выбрать одно значение из стран или городов (список будет один).</p>
<h3>Реализация</h3>
<p>Начнем с контроллера <strong>QuestionableController</strong> (не очень, конечно, удачное название), который будет отдавать солянку из городов и стран с возможностю поиска.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> QuestionableController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> index<br />
&nbsp; &nbsp; countries = Country.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, conditions: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'name LIKE(?)'</span>, <span style="color:#996600;">&quot;%#{ params[:q] <br />
&nbsp; &nbsp; cities = City.find(:all, conditions: ['name LIKE(?)', &quot;</span><span style="color:#006600; font-weight:bold;">%</span><span style="color:#008000; font-style:italic;">#{ params[:q] }%&quot;])</span><br />
<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@questionable</span> = countries <span style="color:#006600; font-weight:bold;">+</span> cities<br />
<br />
&nbsp; &nbsp; respond_to <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span><span style="color:#CC0066; font-weight:bold;">format</span><span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">json</span> <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span> &nbsp;<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span> &nbsp;<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Лучше вынести всю логику в модель, но данный пример создан исключительно для демонстрации. Что мы делаем в этом контроллере? Ищем страны и города, удовлетворяющих параметру <strong>q</strong> и заполняем инстанс переменную <strong>@questionable</strong></p>
<p>Также давайте заполним нашу вьюшку <em>index.json.erb</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span>= sanitize <span style="color:#0066ff; font-weight:bold;">@questionable</span>.<span style="color:#9900CC;">to_json</span><span style="color:#006600; font-weight:bold;">&#40;</span>methods: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id_with_class_name</span><span style="color:#006600; font-weight:bold;">&#93;</span>, only: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></div></td></tr></tbody></table></div>
<p>в которой мы рендерим наш json, т.к. нам не нужны все поля модели мы используем только необходимые (only: [:id, :name]), ключ methods: указывает на то, что мы помимо физических свойст, будем использовать метод модели <em>id_with_class_name</em>.</p>
<p>Пока не забыл, давайте пропишем пару строк в наш <em>config/routes.rb</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources <span style="color:#ff3333; font-weight:bold;">:questions</span> <span style="color:#008000; font-style:italic;"># для того, чтобы создавать/показывать/удалять вопросы</span><br />
resources <span style="color:#ff3333; font-weight:bold;">:questionable</span>, only: <span style="color:#ff3333; font-weight:bold;">:index</span> <span style="color:#008000; font-style:italic;"># для того, чтобы отображать json</span></div></td></tr></tbody></table></div>
<p>Перейдем к моделям:</p>
<p><em>models/question.rb</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Question <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; attr_accessor <span style="color:#ff3333; font-weight:bold;">:location</span><br />
<br />
&nbsp; belongs_to <span style="color:#ff3333; font-weight:bold;">:questionable</span>, polymorphic: <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; attr_accessible <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:questionable_id</span>, <span style="color:#ff3333; font-weight:bold;">:questionable_type</span><br />
<br />
&nbsp; before_save <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">location</span> =~ <span style="color:#006600; font-weight:bold;">/</span>_<span style="color:#006600; font-weight:bold;">/</span><br />
&nbsp; &nbsp; location_id, location_type = <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">location</span>.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'_'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">questionable_id</span> &nbsp; = location_id &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> location_id.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">questionable_type</span> = location_type <span style="color:#9966CC; font-weight:bold;">unless</span> location_type.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Самая интересная строчка &#8212; это та, которая начинается с belongs_to, в ней мы объявляем полиморфную связь questionable. Дальше идет метод, который мы<br />
вызываем каждый раз перед сохранением в базу данных. В нем мы парсим строку из autoComplete&#8217;а, которая будет иметь вид id_ModelName и сохраняем отдельно id и ModelName.</p>
<p>Модель <em>city.rb</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> City <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; has_many <span style="color:#ff3333; font-weight:bold;">:questions</span>, as: <span style="color:#ff3333; font-weight:bold;">:questionable</span><br />
&nbsp; attr_accessible <span style="color:#ff3333; font-weight:bold;">:name</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> id_with_class_name<br />
&nbsp; &nbsp; <span style="color:#996600;">&quot;#{ id }_#{ self.class.name }&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>В ней объявляется связь has_many через questionable, который мы обявили в модели question полиморфной. Далее идем метод, который возвращает id записи и название класса модели (чтобы можно было отделить зерно от плевел).</p>
<p>Модель <em>country.rb</em> почти такая же</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Country <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; has_many <span style="color:#ff3333; font-weight:bold;">:questions</span>, as: <span style="color:#ff3333; font-weight:bold;">:questionable</span><br />
&nbsp; attr_accessible <span style="color:#ff3333; font-weight:bold;">:name</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> id_with_class_name<br />
&nbsp; &nbsp; <span style="color:#996600;">&quot;#{ id }_#{ self.class.name }&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Связь обявлена также как и в предыдущей модели.</p>
<p>Наш маленький контроллер <em>QuestionController</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> QuestionsController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">InheritedResources::Base</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>где остальное спросите вы. Это все. Это все, что нам нужно для того, чтобы создавать, удалять, редактировать вопросы. Как вы, наверное, заметили наш контроллер наследуется не от ApplicationController&#8217;а, а от inherited_resources. Что это значит? А это значит, если абстрагироваться от 80% возможностей этого гема, то, что гем берет всю &#171;грязную&#187; работу на себя, предоставляя нам в пользование переменные resource и collection, хранятся в которых ссылка на текущую запись (resource) и список всех записей (collection) соответственно. Для того, чтобы мы смогли создать свой первый вопрос нам необходимы лишь вьюшки. Начнем с _form.html.erb, которую мы будем подключать и в создании вопроса, и в редактировании.</p>
<p><em>app/views/questions/_form.html.erb</em></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span>= simple_form_for resource <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span> pre = <span style="color:#9966CC; font-weight:bold;">if</span> resource.<span style="color:#9900CC;">questionable</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#006600; font-weight:bold;">&#91;</span>resource.<span style="color:#9900CC;">questionable</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">to_json</span><span style="color:#006600; font-weight:bold;">&#40;</span>only: <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">input</span> <span style="color:#ff3333; font-weight:bold;">:location</span>, input_html: <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#996600;">'data-pre'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> pre, <span style="color:#9966CC; font-weight:bold;">class</span>: <span style="color:#996600;">'token-input-questionable'</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">submit</span> <span style="color:#0000FF; font-weight:bold;">nil</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></div></td></tr></tbody></table></div>
<p>Как видите, почти никаких различий с нативным form_for нет. Во второй строке мы заполняем переменную pre json&#8217;ом выбранного города или страны, в предпоследней создаем инпут с атрибутом data-pre, равным json&#8217;у и классом, чтобы мы могли найти этот элемент без проблем.</p>
<p><em>new.html.erb</em> и <em>edit.html.erb</em> абсолютно одинаковы и представляют собой следующее:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span>= render <span style="color:#996600;">'form'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></div></td></tr></tbody></table></div>
<p>в них мы отрисовываем только форму.</p>
<p>Далее кинем наш скачанный jquery.tokeninput.js в папку <em>app/assets/javascripts</em> и допишем в <em>application.js</em> следующее:</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> $input <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.token-input-questionable'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;$input.<span style="color: #660066;">tokenInput</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/questionable.json'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; tokenLimit<span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; tokenValue<span style="color: #339933;">:</span> <span style="color: #3366CC;">'id_with_class_name'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; prePopulate<span style="color: #339933;">:</span> $input.<span style="color: #660066;">data</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'pre'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Первым параметром к tokenInput мы указываем откуда брать данные, tokenLimit:1 указывает на то, что одной записи нам будет достаточно (одного элемента из выпадающего списка), tokenValue &#8212; откуда мы будем брать имя, которое будем отображать из json&#8217;а, prePopulate используем для того, чтобы заполнить элемент, если мы его уже выбрали (редактирование).</p>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/04/rsz_1screenshot_from_2012-04-18_230555-300x209.png" alt="rsz 1screenshot from 2012 04 18 230555 300x209 Rails Полиморфная связь и TokenInput jQuery" title="polymorphic relations rails" width="300" height="209" class="alignleft size-medium wp-image-917 colorbox-916" />Сумбурным получилось изложения материала, потому что для меня это в новинку и писалось это для того, чтобы не забыть полезную &#171;плюшку&#187; в дальнейшем. Если заметка кому-нибудь еще пригодится, я буду очень рад <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Rails Полиморфная связь и TokenInput jQuery" class='wp-smiley colorbox-916' title="Rails Полиморфная связь и TokenInput jQuery" /> </p>
<p>P.S.: Если данную заметку читает Александр, мало ли, то, надеюсь, он будет не против, что я позаимствовал его идею <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Rails Полиморфная связь и TokenInput jQuery" class='wp-smiley colorbox-916' title="Rails Полиморфная связь и TokenInput jQuery" /> </p>
<p>Демо проект &#171;лежит&#187; на <a href="http://vredniy-polymorphic.heroku.com/questions/" rel="nofollow">heroku</a>, репозиторий, как всегда на <a href="https://github.com/vredniy/rails-token-input" rel="nofollow">github</a> (там же лежат и миграции, нужные для запуска проекта).</p>
<p>Удачи вам в любых начинаниях и до новых встреч <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Rails Полиморфная связь и TokenInput jQuery" class='wp-smiley colorbox-916' title="Rails Полиморфная связь и TokenInput jQuery" /> </p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/gFHDAqwqbu8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/04/polymorphic-relations-and-token-input-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/04/polymorphic-relations-and-token-input-jquery/</feedburner:origLink></item>
		<item>
		<title>Собеседование и Unobtrusive Javascript на Rails</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/KqFyc2hh0cg/</link>
		<comments>http://vredniy.ru/2012/03/unobtrusive-javascript-rails/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 10:55:02 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ujs]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=911</guid>
		<description><![CDATA[Приветствую всех гостей и постояльцев на своем техническом, иногда не совсем, блоге. Кто читает меня в твиттере, наверное, помнят то, что вчера у меня было первое в жизни собеседование на ruby on rails вакансию, кто не читает, милости просим дружить в твиттере. Встретились мы сначала с генеральным директором, он рассказал о проекте, пока его не [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F03%2Funobtrusive-javascript-rails%2F"><br />
				<img class="colorbox-911"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F03%2Funobtrusive-javascript-rails%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=heroku,rails,ujs&amp;b=2" height="61" width="50" title="Собеседование и Unobtrusive Javascript на Rails" alt=" Собеседование и Unobtrusive Javascript на Rails" /><br />
			</a>
		</div>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/03/ajax-crud-150x150.jpg" alt="ajax crud 150x150 Собеседование и Unobtrusive Javascript на Rails" title="unobtrusive javascript rails" width="150" height="150" class="alignleft size-thumbnail wp-image-913 colorbox-911" />Приветствую всех гостей и постояльцев на своем техническом, иногда не совсем, блоге. Кто читает меня в твиттере, наверное, помнят то, что вчера у меня было первое в жизни собеседование на ruby on rails вакансию, кто не читает, милости просим <a href="http://twitter.com/vredniy" rel="nofollow">дружить в твиттере</a>.<span id="more-911"></span></p>
<p>Встретились мы сначала с генеральным директором, он рассказал о проекте, пока его не буду называть, но это компания, которая занимается развитием сайта, посвященному туризму: туры, бронирование отелей, такси и прочей смежной тематикой. Обсудили нетехнические вопросы. Затем подошел старший программист и по большей части мы уже общались непосредственно с ним. Конечно, сказывалось отсутствие большого опыта программирования на ruby и ruby on rails, но на большую часть вопросов, как мне кажется, я ответил правильно. Вопросы были следующего характера: </p>
<ul>
<li>какие виды связей и как их создать в rails</li>
<li>чем отличается include от extend&#8217;а</li>
<li>имеется ли множественное наследование в ruby</li>
</ul>
<p>Параллельно с вопросами я рассказывал о своих проектах и на ruby, и на php. Рассказал почему захотел перейти с php на ruby, как решал задачу из предыдущего поста тоже рассказал <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Собеседование и Unobtrusive Javascript на Rails" class='wp-smiley colorbox-911' title="Собеседование и Unobtrusive Javascript на Rails" /> .</p>
<p>После собеседования мне дали тестовое задание, оно заключается в следующем: необходимо без сторонних гемов, плагинов и библиотек реализовать простое приложение по управлению записями (обычный CRUD), только все это дело должно располагаться на одной странице, все запросы должны происходить в фоне (ajax) с применением unobtrusive javascript&#8217;а. Еще мне нужно было засечь сколько времени займет все это дело. </p>
<p>На ознакомление с мат. частью (railscasts, guides.rubyonrails и пр.), так сказать, ушло около двух часов, на реализацию проекта столько же. Что получилось и ссылку на репозиторий вы можете увидеть в конце данной заметки.</p>
<p>Итак, начнем.<br />
Единственную &#171;плюшку&#187;, которую я применил в проекте был gem &#8216;twitter-bootstrap-rails&#8217; для придания &#171;красивости&#187;, на конечную функциональность он никак не повлиял. </p>
<p>Сначала, как и всегда, создаем проект <strong>rails new unobtrusive &#038;&#038; unobtrusive</strong>. Вписываем в <em>Gemfile</em>, что будем использовать twitter-bootstrap-rails <strong>gem &#8216;twitter-bootstrap-rails&#8217;</strong> и делаем <strong>bundle</strong>, чтобы обновить <em>Gemfile.lock</em></p>
<p>Далее установим нужные стили, js-файлы, написав в консоли <em>rails g bootstrap:install</em> и обновим наш шаблон <strong>application</strong> командой <em>rails g bootstrap:layout application fluid</em>.</p>
<p>Скаффолдом создадим все необходимое для задачи <em>rails g scaffold item name:string description:string</em>, теперь мы можем создавать, удалять и редактировать, но без ajax&#8217;а. Также давайте добавим красоты нашим item&#8217;ам <em>rails g bootstrap:themed Items</em>. Сейчас можно зайти на /items своего приложения и увидеть что получилось. Но нам пока рано останавливаться. </p>
<p>Давайте добавим валидацию, которую я упустил, в файл <strong>app/models/item.rb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Item <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><br />
&nbsp; validates_presence_of <span style="color:#ff3333; font-weight:bold;">:name</span>, <span style="color:#ff3333; font-weight:bold;">:description</span><br />
&nbsp; validates_uniqueness_of <span style="color:#ff3333; font-weight:bold;">:name</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Первой строкой мы добавляем, как, наверное, ясно из название, наличие и имени, и описания, второй мы проверям уникальность имени, чтобы не было двух айтемов с одним и тем же именем.</p>
<p>Далее давайте немного изменим нашу форму <strong>app/views/items/_form.html.erb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span>= form_for <span style="color:#0066ff; font-weight:bold;">@item</span>, <span style="color:#ff3333; font-weight:bold;">:remote</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:html</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'form-horizontal'</span> <span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &lt;div id=&quot;item_errors&quot; style=&quot;display:none; color: red&quot;&gt;&lt;/div&gt;<br />
<br />
&nbsp; &lt;fieldset&gt;<br />
&nbsp; &nbsp; &lt;legend&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= controller.<span style="color:#9900CC;">action_name</span>.<span style="color:#9900CC;">capitalize</span> <span style="color:#006600; font-weight:bold;">%&gt;</span> /Item&lt;/legend&gt;<br />
<br />
&nbsp; &nbsp; &lt;div class=&quot;control-group&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">label</span> <span style="color:#ff3333; font-weight:bold;">:name</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'control-label'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; &lt;div class=&quot;controls&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:name</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'text_field'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; &lt;/div&gt;<br />
&nbsp; &nbsp; &lt;/div&gt;<br />
<br />
&nbsp; &nbsp; &lt;div class=&quot;control-group&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">label</span> <span style="color:#ff3333; font-weight:bold;">:description</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'control-label'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; &lt;div class=&quot;controls&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">text_field</span> <span style="color:#ff3333; font-weight:bold;">:description</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'text_field'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; &lt;/div&gt;<br />
&nbsp; &nbsp; &lt;/div&gt;<br />
<br />
&nbsp; &nbsp; &lt;div class=&quot;form-actions&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= f.<span style="color:#9900CC;">submit</span> <span style="color:#0000FF; font-weight:bold;">nil</span>, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'btn btn-primary'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&lt;%</span>= link_to <span style="color:#996600;">'Cancel'</span>, items_path, :<span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'btn'</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp; &lt;/div&gt;<br />
&nbsp; &lt;/fieldset&gt;<br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></div></td></tr></tbody></table></div>
<p>Небольшого изменения коснулась первоя строка, а именно добавился атрибут <strong>:remote => true</strong>, что сообщает рельсам задейстовать ujs (unobtrusive javascript). Также был добавлен тег с id item_errors, где мы будем выводить все ошибки валидации нашей модели.</p>
<p>Так как у нашего приложение будет только одна страница, можно смело избавляться от других вьюшек, заодно изменим наш контроллер <strong>app/controllers/items_controller.rb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> ItemsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController<br />
<br />
&nbsp; before_filter <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@items</span> = Item.<span style="color:#9900CC;">all</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@item</span> = Item.<span style="color:#9900CC;">new</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; before_filter <span style="color:#ff3333; font-weight:bold;">:find_an_item</span>, <span style="color:#ff3333; font-weight:bold;">:only</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:edit</span>, <span style="color:#ff3333; font-weight:bold;">:update</span>, <span style="color:#ff3333; font-weight:bold;">:destroy</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> index<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> create<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@item</span> = Item.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:item</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@item</span>.<span style="color:#9900CC;">save</span><br />
&nbsp; &nbsp; &nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Successfully created item.&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@items</span> = Item.<span style="color:#9900CC;">all</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> edit<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@items</span> = Item.<span style="color:#9900CC;">all</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> update<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@item</span>.<span style="color:#9900CC;">update_attributes</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:item</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Successfully updated item.&quot;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@items</span> = Item.<span style="color:#9900CC;">all</span><br />
&nbsp; &nbsp; render <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'create'</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> destroy<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@item</span>.<span style="color:#9900CC;">destroy</span><br />
&nbsp; &nbsp; flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#996600;">&quot;Successfully destroyed item.&quot;</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@items</span> = Item.<span style="color:#9900CC;">all</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; protected <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> find_an_item<br />
&nbsp; &nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@item</span> = Item.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Тут я, конечно, перемудрил с before_filter&#8217;ами, но это то, как смог сделать за два часа. Как видите, контроллер шан стал намного полегче от того состояния, в котором он был после скаффолдинга: мы избавились от редиректов и вынести многое в before_filter&#8217;ы.</p>
<p>Далее я добавил в шаблон <strong>app/view/layouts/application.html.erb</strong> рядом с тем где выводится контент экшнов, вывод flash сообщения.</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span9&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;flash_notice&quot;</span> <span style="color: #000066;">style</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;color:green&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> yield %&gt;</span></div></td></tr></tbody></table></div>
<p>Это не весь шаблон, а только измененная его часть. </p>
<p>Дело за вьюшками, создадим <strong>_items.html.erb</strong></p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">table</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;table table-striped&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">thead</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>ID<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Name<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Description<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Actions<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">thead</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tbody</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;% @items.each do |item| %&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> item.<span style="color: #000066;">id</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> link_to item.<span style="color: #000066;">name</span>, item_path<span style="color: #66cc66;">&#40;</span>item<span style="color: #66cc66;">&#41;</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> item.description %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> link_to <span style="color: #ff0000;">'Edit'</span>, edit_item_path<span style="color: #66cc66;">&#40;</span>item<span style="color: #66cc66;">&#41;</span>, :<span style="color: #000066;">class</span> <span style="color: #66cc66;">=</span>&gt;</span> 'btn btn-mini', :remote =&gt; true %&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> link_to <span style="color: #ff0000;">'Destroy'</span>, item_path<span style="color: #66cc66;">&#40;</span>item<span style="color: #66cc66;">&#41;</span>, :<span style="color: #000066;">method</span> <span style="color: #66cc66;">=</span>&gt;</span> :delete, :confirm =&gt; 'Are you sure?', :class =&gt; 'btn btn-mini btn-danger', :remote =&gt; true %&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;% end %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tbody</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">table</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Здесь нет тоже ничего необычного, кроме атрибута <strong>:remote => true</strong> у ссылок. Тем самым мы сообщаем рельсам, чтобы они инициировали ajax запрос, вместо обычного get&#8217;а.</p>
<p>Так как мы создали все необходимые partial&#8217;ы, мы модем изменить наш index view.</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;item_form&quot;</span>&gt;&lt;%<span style="color: #66cc66;">=</span> render <span style="color: #ff0000;">'form'</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>Items<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;items_list&quot;</span>&gt;&lt;%<span style="color: #66cc66;">=</span> render <span style="color: #ff0000;">'items'</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Который только собирает воедино нашу форму и список айтемов. Если вы запустите сейчас приложение и попытаетесь создать что-либо или отредактировать, получите множество сообщений об ошибках, связанных с отсутствием нужных шаблонов (если вы удалили все вьюшки, кроме <strong>index.html.erb</strong>).</p>
<p>Теперь переходим к магии: вмето того, чтобы отдавать html файлы, мы будем отдавать javascript, который rails вставит в нушное место. Вместо create.html.erb, у нас будет <strong>app/views/items/create.js.erb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@item</span>.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">any</span>? <span style="color:#006600; font-weight:bold;">-%&gt;</span><br />
&nbsp; $(&quot;#flash_notice&quot;).hide(300);<br />
&nbsp; $(&quot;#item_errors&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span>@item.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">full_messages</span>.<span style="color:#9900CC;">join</span> <span style="color:#996600;">'&lt;br&gt;'</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">html_safe</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;);<br />
&nbsp; $(&quot;#item_errors&quot;).show(300);<br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">else</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span><br />
&nbsp; $(&quot;#item_errors&quot;).hide(300);<br />
&nbsp; $(&quot;#flash_notice&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span>flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;);<br />
&nbsp; $(&quot;#flash_notice&quot;).show(300);<br />
&nbsp; $(&quot;:input[type=text]&quot;).val('');<br />
&nbsp; $(&quot;#items_list&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span>render <span style="color:#996600;">'items'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;);<br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span></div></td></tr></tbody></table></div>
<p>Вкратце мы делаем следующее: если есть ошибки, то выводим их, если нет, то очищаем наши текстовые поля и обновляем список айтемов.</p>
<p>Самая длинная строчка в этом файле мне не очень понравилась, может можно как-то попроще, покороче?</p>
<p>Если запустить наше приложение, то вы сможете создавать новые записи, видеть сообщения об успешном или неуспешном (если возникли ошибки валидации) создании.</p>
<p>Также поступим с двумя оствшимися вьюшками <strong>app/views/items/edit.js.erb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$(&quot;#item_form&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span>render <span style="color:#996600;">'form'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;);</div></td></tr></tbody></table></div>
<p>Где мы просто обновляем наш список элементов.</p>
<p>и <strong>app/views/items/destroy.js.erb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$(&quot;#item_errors&quot;).hide();<br />
$(&quot;#flash.notice&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span>flash<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:notice</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;).show();<br />
$(&quot;#items_list&quot;).html(&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= escape_javascript<span style="color:#006600; font-weight:bold;">&#40;</span> render <span style="color:#996600;">'items'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;);</div></td></tr></tbody></table></div>
<p>Вот и все <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Собеседование и Unobtrusive Javascript на Rails" class='wp-smiley colorbox-911' title="Собеседование и Unobtrusive Javascript на Rails" />  Заранее хочу извиниться за сумбурное, местами беглое, изложение, но я сейчас нахожусь в ожидании ответа от работодателя и не могу спокойно сидеть на месте <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Собеседование и Unobtrusive Javascript на Rails" class='wp-smiley colorbox-911' title="Собеседование и Unobtrusive Javascript на Rails" /> .</p>
<p>Репозиторий доступен, как всегда на <a href="https://github.com/vredniy/unobtrusive-javascript-rails" rel="nofollow">github</a>, работающее приложение на <a href="http://vredniy-unobtrusive.herokuapp.com/items" rel="nofollow">heroku</a></p>
<p>P.S. деплой на heroku</p>
<ul>
<li>запускаем <em>RAILS_ENV=production bundle exec rake assets:precompile</em>, чтобы скомпилировать наши стили и javascript&#8217;ы</li>
<li>заменяем в <strong>Gemfile</strong> sqlite3 на pg и далеем <em>bundle</em></li>
<li>создаем приложение на heroku <em>heroku create &#8212;stack cedar</em> (у вас приложение должно быть под git&#8217;ом и вы должны войти в heroku аккаунт)</li>
<li><em>git push heroku master</em> отправляем наше приложение за тысячи километров <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Собеседование и Unobtrusive Javascript на Rails" class='wp-smiley colorbox-911' title="Собеседование и Unobtrusive Javascript на Rails" /> </li>
<li>на heroku сайт пишут, что нужно сделать <em>heroku run rake db:migrate<br />
</em>, но у меня с этим не вышло, поэтому я запустил эту же команду в фоновом режиме <em>heroku run:detached rake db:migrate</em></li>
<li>открываем приложение</li>
<li>наслаждаемся</li>
<li>и еще раз наслаждаемся <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Собеседование и Unobtrusive Javascript на Rails" class='wp-smiley colorbox-911' title="Собеседование и Unobtrusive Javascript на Rails" /> </li>
</ul>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/KqFyc2hh0cg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/03/unobtrusive-javascript-rails/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/03/unobtrusive-javascript-rails/</feedburner:origLink></item>
		<item>
		<title>Поиграем? или совместное использование ruby и php</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/jzbUm7uiAY4/</link>
		<comments>http://vredniy.ru/2012/03/lets-game-with-ruby-and-php/#comments</comments>
		<pubDate>Sat, 17 Mar 2012 14:14:35 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[алгоритмы]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=901</guid>
		<description><![CDATA[Сегодня заметка будет посвящена теме далекой от веб-программирования, она будет посвящена немного алгоритмам, немного парсингу и немного Mongodb. Будем сегодня играть в игру. Часто по вечерам мы с женой играем в приложение на iPad&#8217;е под названием Словомания. Смысл в нем, как вы, наверное, заметили из названия, поиск слов. На входе матрица 4х4, можно начать из [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F03%2Flets-game-with-ruby-and-php%2F"><br />
				<img class="colorbox-901"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F03%2Flets-game-with-ruby-and-php%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=mongodb,php,redis,ruby&amp;b=2" height="61" width="50" title="Поиграем? или совместное использование ruby и php" alt=" Поиграем? или совместное использование ruby и php" /><br />
			</a>
		</div>
<p>Сегодня заметка будет посвящена теме далекой от веб-программирования, она будет посвящена немного алгоритмам, немного парсингу и немного Mongodb. Будем сегодня играть в игру.<span id="more-901"></span></p>
<p>Часто по вечерам мы с женой играем в приложение на iPad&#8217;е под названием Словомания. <img src="http://vredniy.ru/wp-content/uploads/2012/03/slovomania.jpeg" alt=" Поиграем? или совместное использование ruby и php" title="slovomania" width="276" height="275" class="aligncenter size-full wp-image-902 colorbox-901" /> Смысл в нем, как вы, наверное, заметили из названия, поиск слов. На входе матрица 4х4, можно начать из любой клетки и задействовать соседние по одному разу, чтобы отыскать имеющееся у них в словаре слово (в том словаре есть и наречия, и глаголы, и прилагательные, и конечно же существительные).</p>
<p>Задача: отыскать все слова. Но я немного облегчу себе задачу, потому как по примерным подсчетам в матрице 4х4 всевозможных комбинаций поиска слова около 16 миллионов, что даже по скромным подсчетам и при словаре в ~160 тысяч слов займет около 5 часов. В данной заметке мы будем использовать матрицу 3х3, что сокращает количество комбинаций до 8 с небольшим тысяч, что вполне приемлимо, но недостаточно быстро, для одной игры, которая длится около минуты. Да и плевать, для меня главное решить задачу, хоть и читерить в игре не получится ).</p>
<p>Для начала отыщем все возможные комбинации, для этого воспользуемся php-скриптом <a href="/2011/02/depth-first-search-php/">поиска в ширину</a>, немного его изменив для наших нужд. На выходе должны получить файл, где в каждой строке одна комбинация.</p>
<p>Цифры на матрице я обозначил от 1 до 9 (3х3), поэтому в выходном файле будут строки подобного вида &#8212; 1,2,3,6,5,4,7,8,9.</p>
<p>Но сначала нам пригодится небольшой скрипт, который поможет построить граф для таблицы 3х3.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">for</span> i <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span>..<span style="color:#006666;">9</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;%-2s&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> i<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> i <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">3</span> == <span style="color:#006666;">0</span> <span style="color:#9966CC; font-weight:bold;">then</span> <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>На выходе получим таблицу</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">1 2 3<br />
4 5 6<br />
7 8 9</div></td></tr></tbody></table></div>
<p>которая поможет нам построить граф, ключами массива которого будут вершины &#171;откуда&#187;, значениями &#8212; точки &#171;куда&#187;, мы можем попасть из данной вершины. Из таблицы следует, что из точки 1, мы можем попасть в точки: 2,5 (по диагонали тоже можно) и 4. Так нам нужно описать каждую вершину графа.</p>
<div class="codecolorer-container php railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <br />
<span style="color: #000088;">$paths</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009933; font-style: italic;">/**<br />
* рекурсивный поиск в глубину<br />
*<br />
* @param $graph array наш граф<br />
* @param $start string точка &quot;откуда&quot;<br />
* @param $end string точка &quot;куда&quot;<br />
* @param $path array массив предыдущих шагов<br />
**/</span><br />
<span style="color: #000000; font-weight: bold;">function</span> find_path<span style="color: #009900;">&#40;</span><span style="color: #000088;">$graph</span><span style="color: #339933;">,</span> <span style="color: #000088;">$start</span><span style="color: #339933;">,</span> <span style="color: #000088;">$end</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$paths</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000088;">$path</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$start</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$start</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$end</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #000088;">$path</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$graph</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$start</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #666666; font-style: italic;"># находим всех соседей<br />
</span> &nbsp;<span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$graph</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$start</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$node</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$node</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$newpath</span> <span style="color: #339933;">=</span> find_path<span style="color: #009900;">&#40;</span><span style="color: #000088;">$graph</span><span style="color: #339933;">,</span> <span style="color: #000088;">$node</span><span style="color: #339933;">,</span> <span style="color: #000088;">$end</span><span style="color: #339933;">,</span> <span style="color: #000088;">$path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$newpath</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$paths</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$newpath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># получившийся граф<br />
</span><span style="color: #000088;">$graph</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; <span style="color: #0000ff;">'1'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'4'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'2'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'3'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'4'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'3'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'4'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'7'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'8'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'5'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'1'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'3'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'4'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'7'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'6'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'3'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'9'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'7'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'4'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'5'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'8'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'8'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'4'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'7'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'9'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #0000ff;">'9'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'5'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'6'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'8'</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># циклы по всем вершинам графа,<br />
</span><span style="color: #666666; font-style: italic;"># каждая вершина может быть начальной и конечной<br />
</span><span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">9</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> &nbsp;<br />
&nbsp; <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$j</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span> <span style="color: #339933;">&lt;=</span> <span style="color: #cc66cc;">9</span><span style="color: #339933;">;</span> <span style="color: #000088;">$j</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; find_path<span style="color: #009900;">&#40;</span><span style="color: #000088;">$graph</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span>string<span style="color: #009900;">&#41;</span> <span style="color: #000088;">$j</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># избавляемся от дубликатов<br />
</span><span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_unique</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$paths</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>Количество комбинаций: &quot;</span><span style="color: #339933;">,</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #666666; font-style: italic;"># записываем результаты в файл<br />
</span><span style="color: #000088;">$fh</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'combinations.dat'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'a'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fh</span><span style="color: #339933;">,</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$result</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fh</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>В коде старался комментировать каждый момент, поэтому, думаю, должно быть понятно. На выходе у нас файлы <em>combinations.dat</em> с 8175 строками из всевозможных комбинаций.</p>
<p>Теперь давайте подготовим наш словарь. Я скачал какой-то орфографический словарь, каждая строка которого предствляла собой следующее</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">жопа#ж`опа%ж`опа, -ы</div></td></tr></tbody></table></div>
<p>Я решил сохранить два первый слова, точнее слово и ударение (которое в данном проекте не используется). Первое слово отделено от второго #, второе от остального %. По мере парсинга словаря, мы будем записывать все слова в нашу mongo базу данных для быстрого поиска по ней в дальнейшем.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># coding: utf-8</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo_mapper'</span><br />
<br />
MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'words'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Word<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
<br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word2</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
f = <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'./dic.txt'</span>, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># цикл по всем строкам словаря</span><br />
f.<span style="color:#9900CC;">lines</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; word, word2 = line.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'#'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># отделяем первое слово</span><br />
&nbsp; word2 = word2.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'%'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#008000; font-style:italic;"># и второе</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{word} #{word2}<span style="color:#000099;">\n</span>&quot;</span><br />
&nbsp; <br />
&nbsp; <span style="color:#008000; font-style:italic;"># и сохраняем его</span><br />
&nbsp; Word.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><br />
&nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:word</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> word,<br />
&nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:word2</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> word2<br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Если вам лень запускать подобный скрипт, то в корне проекта лежит файл <em>words.json</em>, содержащий все слова, вы можете импортировать его в свою mongo базу командой</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mongoimport -d DB -c COLLECTION words.json</div></td></tr></tbody></table></div>
<p>.<br />
Далее, чтобы ускорить и без того медленное приложение, нужно создать индекс в базе на поле word, запускаем mongo-терминал, выбираем базу данных <em>use DB</em> и пишем следующее</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">db.COLLECTION.ensureIndex({word: 1})</div></td></tr></tbody></table></div>
<p>, где DB &#8212; имя ваше базы данных, а COLLECTION &#8212; имя коллекции.</p>
<p>Итак, переходим к завершающей части &#8212; моменту истины, так сказать, поиску слов.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># encoding: utf-8</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo_mapper'</span><br />
<br />
MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'words'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Word<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
<br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word2</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#008000; font-style:italic;"># файл с полученным в предыдущих шагах комбинациями</span><br />
COMBINATIONS_FILE = <span style="color:#996600;">'./combinations.dat'</span><br />
<span style="color:#008000; font-style:italic;"># файл с результатами</span><br />
OUTPUT_FILE = <span style="color:#996600;">'./results.dat'</span><br />
<br />
<span style="color:#008000; font-style:italic;"># наше игровое поле</span><br />
alphabet = <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; к о ж<br />
&nbsp; а п у<br />
&nbsp; а р р<br />
<span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
<span style="color:#008000; font-style:italic;"># поиск текущего слова в словаре</span><br />
<span style="color:#9966CC; font-weight:bold;">def</span> find_a_word<span style="color:#006600; font-weight:bold;">&#40;</span>word<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; w = Word.<span style="color:#9900CC;">where</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:word</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> word<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">first</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> w<br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> w.<span style="color:#9900CC;">word</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">return</span> <span style="color:#0000FF; font-weight:bold;">nil</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#008000; font-style:italic;"># из комбинации, учитывая alphabet, составляем &quot;слово&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">def</span> number_to_letters<span style="color:#006600; font-weight:bold;">&#40;</span>alphabet, line<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; letters = line.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">','</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; word = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; letters.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>letter<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; word <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> alphabet<span style="color:#006600; font-weight:bold;">&#91;</span>letter.<span style="color:#9900CC;">to_i</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; word.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#008000; font-style:italic;"># основной цикл приложение</span><br />
<span style="color:#008000; font-style:italic;"># проходимся во всему списку комбинаций</span><br />
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>COMBINATIONS_FILE, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; f.<span style="color:#9900CC;">lines</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># составляем слово</span><br />
&nbsp; &nbsp; n_t_l = number_to_letters<span style="color:#006600; font-weight:bold;">&#40;</span>alphabet, line<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># находим в бд</span><br />
&nbsp; &nbsp; result = find_a_word<span style="color:#006600; font-weight:bold;">&#40;</span>n_t_l<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> result.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#9966CC; font-weight:bold;">then</span> <span style="color:#008000; font-style:italic;"># если нашли</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> n_t_l <span style="color:#008000; font-style:italic;"># выводим его </span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>OUTPUT_FILE, <span style="color:#996600;">'a'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>output<span style="color:#006600; font-weight:bold;">|</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; output.<span style="color:#CC0066; font-weight:bold;">puts</span> n_t_l <span style="color:#008000; font-style:italic;"># и записываем в файл</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span> <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>После этого запускаем скрипт ruby find-words.rb, откидываемся на скпинку стула и ждем результат. Начнут появляться на экране слова, которые были найдены этим скриптом, возможны повторения, потому что одно слово может быть составлено из разных комбинаций.</p>
<p>Удачи в кодинге и побольше интересных задач, которые вам под силу решить <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Поиграем? или совместное использование ruby и php" class='wp-smiley colorbox-901' title="Поиграем? или совместное использование ruby и php" /> .</p>
<p>P.S.: репозиторий, как всегда, доступен на <a href="https://github.com/vredniy/game-ruby-php" rel="nofollow">github</a>.</p>
<hr />
<p><a name="update">update 25.03.2012</a><br />
Все-таки намного интереснее заставить приложение работать как задумывалось, а именно, чтобы оно находило слова из матрицы 4х4. Для этого мною были предприняты следующие меры:</p>
<ul>
<li>удаление лишних слов из словаря</li>
<li>оптимизация самого алгоритма</li>
<li>сужение диапазона поиска</li>
</ul>
<h3>Удаление лишних слов из словаря</h3>
<p>Пробежался я по словарю и понял, что там много слово, содержащих дефисы, скобки, пробелы. Некоторые слова состояли из одной-двух букв. Я решил с ними попрощаться, благо mongo поддерживает регулярные выражения.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'words'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Word<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#008000; font-style:italic;">#s = Word.all(:word =&gt; /^.*[-А-Я].*$/).each do |word|</span><br />
<span style="color:#008000; font-style:italic;">#s = Word.all(:word =&gt; /^.*[ё].*$/).each do |word|</span><br />
<span style="color:#008000; font-style:italic;">#s = Word.all(:word =&gt; /^.*[\(\)\.\s+].*$/).each do |word|</span><br />
s = Word.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:word</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">/</span>^.<span style="color:#006600; font-weight:bold;">*</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">-</span>,.:;<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#006600; font-weight:bold;">*</span>$<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>word<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; word.<span style="color:#9900CC;">destroy</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Запускаем и удаляем ненужные слова, из 160 тысяч слов, останется 140 тысяч, неплохо <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Поиграем? или совместное использование ruby и php" class='wp-smiley colorbox-901' title="Поиграем? или совместное использование ruby и php" /> </p>
<h3>Оптимизация самого алгоритма</h3>
<p>Самый быстрый код &#8212; это мало кода. Поэтому максимально постараемся избавиться от методов. Выбросив все лишнее получим следующее.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># encoding: utf-8</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo_mapper'</span><br />
<br />
MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'words'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Word<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
<br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:word</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
COMBINATIONS_FILE = <span style="color:#996600;">'./game.dat'</span><br />
<br />
Alphabet = <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#123;</span><br />
ё ж е т<br />
у ч е р<br />
к о ю т<br />
р м п ь<br />
<span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
start = _start = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
counter = <span style="color:#006666;">0</span><br />
<br />
combinations = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>COMBINATIONS_FILE, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">while</span> <span style="color:#006600; font-weight:bold;">&#40;</span>line = f.<span style="color:#CC0066; font-weight:bold;">gets</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; counter <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span><br />
&nbsp; &nbsp; &nbsp; line = line.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">','</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">3</span>..<span style="color:#006666;">9</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9966CC; font-weight:bold;">include</span>? line.<span style="color:#9900CC;">size</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w = Word.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:word</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> line.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>l<span style="color:#006600; font-weight:bold;">|</span> Alphabet<span style="color:#006600; font-weight:bold;">&#91;</span>l.<span style="color:#9900CC;">to_i</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">join</span> <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; line = <span style="color:#0000FF; font-weight:bold;">nil</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; combinations <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> w.<span style="color:#9900CC;">word</span> <span style="color:#9966CC; font-weight:bold;">unless</span> w.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> counter <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">100</span>_000 == <span style="color:#006666;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> combinations.<span style="color:#9900CC;">join</span> <span style="color:#996600;">' '</span> <span style="color:#9966CC; font-weight:bold;">unless</span> combinations.<span style="color:#9900CC;">empty</span>?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; combinations = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">&quot;#{Time.now - start} - #{counter}&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; start = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">-</span> _start<span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>Код получился намного &#171;легче&#187; и быстрее. </p>
<h3>Сужаем диапазон поиска</h3>
<p>Чтобы хоть как-то еще прибавить скорость, я сузил длину слова, теперь проверяются только строки от 3 до 9 символов, это тоже очень хорошо сужает конечную выборку.</p>
<h3>Обратная связь приветствуется</h3>
<p>Если вы видите, что есть какие-то неточности или гипотезы по поводу оптимизации быстродействия кода, то всегда пожалуйста, я открыт для обсуждения всегда.</p>
<p>Не хочу быть излишне самоуверенным, но мне, кажется, что сейчас весь алгоритм упирается в &#171;железо&#187;, точнее скорость считывания с диска. (К сожалению, у меня нет ssd диска, чтобы это проверить).</p>
<p>В заключение картинка с какой скоростью отрабатывает скрипт. Первое число на картинке &#8212; количество секунд на 100_000 строк, считанных из файла и проверенных с каждой строкой словаря, содержащего ~ 140.000 слов. Второе число &#8212; сколько строк уже просмотрено. Всего комбинаций получилось, если рассматривать поле 4х4 &#8212; 12.000.000 штук. <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Поиграем? или совместное использование ruby и php" class='wp-smiley colorbox-901' title="Поиграем? или совместное использование ruby и php" /> </p>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/03/optimization.jpeg" alt=" Поиграем? или совместное использование ruby и php" title="ruby mongo graph" width="338" height="479" class="aligncenter size-full wp-image-906 colorbox-901" /></p>
<hr />
<a name="update-redis"><br />
<h3>Обновление от 27.03.2012 (redis)</h3>
<p></a><br />
Пришла еще одна мысля по оптимизации данного приложения, вместо mongodb, я решил попробовать использовать redis &#8212; очень быстрое ключ-значение хранилище. </p>
<p>Сначала нужно экспортировать базу mongo в redis, тут ничего сложного (с учетом того, что у вас и сам redis установлен, и redis gem).</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo_mapper'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'redis'</span><br />
<br />
MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'words'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> Word<br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
<br />
&nbsp; &nbsp;key <span style="color:#ff3333; font-weight:bold;">:word</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
redis = Redis.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:host</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;127.0.0.1&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:port</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">6379</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
Word.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>w<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; w = w.<span style="color:#9900CC;">word</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> <span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">-</span>А<span style="color:#006600; font-weight:bold;">-</span>Я\<span style="color:#006600; font-weight:bold;">&#40;</span>\<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">/</span>.<span style="color:#9900CC;">match</span> w<br />
&nbsp; &nbsp; redis.<span style="color:#9900CC;">set</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;word:#{w}&quot;</span>, w<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Пробегаемся по всем словам из коллекции mongodb и сохраняем все слова в redis под ключом word:СЛОВО, чтобы не перепутать с другими ключами.</p>
<p>Теперь основной файл, только в качестве хранилища мы будем использовать redis.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># encoding: utf-8</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'redis'</span><br />
redis = Redis.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:host</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;127.0.0.1&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:port</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">6379</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
COMBINATIONS_FILE = <span style="color:#996600;">'./game.dat'</span><br />
<br />
Alphabet = <span style="color:#006600; font-weight:bold;">%</span>w<span style="color:#006600; font-weight:bold;">&#123;</span><br />
ё ж е т<br />
у ч е р<br />
к о ю т<br />
р м п ь<br />
<span style="color:#006600; font-weight:bold;">&#125;</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">for</span> i <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span>..<span style="color:#006666;">16</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <br />
&nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;%-3s&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> Alphabet<span style="color:#006600; font-weight:bold;">&#91;</span>i<span style="color:#006600; font-weight:bold;">-</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> i <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">4</span> == <span style="color:#006666;">0</span> <span style="color:#9966CC; font-weight:bold;">then</span> <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span> <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
start = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
_start = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
counter = <span style="color:#006666;">0</span><br />
<br />
combinations = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
lines = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>COMBINATIONS_FILE, <span style="color:#996600;">'r'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; f.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>line<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; counter <span style="color:#006600; font-weight:bold;">+</span>= <span style="color:#006666;">1</span><br />
&nbsp; &nbsp; line = line.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">','</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">3</span>..<span style="color:#006666;">9</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9966CC; font-weight:bold;">include</span>? line.<span style="color:#9900CC;">size</span><br />
&nbsp; &nbsp; &nbsp; w = redis.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;word:&quot;</span> <span style="color:#006600; font-weight:bold;">+</span> line.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>l<span style="color:#006600; font-weight:bold;">|</span> Alphabet<span style="color:#006600; font-weight:bold;">&#91;</span>l.<span style="color:#9900CC;">to_i</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; line = <span style="color:#0000FF; font-weight:bold;">nil</span><br />
&nbsp; &nbsp; &nbsp; combinations <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> w <span style="color:#9966CC; font-weight:bold;">unless</span> w.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> counter <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">100</span>_000 == <span style="color:#006666;">0</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> combinations.<span style="color:#9900CC;">uniq</span>.<span style="color:#9900CC;">join</span> <span style="color:#996600;">' '</span> <span style="color:#9966CC; font-weight:bold;">unless</span> combinations.<span style="color:#9900CC;">empty</span>?<br />
&nbsp; &nbsp; &nbsp; combinations = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#996600;">&quot;#{Time.now - start} - #{counter}&quot;</span><br />
&nbsp; &nbsp; &nbsp; start = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">-</span> _start<span style="color:#006600; font-weight:bold;">&#41;</span><br />
<span style="color:#CC0066; font-weight:bold;">p</span> counter</div></td></tr></tbody></table></div>
<p>Вывод: приложение стало заметно быстрее (в 3-5 раз), скриншот прилагаю.<br />
<img src="http://vredniy.ru/wp-content/uploads/2012/03/redis-game.png" alt="redis game Поиграем? или совместное использование ruby и php" title="redis-ruby-game" width="651" height="375" class="aligncenter size-full wp-image-908 colorbox-901" /></p>
<p>Надеюсь, смогу добиться скорость выполнения в раза больше, чем сейчас. Мне нужно чтобы приложение проходило по всем комбинациям, сравнивая со всем словами в словаре и тратило при этом меньше минуты, сейчас около 3х.</p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/jzbUm7uiAY4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/03/lets-game-with-ruby-and-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/03/lets-game-with-ruby-and-php/</feedburner:origLink></item>
		<item>
		<title>arbor.js: красивые графы на стороне клиента с помощью Ruby</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/7JSrEIafBLo/</link>
		<comments>http://vredniy.ru/2012/02/arbor-js-ruby-sinatra/#comments</comments>
		<pubDate>Sat, 25 Feb 2012 13:24:37 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[arborjs]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=892</guid>
		<description><![CDATA[Сегодня мы займемся рисованием интерактивного графа на стороне клиента. На графе, чтобы далеко не ходить в поисках данных, будет изображать тех, кого читаем в твиттере. Требования Граф должен выглядеть привлекательно При наведении на вершину графа мы должны получать дополнительную информацию, в данном приложении &#8212; это имя твиттерянина, картинка профиля, количество дней прошедших с регистрации и [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Farbor-js-ruby-sinatra%2F"><br />
				<img class="colorbox-892"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Farbor-js-ruby-sinatra%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=arborjs,mongodb,ruby,sinatra&amp;b=2" height="61" width="50" title="arbor.js: красивые графы на стороне клиента с помощью Ruby" alt=" arbor.js: красивые графы на стороне клиента с помощью Ruby" /><br />
			</a>
		</div>
<p>Сегодня мы займемся рисованием интерактивного графа на стороне клиента. На графе, чтобы далеко не ходить в поисках данных, будет изображать тех, кого читаем в твиттере. </p>
<h3>Требования</h3>
<ul>
<li>Граф должен выглядеть привлекательно</li>
<li>При наведении на вершину графа мы должны получать дополнительную информацию, в данном приложении &#8212; это имя твиттерянина, картинка профиля, количество дней прошедших с регистрации и дата регистрации</li>
<li>Backend&#8217;ом будет выступать Mongo с Rack прослойкой в виде Sinatra</li>
</ul>
<h3>Этапы разработки</h3>
<ul>
<li>Определяемся с инструментарием</li>
<li>Немного проектирования</li>
<li>Регистрируем наше Twitter приложение</li>
<li>Сохраняем всех наших друзей в Mongo</li>
<li>Шаблоны, скрипты и стили на клиенте</li>
</ul>
<h5>Определяемся с инструментарием</h5>
<p>В пункте с требованиями я уже сказал, что мы будем использовать Mongo в связке MongoMapper&#8217;ом, для удобного хранения наших друзей с нужной нам информацией (именем, датой регистрации, картинкой и пр.). Для удобного взимодействия с Twitter API, используем gem Twitter, который предоставляет полный контроль через Twitter приложение.</p>
<h5>Немного проектирования</h5>
<p>Что мы имеем? На главной странице (/) будет отображаться сам граф, данные по средством ajax-запроса к серверу будут приходить от /json (данные будем возвращать в json&#8217;е). Обновлять список пользователей мы будем по адресу /friends (получаем список всех пользователей, которых мы читаем и запрашиваем их дополнительные данные, сохраняя все в базу). </p>
<h5>Регистрируем наше Twitter приложение</h5>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/02/twitter-application-800x614.png" alt="twitter application 800x614 arbor.js: красивые графы на стороне клиента с помощью Ruby" title="twitter application" width="600" height="460" class="aligncenter size-large wp-image-898 colorbox-892" />Т.к. все взаимодействие с Twitter API происходит через Twitter приложение, нам необходимо его создать, для этого заходим в <a href="https://dev.twitter.com/apps/new" rel="nofollow">раздел для разработчиков</a>. Заполняем обязательные поля и нажимаем кнопку &#171;Create your twitter application&#187;. Спустя несколько секунд мы оказываемся на странице созданного приложения. Прокрутив вниз, мы увидим кнопку &#171;Create my access token&#187;, нажав на которую мы заполним Access token и Access token secret для нашего приложения. Полученные ключи можно лицезреть на вкладке &#171;OAuth tool&#187; под заголовком &#171;OAuth Settings&#187;. Все четыре строчки нам понадобятся чуть позже.</p>
<h5>Сохраняем всех наших друзей в Mongo</h5>
<p>Итак, приступим непосредственно к написанию кода. К этому моменту у вас должно быть рабочее Twitter приложение, установленный Mongo (освещение установки выходит за рамки данной заметки).</p>
<p>Вначале, как всегда, стандартный <strong>./config.ru</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'./twitter.rb'</span><br />
run <span style="color:#6666ff; font-weight:bold;">Sinatra::Application</span></div></td></tr></tbody></table></div>
<p>Дальше создадим <strong>./Gemfile</strong>, который будет содержать все гемы, которые мы используем</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">source <span style="color:#ff3333; font-weight:bold;">:rubygems</span><br />
gem <span style="color:#996600;">'sinatra'</span><br />
gem <span style="color:#996600;">'twitter'</span><br />
<br />
gem <span style="color:#996600;">'mongo'</span><br />
gem <span style="color:#996600;">'bson_ext'</span><br />
gem <span style="color:#996600;">'mongo_mapper'</span></div></td></tr></tbody></table></div>
<p>После этого запустим <em>bundle install</em>, что создаст нам Gemfile.lock</p>
<p>А теперь наше приложение <strong>./twitter.rb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># encoding: UTF-8</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'twitter'</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mongo_mapper'</span></div></td></tr></tbody></table></div>
<p>Подключаем необходимые гемы.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Twitter.<span style="color:#9900CC;">configure</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>config<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp;config.<span style="color:#9900CC;">consumer_key</span> = <span style="color:#996600;">'YOUR_CONSUMER_KEY'</span><br />
&nbsp; &nbsp;config.<span style="color:#9900CC;">consumer_secret</span> = <span style="color:#996600;">'YOUR_CONSUMER_SECRET'</span><br />
&nbsp; &nbsp;config.<span style="color:#9900CC;">oauth_token</span> = <span style="color:#996600;">'YOUR_ACCESS_TOKEN'</span><br />
&nbsp; &nbsp;config.<span style="color:#9900CC;">oauth_token_secret</span> = <span style="color:#996600;">'YOUR_ACCESS_SECRET'</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Конфигурируем twitter (заполните строки выше теми данными, которые вы получили после регистрации twitter приложения), привязывая его к нашему приложению.</p>
<p>Теперь настроим MongoMapper, указав ему с какими данными мы хотим работать.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MongoMapper.<span style="color:#9900CC;">database</span> = <span style="color:#996600;">'users'</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">class</span> User <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">MongoMapper::Document</span><br />
<br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:screen_name</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:profile_image_url</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:followers_count</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:statuses_count</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:name</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:friends_count</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:lang</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:url</span><br />
&nbsp; key <span style="color:#ff3333; font-weight:bold;">:created_at</span>, <span style="color:#CC00FF; font-weight:bold;">DateTime</span><br />
<br />
&nbsp; <span style="color:#008000; font-style:italic;"># id location notifications profile_image_url profile_image_url_https profile_background_color </span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># followers_count default_profile time_zone is_translator utc_offset profile_background_image_url </span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># statuses_count profile_link_color name friends_count listed_count protected </span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># profile_use_background_image profile_background_image_url_https contributors_enabled lang </span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># profile_text_color follow_request_sent description profile_sidebar_border_color show_all_inline_media </span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># url verified default_profile_image created_at profile_background_tile favourites_count id_str</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># following profile_sidebar_fill_color geo_enabled screen_name</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Сначала указываем базу данных (&#8216;users&#8217;), дальше описываем поля. Закомментированные строки &#8212; это дополнительные поля, которые вы можете использовать при получении данных твиттер-пользователя.</p>
<p>Пришло время написать экшн, которые сохранит всех наших друзей в базе Mongo и здесь нет ничего сложного.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/friends'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; User.<span style="color:#9900CC;">collection</span>.<span style="color:#9900CC;">remove</span> <span style="color:#008000; font-style:italic;"># очищаем коллекцию</span><br />
<br />
&nbsp; friends = Twitter.<span style="color:#9900CC;">friend_ids</span> <span style="color:#008000; font-style:italic;"># получаем список всех друзей</span><br />
&nbsp; friend_ids = friends.<span style="color:#9900CC;">ids</span><br />
<br />
&nbsp; friend_ids.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>f<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#008000; font-style:italic;"># проходимся по каждому и</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; twi_user = Twitter.<span style="color:#9900CC;">user</span><span style="color:#006600; font-weight:bold;">&#40;</span>f<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#008000; font-style:italic;"># получаем данные, отправляет запрос на сервер Twitter'а</span><br />
&nbsp; &nbsp; &nbsp; User.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#008000; font-style:italic;"># заполняем поля</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:screen_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">screen_name</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:profile_image_url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">profile_image_url</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:followers_count</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">followers_count</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:statuses_count</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">statuses_count</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">name</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:friends_count</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">friends_count</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:lang</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">lang</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:url</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">url</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:created_at</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> twi_user.<span style="color:#9900CC;">created_at</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">Exception</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e <span style="color:#008000; font-style:italic;"># обрабатываем исключение</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> e.<span style="color:#9900CC;">message</span> &nbsp;<br />
&nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">puts</span> e.<span style="color:#9900CC;">backtrace</span>.<span style="color:#9900CC;">inspect</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@users</span> = User.<span style="color:#9900CC;">all</span> <span style="color:#008000; font-style:italic;"># получаем всех сохраненных пользователей</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:friends</span> <span style="color:#008000; font-style:italic;"># отображаем их</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Чтобы наш экшн отработал, на необхомо создать файл <strong>./views/friends.erb</strong> со следующим содержимым:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#0066ff; font-weight:bold;">@users</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>u<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#006600; font-weight:bold;">%&gt;</span><br />
&nbsp; &nbsp;&lt;h5&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= u.<span style="color:#9900CC;">name</span> <span style="color:#006600; font-weight:bold;">%&gt;</span> - <span style="color:#006600; font-weight:bold;">&lt;%</span>= u.<span style="color:#9900CC;">screen_name</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/h5&gt;<br />
&nbsp; &nbsp;&lt;img src=&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= u.<span style="color:#9900CC;">profile_image_url</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&quot;&gt;<br />
&nbsp; &nbsp;&lt;p&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= u.<span style="color:#9900CC;">created_at</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/p&gt;<br />
&nbsp; &nbsp;&lt;hr&gt;<br />
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></div></td></tr></tbody></table></div>
<p>Который не делает ничего более того, что отображает в цикле всех пользователей с картикой профиля. (Это нужно для того, чтобы убедиться в том, что все работает как ожидалось).</p>
<h5>Шаблоны, скрипты и стили на клиенте</h5>
<p>Сначала создадим шаблон для всех наших представлений, <strong>./views/layout.erb</strong>:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>Twitter friends (arbor.js + Ruby)<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/arbor.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/application.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/styles/application.css&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> yield %&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></td></tr></tbody></table></div>
<p>В котором мы подключаем библиотеку jQuery через Google CDN, файл arbor.js, который вы можете скачать <a href="https://github.com/samizdatco/arbor" rel="nofollow">отсюда</a> (данная библиотека используется нами для визуализации графа на стороне клиента).</p>
<p>Файл arbor.js необходимо положить в папку <strong>./public/js/arbor.js</strong></p>
<p>Далее напишем последний скрипт, который будет обрабатывать события отрисовки, drag&#038;drop&#8217;а и загрузки данных ajax&#8217;ом. (За основу взят пример с сайта arbor.js). <strong>./js/application.js</strong></p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br />77<br />78<br />79<br />80<br />81<br />82<br />83<br />84<br />85<br />86<br />87<br />88<br />89<br />90<br />91<br />92<br />93<br />94<br />95<br />96<br />97<br />98<br />99<br />100<br />101<br />102<br />103<br />104<br />105<br />106<br />107<br />108<br />109<br />110<br />111<br />112<br />113<br />114<br />115<br />116<br />117<br />118<br />119<br />120<br />121<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Renderer <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> canvas <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ctx <span style="color: #339933;">=</span> canvas.<span style="color: #660066;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;2d&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> particleSystem<br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> dom <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> that <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; init<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>system<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; particleSystem <span style="color: #339933;">=</span> system<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; particleSystem.<span style="color: #660066;">screenSize</span><span style="color: #009900;">&#40;</span>canvas.<span style="color: #660066;">width</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; particleSystem.<span style="color: #660066;">screenPadding</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">80</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// leave an extra 80px of whitespace per side</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; that.<span style="color: #660066;">initMouseHandling</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; redraw<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;white&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillRect</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">width</span><span style="color: #339933;">,</span> canvas.<span style="color: #660066;">height</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; particleSystem.<span style="color: #660066;">eachEdge</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>edge<span style="color: #339933;">,</span> pt1<span style="color: #339933;">,</span> pt2<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">strokeStyle</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;rgba(88,0,0, .133)&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">lineWidth</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">beginPath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">moveTo</span><span style="color: #009900;">&#40;</span>pt1.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> pt1.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">lineTo</span><span style="color: #009900;">&#40;</span>pt2.<span style="color: #660066;">x</span><span style="color: #339933;">,</span> pt2.<span style="color: #660066;">y</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">stroke</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; particleSystem.<span style="color: #660066;">eachNode</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>node<span style="color: #339933;">,</span> pt<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> w <span style="color: #339933;">=</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">;</span> &nbsp; <span style="color: #006600; font-style: italic;">//ширина квадрата</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'Я'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'yellow'</span> <span style="color: #339933;">:</span> node.<span style="color: #660066;">data</span>.<span style="color: #660066;">color</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillRect</span><span style="color: #009900;">&#40;</span>pt.<span style="color: #660066;">x</span><span style="color: #339933;">-</span>w<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> pt.<span style="color: #660066;">y</span><span style="color: #339933;">-</span>w<span style="color: #339933;">/</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> w<span style="color: #339933;">,</span>w<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//рисуем</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillStyle</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'Я'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'green'</span> <span style="color: #339933;">:</span> node.<span style="color: #660066;">data</span>.<span style="color: #660066;">color</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//цвет для шрифта</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">font</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'Я'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'bold 18px sans-serif'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'italic 13px sans-serif'</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//шрифт</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctx.<span style="color: #660066;">fillText</span> <span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span><span style="color: #339933;">,</span> pt.<span style="color: #660066;">x</span><span style="color: #339933;">+</span><span style="color: #CC0000;">8</span><span style="color: #339933;">,</span> pt.<span style="color: #660066;">y</span><span style="color: #339933;">+</span><span style="color: #CC0000;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//пишем имя у каждой точки</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; initMouseHandling<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> dragged <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> handler <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; moved<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> pos <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">offset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mouseP <span style="color: #339933;">=</span> arbor.<span style="color: #660066;">Point</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">pageX</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">left</span><span style="color: #339933;">,</span> e.<span style="color: #660066;">pageY</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">top</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nearest <span style="color: #339933;">=</span> particleSystem.<span style="color: #660066;">nearest</span><span style="color: #009900;">&#40;</span>_mouseP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>nearest.<span style="color: #660066;">node</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#status h1'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>nearest.<span style="color: #660066;">node</span>.<span style="color: #660066;">data</span>.<span style="color: #660066;">full_name</span><span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#status .image'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;img&gt;'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'src'</span><span style="color: #339933;">,</span> nearest.<span style="color: #660066;">node</span>.<span style="color: #660066;">data</span>.<span style="color: #660066;">image</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#status .ago'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span>nearest.<span style="color: #660066;">node</span>.<span style="color: #660066;">data</span>.<span style="color: #660066;">days</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&lt;br&gt;'</span> <span style="color: #339933;">+</span> nearest.<span style="color: #660066;">node</span>.<span style="color: #660066;">data</span>.<span style="color: #660066;">created_at</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; clicked<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> pos <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">offset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mouseP <span style="color: #339933;">=</span> arbor.<span style="color: #660066;">Point</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">pageX</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">left</span><span style="color: #339933;">,</span> e.<span style="color: #660066;">pageY</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">top</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged <span style="color: #339933;">=</span> particleSystem.<span style="color: #660066;">nearest</span><span style="color: #009900;">&#40;</span>_mouseP<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dragged <span style="color: #339933;">&amp;&amp;</span> dragged.<span style="color: #660066;">node</span> <span style="color: #339933;">!==</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged.<span style="color: #660066;">node</span>.<span style="color: #660066;">fixed</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mousemove'</span><span style="color: #339933;">,</span> handler.<span style="color: #660066;">dragged</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mouseup'</span><span style="color: #339933;">,</span> handler.<span style="color: #660066;">dropped</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; that.<span style="color: #660066;">redraw</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> pos <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">offset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> arbor.<span style="color: #660066;">Point</span><span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">pageX</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">left</span><span style="color: #339933;">,</span> e.<span style="color: #660066;">pageY</span><span style="color: #339933;">-</span>pos.<span style="color: #660066;">top</span><span style="color: #009900;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dragged <span style="color: #339933;">&amp;&amp;</span> dragged.<span style="color: #660066;">node</span> <span style="color: #339933;">!==</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> p <span style="color: #339933;">=</span> particleSystem.<span style="color: #660066;">fromScreen</span><span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged.<span style="color: #660066;">node</span>.<span style="color: #660066;">p</span> <span style="color: #339933;">=</span> p<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dropped<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dragged<span style="color: #339933;">===</span><span style="color: #003366; font-weight: bold;">null</span> <span style="color: #339933;">||</span> dragged.<span style="color: #660066;">node</span><span style="color: #339933;">===</span>undefined<span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dragged.<span style="color: #660066;">node</span> <span style="color: #339933;">!==</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> dragged.<span style="color: #660066;">node</span>.<span style="color: #660066;">fixed</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged.<span style="color: #660066;">node</span>.<span style="color: #660066;">tempMass</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">1000</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dragged <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mousemove'</span><span style="color: #339933;">,</span> handler.<span style="color: #660066;">dragged</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">unbind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'mouseup'</span><span style="color: #339933;">,</span> handler.<span style="color: #660066;">dropped</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mouseP <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">null</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">mousedown</span><span style="color: #009900;">&#40;</span>handler.<span style="color: #660066;">clicked</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>canvas<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">mousemove</span><span style="color: #009900;">&#40;</span>handler.<span style="color: #660066;">moved</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> that<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; &nbsp;<br />
<br />
&nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sys <span style="color: #339933;">=</span> arbor.<span style="color: #660066;">ParticleSystem</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1000</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">100</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0.5</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// create the system with sensible repulsion/stiffness/friction</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">renderer</span> <span style="color: #339933;">=</span> Renderer<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#viewport&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">// our newly created renderer will have its .init() method called shortly by sys...</span><br />
<br />
&nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">addNode</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Я'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">addNode</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Кто-то другой'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $.<span style="color: #660066;">getJSON</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/json'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>response<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>response.<span style="color: #660066;">nodes</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span>node<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">addNode</span><span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; days<span style="color: #339933;">:</span> node.<span style="color: #660066;">days</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; image<span style="color: #339933;">:</span> node.<span style="color: #660066;">image</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; full_name<span style="color: #339933;">:</span> node.<span style="color: #660066;">full_name</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; color<span style="color: #339933;">:</span> node.<span style="color: #660066;">color</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; created_at<span style="color: #339933;">:</span> node.<span style="color: #660066;">created_at</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.<span style="color: #660066;">addEdge</span><span style="color: #009900;">&#40;</span>node.<span style="color: #000066;">name</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Я'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
<br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">jQuery</span><span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>В строках 106-117 мы получаем данные с сервера, заполняя каждую ноду именем и данными, которые будет использовать далее.</p>
<p>Отрисовка происходит в строках 29-36, а обработка события перемещения мыши в 42-51, где мы сохраненные в ноде данные отображаем (для этого используем возможности движка по нахождению ближайшей к указателю мыши ноды).</p>
<p>Шаблон для отображения главной страницы <strong>./views/index.erb</strong></p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;status&quot;</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;image&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>Я<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;ago&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">p</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;clear&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">p</span>&gt;</span><br />
<span style="color: #009900;">&lt;canvas <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;viewport&quot;</span> <span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;1000&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;700&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span>canvas&gt;</span></div></td></tr></tbody></table></div>
<p>В нем мы создаем статусбар и канвас, в котором и будет отображать наш граф и обрабатывать события.</p>
<p>Добавим к нашему <strong>./twitter.rb</strong> последний штрих, точнее два, вывод главной страницы и отправка данных ajax&#8217;ом.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;erb :<span style="color:#996600;">'index'</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
get <span style="color:#996600;">'/json'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; content_type <span style="color:#ff3333; font-weight:bold;">:json</span><br />
&nbsp; users = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; User.<span style="color:#9900CC;">all</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>u<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; users <span style="color:#006600; font-weight:bold;">&lt;&lt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> u.<span style="color:#9900CC;">screen_name</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:full_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> u.<span style="color:#9900CC;">name</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:days</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">DateTime</span>.<span style="color:#9900CC;">now</span><span style="color:#006600; font-weight:bold;">-</span><span style="color:#CC00FF; font-weight:bold;">DateTime</span>.<span style="color:#9900CC;">strptime</span><span style="color:#006600; font-weight:bold;">&#40;</span>u.<span style="color:#9900CC;">created_at</span>.<span style="color:#9900CC;">to_s</span>, <span style="color:#996600;">'%Y-%m-%d'</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_i</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> u.<span style="color:#9900CC;">profile_image_url</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:color</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;#%06x&quot;</span> <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">rand</span> <span style="color:#006600; font-weight:bold;">*</span> 0xffffff<span style="color:#006600; font-weight:bold;">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:created_at</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> u.<span style="color:#9900CC;">created_at</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span><br />
&nbsp; &nbsp; nodes: users<br />
&nbsp; <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">to_json</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>В методе <em>/json</em> мы проходимся по списку всех пользователей, которых мы сохранили в методе <em>/friends</em> и собираем json объект, который и выводим с заголовком <em>content_type :json</em></p>
<p>Единственное, что может показаться странным, так это конструкция <em>(DateTime.now-DateTime.strptime(u.created_at.to_s, &#8216;%Y-%m-%d&#8217;)).to_i</em>, которая считает разницу в днях между днем регистрации пользователя и текущим днем, и конструкция <em>&#171;#%06x&#187; % (rand * 0xffffff)</em>, которая генерирует случайный цвет в формате #1234ab, остальные строки, надеюсь, прозрачны и легки к пониманию.</p>
<h3>Демонстрация и заключение</h3>
<p>Видео, демонстрирующее возможности разработонного приложения смотрите ниже, из него, я думаю, все станет понятно, что нельзя сказать о кучи текста и кода. Как говорят, лучше один раз увидеть, чем несколько раз прочитать.</p>
<p><object width="640" height="360"><param name="movie" value="http://www.youtube.com/v/-SX1AVO_bj0?version=3&amp;hl=ru_RU"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/-SX1AVO_bj0?version=3&amp;hl=ru_RU" type="application/x-shockwave-flash" width="640" height="360" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
В качестве заключения хочу сказать следующее: arbor.js &#8212; очень мощная библиотека для отрисовки графов на стороне клиента, которая загружает процессор на 100%, но позволяет, чертовка, визуализировать графы наглядно и красиво. Еще в данной заметке мы с вами познакомились очень поверхностно с Twitter гемом, который позволяет создавать приложения для взаимодействия с Twitter API. Надеюсь, потраченное на прочтение данной заметки, не было бесполезным <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile arbor.js: красивые графы на стороне клиента с помощью Ruby" class='wp-smiley colorbox-892' title="arbor.js: красивые графы на стороне клиента с помощью Ruby" />  и до новых встреч.</p>
<p>P.S.: ссылка на <a href="https://github.com/vredniy/arbor-twitter-sinatra" rel="nofollow">репозиторий на Github</a></p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/7JSrEIafBLo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/02/arbor-js-ruby-sinatra/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/02/arbor-js-ruby-sinatra/</feedburner:origLink></item>
		<item>
		<title>Backbone.js и Sinatra (Ruby)</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/j4qLjvssQnU/</link>
		<comments>http://vredniy.ru/2012/02/backbone-js-sinatra-ruby/#comments</comments>
		<pubDate>Sat, 11 Feb 2012 19:58:01 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[backbone]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=883</guid>
		<description><![CDATA[Приветствую тебя, товарищ-разработчик, сегодня речь пойдет больше о клиентсом программировании, точнее об одном фреймворке. Backbone js ему название. Что в нем особенного спросите вы. Это первый MVC фреймворк на стороне клиента, попавшийся мне на глаза. Очень долго я с ним воевал, поэтому тут уж дело чести понять как работают 1200 строк кода на javascript. Данная [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fbackbone-js-sinatra-ruby%2F"><br />
				<img class="colorbox-883"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fbackbone-js-sinatra-ruby%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=backbone,heroku,jQuery,ruby,sinatra&amp;b=2" height="61" width="50" title="Backbone.js и Sinatra (Ruby)" alt=" Backbone.js и Sinatra (Ruby)" /><br />
			</a>
		</div>
<p>Приветствую тебя, товарищ-разработчик, сегодня речь пойдет больше о клиентсом программировании, точнее об одном фреймворке. Backbone js ему название. Что в нем особенного спросите вы. Это первый MVC фреймворк на стороне клиента, попавшийся мне на глаза. Очень долго я с ним воевал, поэтому тут уж дело чести понять как работают 1200 строк кода на javascript.<br />
<span id="more-883"></span><br />
Данная заметка не прендует на всеобъемлющее описание, да и практической пользы от разрабатываемого в ней приложения (без доработки) практически нет, это больше для души или, как говорится, for fun.</p>
<p>Сначала поставим себе небольшую цель, чего же мы хотим увидеть по окончании: одна страница, без ссылок и переходов, все взаимодействие с сервером происходит в режиме реального времени по средством ajax запросов. В конце мы сможем добавлять новые книги, удалять их и изменять поля. Весь &#171;дизайн&#187; выполнен человеком, то бишь мною, ничего общего с дизайнерами и верстальщиками не имеющего, но, как мне кажется, он [дизайн], получился удобным и не отталкивающим. Обрабатывать наши ajax запросы будет Ruby при помощи замечательного фреймворка Sinatra, но работа им предстоит не сложная, поэтому сосредоточимся на frontend&#8217;е.</p>
<h3>Что еще за backbone.js?</h3>
<p>Аналог jquery? Нет, у данного фреймворка совсем другая специализация &#8212; его основная задача создать основу для модульного приложения на стороне клиента, чтобы богатые на компоненты и модули интерфейсы легко могли взаимодействовать с пользователем. Чтобы добавления новой функциональности не превращало код приложения в спагетти, а наоборот, этому способствовало.</p>
<h3>Из чего состоит backbone.js?</h3>
<p>Модель, Представление, Коллекция и Роутер, если не сильно вдаваться в подробности (очень хорошая документация собрана на сайте backbone.js), то модель представляет собой, если проводить аналогию с базами данных, строку в таблице, к любым свойствам которой мы легко можем обращаться, также легко мы можем ее обновлять, сохранять и прочее. Коллекция &#8212; кучка моделей или по аналогии &#8212; несколькими строками таблицы, объединенных общими полями и свойствами. Представление &#8212; вот это, по-моему, самая интересная и в то же время непростая для меня часть. Представление в понимании создателей backbone.js &#8212; это совсем иное, нежели мы, backend-разработчики привыкли видеть. Это что-то очень похожее на букву V из аббревиатуры MVC, но с немного большими возможностями и ответственностями. Я думаю на примере станет немного яснее. И последним будет Роутер &#8212; в данном приложении я его использовать не буду, оно слишком маленькое, чтобы усложнять его и без того не простую к пониманию новую технологию, по крайней мере, для меня. Как написано на сайте backbone.js роутер предоставляет методы для связывания ссылок на странице со всевозможными событиями. С появлением в нашей жизни History API, появилась возможность использовать наряду с ссылками вида /#about, ссылки обычного вида, /about, к примеру, что намного приятнее для глаза человеческого.<br />
<img src="http://vredniy.ru/wp-content/uploads/2012/02/backbone-sinatra.jpeg" alt=" Backbone.js и Sinatra (Ruby)" title="backbone sinatra" width="689" height="483" class="aligncenter size-full wp-image-885 colorbox-883" /><br />
Итак, хватит воды, давайте приступим к делу. Начнем, конечно же с html, который и будет подключать все библиотеки стили на стороне клиента, в нем же будем хранить наш шаблон, что для маленького приложения не будет грубой ошибкой.</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/jquery-1.7.1.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/underscore.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/backbone.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;styles/bootstrap.css&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/hot-sneaks/jquery-ui.css&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;styles/main.css&quot;</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/bootstrap.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/jquery.ui.datepicker-ru.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!--&lt;script type=&quot;text/javascript&quot; src=&quot;js/backbone.localStorage.js&quot;&gt;&lt;/script&gt;--&gt;</span></div></td></tr></tbody></table></div>
<p>Начнем с подключения библиотеки и стилей: за основу взят, уже не в первый раз css фреймворк bootstrap от twitter, в самом начале подключаем нашу любимую библиотеки <a href="/category/jquery">Query</a>, но backbone.js может работать и без нее, это больше для нас, чтобы вместо 5 строк не писать 50 <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Backbone.js и Sinatra (Ruby)" class='wp-smiley colorbox-883' title="Backbone.js и Sinatra (Ruby)" /> . underscore.js &#8212; библиотека-утилита, которая предоставляет основу для функционального программирования на JavaScript, без него не работает наш backbone.js, поэтому подключайте underscore.js раньше. Остальные библиотеки не должны вызвать сложностей в понимании: они уже у всех на слуху, отдельно коснусь закомментированной строки. Если ее расскомментировать и внести небольшие изменения в код, то вместо хранения всего в базе данных, мы будем использовать localStorage браузера, который это поддерживает.</p>
<p>Теперь немного разметки,</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;container-fluid&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;books&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span12&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>Моя библиотека<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span2&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-control&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #808080; font-style: italic;">&lt;!-- добавление новых книг --&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h3</span>&gt;</span>Добавить<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h3</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-title&quot;</span>&gt;</span>Название книги<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-title&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span12&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">button</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;btn-primary&quot;</span>&gt;</span>Добавить новую<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">button</span>&gt;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span8 book-container&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">&lt;!-- место для книг --&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span2&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h3</span>&gt;</span>Описание<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h3</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Здесь ничего особенного, поэтому не буду комментрировать.</p>
<p>Самое время привнести в наш проект немного магии, которое будет не мало. Первая магия &#8212; шаблоны на стороне клиента.</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/template&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-template&quot;</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dl</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;#&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-edit&quot;</span>&gt;</span>Название:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span> <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">i</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;icon-remove book-delete&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">i</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-title&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> <span style="color: #000066;">title</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>Год издания: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-year span3&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> year %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>Автор: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-author&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> author %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>Жанр: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-genre&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> genre %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>ISBN: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-isbn&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> isbn %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>Статус: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;book-status&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;read&quot;</span>&gt;</span>Прочитана<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;not-read&quot;</span>&gt;</span>Не прочитана<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">option</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;want-read&quot;</span>&gt;</span>Хочу прочитать<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">option</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">select</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> status %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dt</span>&gt;</span>Дата: <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dt</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">dd</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;datepicker book-date&quot;</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;%<span style="color: #66cc66;">=</span> date %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">span</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dd</span>&gt;</span><br />
<br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">dl</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;btn btn-primary book-save&quot;</span>&gt;</span>Сохранить<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Казалось бы так похож на erb, но это просто совпадение, или разработчики данного шаблона рубисты. Вместо конструкций вида <%= title %> в конечном html, появятся наши переменные, нам их нужно будет лишь заполнить. А верстка останется неизменной, что очень удобно.</p>
<p>Почти все, кроме одной строки, хотя эта одна строчка подключает сердце нашего приложения</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;js/application.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Теперь самое время окунуться с головой в клиентское программирование (файл js/application.js).</p>
<p>Начнем, пожалуй, с модели.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Book <span style="color: #339933;">=</span> Backbone.<span style="color: #660066;">Model</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;defaults<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; title<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Book's title&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; year<span style="color: #339933;">:</span> <span style="color: #CC0000;">2009</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; author<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Murakami&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; genre<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;horror&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;comedy&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; isbn<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;0128127622&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">status</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;not read&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; image<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;/images/placeholder.png&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; date<span style="color: #339933;">:</span> <span style="color: #3366CC;">''</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Все модели нашего приложения должны расширять базовый класс Backbone.Model, свойство defaults, как понятно из названия отвечает за установку свойств модели по умолчанию. Я взял для примеры стандартные книжные свойства, большая часть из которых работает не до конца. </p>
<p>Теперь перейдем непосредственно к нашей библиотеке, расширив класс коллекции Backbone.Collection</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Library <span style="color: #339933;">=</span> Backbone.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #006600; font-style: italic;">//localStorage: new Store(&quot;BackboneCollection&quot;),</span><br />
&nbsp; &nbsp;url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/books'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp;model<span style="color: #339933;">:</span> Book<span style="color: #339933;">,</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Закомментированная строка сохраняла бы всю нашу работу в local Storage браузера, мы же будем взаимодействовать с сервером, для этого нам понадобится адрес, по которому и будет производиться все общение (точнее будет основой для производных адресов). Последняя строка указывает коллекция каких объектов нами будет использоваться.</p>
<p>Если для модели нам не нужен объект, то для коллекции пригодится, поэтому создадим его.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> library <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Library<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>А сейчас начнется самое интересное &#8212; Представление. Будем разбирать его неспеша, чтобы ничего важного не упустить.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> BookView <span style="color: #339933;">=</span> Backbone.<span style="color: #660066;">View</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; tagName<span style="color: #339933;">:</span> <span style="color: #3366CC;">'div'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; className<span style="color: #339933;">:</span> <span style="color: #3366CC;">'book'</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; template<span style="color: #339933;">:</span> _.<span style="color: #660066;">template</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#book-template'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; events<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;click a.book-edit&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;edit&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;keypress input&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;update&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;click .book-delete&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;clear&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #3366CC;">&quot;click .book-save&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;close&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Сначала расширяем базовый класс Backbone.View, далее указываем элемент, с которым мы будем работать, в данном случае, это div с классом book. Следующая строка указывает какой шаблон мы будем рендерить и сохраняет его в переменной. В свойстве events мы перечисляем какие события мы будет &#171;прослушивать&#187;.<br />
Каждая строка состоит из следующих моментов: сначала идет событие, которое мы будем обрабатывать, дальше &#8212; элемент, с которым это событие произойдет, после двоеточия &#8212; имя метода, который будет вызываться при наступлении прослушиваемого события.</p>
<p>Первая строка &#8212; нажимаем на ссылку &#8212; редактирование книги, вторая &#8212; нажимаем на кнопку (в указанном методе мы проверям Enter ли это) в текстовом поле &#8212; сохранить изменения. И последние две &#8212; это удаление и сохранение изменений.</p>
<p>Теперь опишим все методы нашего представления</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'change'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">render</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'destroy'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">remove</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
update<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">keyCode</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">13</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp;<br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
<span style="color: #000066;">close</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">set</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>._get<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">save</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">toJSON</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">el</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">removeClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;editing&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>&nbsp; <br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Первым не важно для модели, коллекции или представления вызывается метод initialize, поэтому можно расценивать его как конструктор.</p>
<p>this.model будет во время работы приложения указывать на текущую модель, т.е. каждый кусок разметки будет связан с отдельной моделью, изменения в котором коснутся только одной модели, также как и наоборот. Первым делом мы связывем события модели с методами: первое это изменение модели, после которого должно произойти &#171;отрисовка&#187;, второе &#8212; удаление.</p>
<p>Метод <em>update</em> вызывается каждыйраз, когда пользователь нажимает на клавиатуру, нам нужно отлавливать только нажатие Enter, чтобы сохранить изменения.</p>
<p>Метод <em>close</em> вызывается, когда пользователь нажал Enter или кликнул по кнопке &#171;Сохранить&#187;, посмотрите еще раз на последнюю строку из свойства events. В первой строке которого мы обновляем нашей модели свойств из текстовых полей. Дальше мы сохраняем модель и удаляем с себя класс редактирования (нужно будет для &#171;рюшечек&#187;).</p>
<p>Следующий метод, наверное, самый значимый, он отрисовывает все изменения модели на экране пользователя.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">render<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">el</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">template</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">toJSON</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">el</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #3366CC;">'background'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">' no-repeat url('</span> <span style="color: #339933;">+</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'image'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">')'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">setText</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p><em>this.el</em> ни что иное, как tagName: &#8216;div&#8217; и className: &#8216;book&#8217;. Первая строка данного метода изменяет html элемента, учитывая новые свойства модели и учитывая разметку из шаблона. (Помните, мы писали недавно template: _.template($(&#8216;#book-template&#8217;).html())). Вторая строка данного метода заполняет фоновой картинкой наш кусок разметки.</p>
<p>&#171;Толстые&#187; методы для обновления свойств модели, исходя из значения текстовых полей или наоборот &#8212; текстоых полей, исходя их свойств модели.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">setText<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;">var</span> text <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'title'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.book span.book-title'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>text<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputTitle</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-title'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputYear</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-year'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputAuthor</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-author'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputGenre</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-genre'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputIsbn</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-isbn'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputStatus</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'select.book-status'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputDate</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input.book-date'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
_fillForm<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">toJSON</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputTitle</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">title</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputYear</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">year</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputAuthor</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">author</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputGenre</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">genre</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputIsbn</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">isbn</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputStatus</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputDate</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">date</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
_get<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; title<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputTitle</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; year<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputYear</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; author<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputAuthor</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; genre<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputGenre</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; isbn<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputIsbn</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066;">status</span><span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputStatus</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; date<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputDate</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>И последние 3 методя для данного представления:</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">edit<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'div.book'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">removeClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'editing'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">el</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">addClass</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'editing'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'input, select'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">fadeIn</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'slow'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>._fillForm<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">inputTitle</span>.<span style="color: #000066;">focus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
clear<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">confirm</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Вы уверены?&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">destroy</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
remove<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">el</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">fadeOut</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'slow'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>$<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Первый &#8212; уделяет класс редактирования со всех книг и устанавливает на активной и заполняет форму значениями модели (данный метод вызывается, когда пользователь нажмет на ссылку для редактирования).</p>
<p>Второй &#8212; задает пользователю вопрос, при утвердительном ответа на который удаляет данную модель.</p>
<p>Третий &#8212; вызывается автоматически и удаляет элемент со страницы, а вызывается он из-за того, что мы в конструкторе написали следующее:</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">model</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'destroy'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">remove</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Осталось рассмотреть последнее представление и можно смело переходить к легкому backend&#8217;у.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> AppView <span style="color: #339933;">=</span> Backbone.<span style="color: #660066;">View</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;el<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#books'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp;<br />
&nbsp; &nbsp;events<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;click button&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;create&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">&quot;keypress #book-title&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;createOnEnter&quot;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp;initialize<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">input</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#book-title'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'add'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">addOne</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'reset'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">addAll</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'all'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">render</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">fetch</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp;render<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Данное представление отвечает за создание новых книг и загрузку книг с сервера. Книга создается заполнением только лишь названия, дальше ее можно отредактировать и сохранить. В конструкторе данного представления мы связываем необходимые события коллекции с методами, которые будет вызываться при наступлении событий. <strong>library.fetch();</strong> &#8212; запрашивает с сервера все книги, чтобы потом их отобразить.</p>
<p>Почему метод рендеринга пустой? Потому что он нам тут не нужен, все отрисовывается в методе добавления новой книги, с него и начнем продолжение рассказа.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">addOne<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>book<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> view <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> BookView<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>model<span style="color: #339933;">:</span> book<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> content <span style="color: #339933;">=</span> view.<span style="color: #660066;">render</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">el</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#books'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.book-container'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">prepend</span><span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>content<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp;addAll<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">addOne</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp;createOnEnter<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e.<span style="color: #660066;">keyCode</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">13</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp;create<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> text <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">input</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; library.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>title<span style="color: #339933;">:</span> text<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">input</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//$('.book-date').datepicker({});</span><br />
<span style="color: #003366; font-weight: bold;">var</span> appView <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> AppView<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Метод addOne добавляет в верстку одну книгу, создавая соответствующее представление. Метод addAll &#8212; пробегается по все коллекции книг и по одной с помощью метода addOne добавляет книги в верстку. Метод create создает для нас книгу с заголовком, который мы укажем в текстовом поле.</p>
<p>Осталось только создать нам представление приложения и наслаждаться результатом, хотя сначала нужно реализовать backend. Но он будет очень простым, поэтому быстрее перейдем к нему.</p>
<h3>Backend на Ruby</h3>
<p>Сначала общие моменты: подключение необходимых гемов, задание дефолтного подключения для DataMapper&#8217;а и описание класса Книга:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># coding: utf-8</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'data_mapper'</span><br />
&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'json'</span><br />
<br />
&nbsp; DataMapper.<span style="color:#9900CC;">setup</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:default</span>, ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'DATABASE_URL'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#996600;">'sqlite:./db/books.db'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Book<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">DataMapper::Resource</span><br />
<br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:id</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial<br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:title</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:year</span>, &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">Integer</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:date</span>, &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">Date</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:image</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:author</span>, &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:genre</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:isbn</span>, &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; &nbsp; property <span style="color:#ff3333; font-weight:bold;">:status</span>, &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">String</span><br />
<br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;">#belongs_to :user</span><br />
<br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; DataMapper.<span style="color:#9900CC;">finalize</span><br />
<br />
&nbsp; get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">read</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'./public/index.html'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Главной страницей у нас будет статичный файл .html<br />
Теперь давайте сделаем небольшую паузу и поговорим о том, как взаимодействует Backbone.js с серверной частью. Если заглянуть в исходники, то там мы увидим следующее:</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp;<span style="color: #003366; font-weight: bold;">var</span> methodMap <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">'create'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'POST'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">'update'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'PUT'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">'delete'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'DELETE'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">'read'</span><span style="color: #339933;">:</span> &nbsp; <span style="color: #3366CC;">'GET'</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Т.е. стандартный RESTfull запрос. Не будем оттягивать кота за яйца, закончим уже кодить над этим проектом, тем более, что Sinatra легко может обработать подобные запросы.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; get <span style="color:#996600;">'/books'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; content_type <span style="color:#ff3333; font-weight:bold;">:json</span><br />
&nbsp; &nbsp; Book.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:order</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">to_json</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; post <span style="color:#996600;">'/books'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; data = JSON.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>request.<span style="color:#9900CC;">body</span>.<span style="color:#CC0066; font-weight:bold;">gets</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; Book.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'title'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>; &nbsp;<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; put <span style="color:#996600;">'/books/:id'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; data = JSON.<span style="color:#9900CC;">parse</span><span style="color:#006600; font-weight:bold;">&#40;</span>request.<span style="color:#9900CC;">body</span>.<span style="color:#CC0066; font-weight:bold;">gets</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; book = Book.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; result = book.<span style="color:#9900CC;">update</span><span style="color:#006600; font-weight:bold;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'title'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:year</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'year'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:author</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'author'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:genre</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'genre'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:isbn</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'isbn'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:status</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> data<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'status'</span><span style="color:#006600; font-weight:bold;">&#93;</span>,<br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:image</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/images/placeholder.png'</span>, <span style="color:#008000; font-style:italic;">#data['image'],</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#ff3333; font-weight:bold;">:date</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#996600;">&quot;false&quot;</span> <span style="color:#9966CC; font-weight:bold;">unless</span> result<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; delete <span style="color:#996600;">'/books/:id'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; Book.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">destroy</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Здесь нет ничего сложного, если есть какие-то сложности, посмотрите мои предыдущие заметки о Ruby и о Sinatra.</p>
<h3>Заключение</h3>
<p>Еще одно приложение мы разработали с вами на ruby, сегодня не обошлось без так важного на сегодняший день клиентсткого программирования. Ссылка на <a href="http://vredniy-library.heroku.com/" rel="nofollow">пример</a> (редактирование и создание не сохраняются в базе)  и ссылка на <a href="https://github.com/vredniy/Backbone-sinatra" rel="nofollow">исходник</a>.<br />
<img src="http://vredniy.ru/wp-content/uploads/2012/02/placeholder.png" alt="placeholder Backbone.js и Sinatra (Ruby)" title="backbonejs ruby sinatra" width="400" height="314" class="aligncenter size-full wp-image-887 colorbox-883" /><br />
Всем спасибо за внимание и до новых встреч <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Backbone.js и Sinatra (Ruby)" class='wp-smiley colorbox-883' title="Backbone.js и Sinatra (Ruby)" />  </p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/j4qLjvssQnU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/02/backbone-js-sinatra-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/02/backbone-js-sinatra-ruby/</feedburner:origLink></item>
		<item>
		<title>Введение в TDD с Ruby и Rspec</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/ILqsqnwokAw/</link>
		<comments>http://vredniy.ru/2012/02/tdd-ruby-introduction/#comments</comments>
		<pubDate>Wed, 08 Feb 2012 18:19:50 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[TDD]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[unit test]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=865</guid>
		<description><![CDATA[Здравствуйте, уважаемые разработчики, сегодня я коснусь немного новой для себя методологии, а именно TDD, что означает test driven development (разработка через тестирование). Что же представляет собой эта методология, что за разработка через тестирование? Это методика, которая с ног на голову переворачивает стандартный ход дел: продумывание архитектуры, проектирование, написание кода и в заключении написание модульных и [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Ftdd-ruby-introduction%2F"><br />
				<img class="colorbox-865"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Ftdd-ruby-introduction%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=rspec,ruby,tdd,unit+test&amp;b=2" height="61" width="50" title="Введение в TDD с Ruby и Rspec" alt=" Введение в TDD с Ruby и Rspec" /><br />
			</a>
		</div>
<p>Здравствуйте, уважаемые разработчики, сегодня я коснусь немного новой для себя методологии, а именно TDD, что означает test driven development (разработка через тестирование).<br />
<span id="more-865"></span><br />
Что же представляет собой эта методология, что за разработка через тестирование? Это методика, которая с ног на голову переворачивает стандартный ход дел: продумывание архитектуры, проектирование, написание кода и в заключении написание модульных и приемочных тестов. По задумке TDD мы сначала продумываем архитектуру, потом пишем модульные они же юнит тесты, потом непосредственно код. С одной небольшой поправкой: юнит тесты пишутся очень маленькими, после этого пишется код, который позволяет тесту закраситься в зеленый цвет и так дальше &#8212; короткие итерации, которые сводят к минимуму функциональные и логические ошибки в приложениях.</p>
<p>Так как я в данный момент очень поглащен изучением замечательного языка ruby, с его основ, то на нем и будем проводить наши с вами эксперименты. Чтобы не усложнять и без того сначала непростую к пониманию информацию, я попробую рассказать про данную методологию на простом примере класса калькулятора. И для дальнейшего, но уже самостоятельного закрепления материала и изучения, я очень рекомендую найти в интернете пример, наглядно показывающий TDD при разработке класса, который подсчитывает игровые очки в боулинге, учитывая особенности игры.</p>
<p>Итак, поехали! Для начала нам понадобится gem rspec, который и будет нашим тестирующим инструментом, почему он, если есть аналоги? Потому что он первый попался мне на глаза, может есть и лучше, я пока не вникал в эту сторону вопроса, как известно &#8212; лучшее &#8212; враг хорошего.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">gem install rspec</div></td></tr></tbody></table></div>
<p>Команда установит нам необходимый гем со всеми необходимыми зависимостями.</p>
<p>Далее создаем папку проект (.). Дерево нашего проекта будет иметь вид:</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<br />
├── _<br />
├── calculator.rb<br />
└── spec<br />
&nbsp; &nbsp; └── calculator_spec.rb</div></td></tr></tbody></table></div>
<p><strong>calculator.rb</strong> &#8212; наше приложение, <strong>spec/calculator_spec.rb</strong> &#8212; наш файл с тестами.</p>
<p>Создайте, если у вас еще не созданы, эти файлы, calculator.rb оставьте пустым. Начнем разработку, как уже говорилось вначале заметки с тестов, но перед этим давайте напишем небольшой план по разработке.</p>
<p>* Должен существовать класс калькулятора<br />
* Калькулятор должен иметь метод add (сумма)<br />
* Метод add должен возвращать сумму двух своих аргументов<br />
* Должен иметь метод sub (разность)<br />
* Также и для методов mul (произведение) и div (частное)<br />
* Метод div должен кидать исключение, когда пытаемся делить на 0<br />
* (не относящийся к делу пункт) Класс Calculator должен быть проивзодным от Calculator</p>
<p>Напишем первый тест</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'../calculator'</span><br />
descibe <span style="color:#996600;">'Calculator'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;it <span style="color:#996600;">'should exists'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Что же мы получаем, в первой строке все просто &#8212; подключаем файл нашего приложени, ведь над ним будем проводить наши эксперименты (без него никак). Со слова <strong>descibe</strong> начинается контекст теста, входящая в него конструкция (it &#8216;should exists&#8217;) непосредственно сам тест. Остается только запустить тест и посмотреть на результат:</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">rspec ./spec/calculator_spec.rb</div></td></tr></tbody></table></div>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/02/tdd-calculator1.jpeg" alt=" Введение в TDD с Ruby и Rspec" title="tdd ruby rspec" width="514" height="309" class="aligncenter size-full wp-image-866 colorbox-865" /><br />
Чтобы написать минимальный код, который бы прошел данный тест, нужно две строчки, а именно создать класс Calculator, так и запишем в <strong>./calculator.rb</strong></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Calulcator<br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Запускаем наш тест еще раз и убеждаемся, что тест пройден. Напишем новый тест, заключим его в тот же describe, что и предыдущий. У нас получится следующее:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">describe <span style="color:#996600;">'Calculator'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;it <span style="color:#996600;">'should exists'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp;it <span style="color:#996600;">'should have method add(a,b)'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span> <span style="color:#006666;">2</span>,<span style="color:#006666;">3</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/02/tdd-calculator2.jpeg" alt=" Введение в TDD с Ruby и Rspec" title="tdd ruby rspec" width="522" height="175" class="aligncenter size-full wp-image-868 colorbox-865" /><br />
Тест говорит следующее: &#171;Калькулятор должен иметь метод add, который принимает 2 параметра&#187;, запускаем наш тест и видим, что !!! тест провален, потому что у нас метода add, тем более принимающего два параметра, так в чем же дело, давайте его напишем, ведь это всего две строки кода.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Calculator<br />
<br />
<span style="color:#9966CC; font-weight:bold;">def</span> add<span style="color:#006600; font-weight:bold;">&#40;</span>a, b<span style="color:#006600; font-weight:bold;">&#41;</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Теперь наш тест проходит и мы можем двигаться дальше. Давайте сделаем так, чтобы метод add возвращал сумму своих двух аргументов. Начнем, конечно же, с написания теста.<br />
<img src="http://vredniy.ru/wp-content/uploads/2012/02/tdd-calculator3.jpeg" alt=" Введение в TDD с Ruby и Rspec" title="tdd ruby rspec" width="529" height="307" class="aligncenter size-full wp-image-869 colorbox-865" /></p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp;it <span style="color:#996600;">'add() method should add two numbers'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should_not</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>И, собственно, код, данный тест проходящий:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> add<span style="color:#006600; font-weight:bold;">&#40;</span>a, b<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;a<span style="color:#006600; font-weight:bold;">+</span>b<br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Остальные тесты я приведу вам без кода приложения, чтобы они выполнялись правильно вам потребуется код написать самим, благо, он совсем простой и займет всего пару минут.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'../calculator'</span><br />
<br />
describe <span style="color:#996600;">'Calculator'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;it <span style="color:#996600;">'should exists'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp;it <span style="color:#996600;">'should have method add(a,b)'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span> <span style="color:#006666;">2</span>,<span style="color:#006666;">3</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;it <span style="color:#996600;">'add() method should add two numbers'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should_not</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;it <span style="color:#996600;">'sub() method should return subtraction'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#CC0066; font-weight:bold;">sub</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span>, <span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;it <span style="color:#996600;">'mul() method should return multiple'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">mul</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">7</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">14</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;it <span style="color:#996600;">'div() method should return division'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">div</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">10</span>, <span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> eq<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp;it <span style="color:#996600;">'div() method should raise exception by division by zero'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; expect <span style="color:#006600; font-weight:bold;">&#123;</span> Calculator.<span style="color:#9900CC;">new</span>.<span style="color:#9900CC;">div</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">2</span>, <span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">to</span> raise_error<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC00FF; font-weight:bold;">ZeroDivisionError</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp;<span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<h3>Заключение</h3>
<p>В данной заметке мы очень поверхностно познакомились с очень интересной методологией разработки TDD (test driven development) и разобрали небольшой пример, чтобы немного закрепить знания. Если вы будете применять данную методику в своих проектах, то количество ошибок в них будет асимптотически приближаться к нулю, это ли не счастье программиста? <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Введение в TDD с Ruby и Rspec" class='wp-smiley colorbox-865' title="Введение в TDD с Ruby и Rspec" /> </p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/ILqsqnwokAw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/02/tdd-ruby-introduction/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/02/tdd-ruby-introduction/</feedburner:origLink></item>
		<item>
		<title>Ruby для начинающих CMS</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/CzV7tb0464s/</link>
		<comments>http://vredniy.ru/2012/02/ruby-sinatra-cms-heroku/#comments</comments>
		<pubDate>Sat, 04 Feb 2012 23:24:29 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[heroku]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=834</guid>
		<description><![CDATA[Данная заметка посвящена целиком Sinatra фреймворку на Ruby, а точнее написанию небольшой, простой CMS. Это ведь следующая стадия после &#8216;hello, world&#8217; в изучении нового языка. Поехали! План по реализации CMS Написание требований (куда без них) Используемые гемы Создание необходимых моделей Написание кода экшнов Наведения марафета Деплой на хероку 1. Написание требований Целью данной CMS должно [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fruby-sinatra-cms-heroku%2F"><br />
				<img class="colorbox-834"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fruby-sinatra-cms-heroku%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=heroku,ruby,sinatra&amp;b=2" height="61" width="50" title="Ruby для начинающих CMS" alt=" Ruby для начинающих CMS" /><br />
			</a>
		</div>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/02/sinatra-cms-heroku-150x150.jpg" alt="sinatra cms heroku 150x150 Ruby для начинающих CMS" title="sinatra-cms-heroku" width="150" height="150" class="alignleft size-thumbnail wp-image-839 colorbox-834" /><br />
Данная заметка посвящена целиком Sinatra фреймворку на Ruby, а точнее написанию небольшой, простой CMS. Это ведь следующая стадия после &#8216;hello, world&#8217; в изучении нового языка. Поехали!<br />
<span id="more-834"></span></p>
<h4>План по реализации CMS</h4>
<ol>
<li>Написание требований (куда без них)</li>
<li>Используемые гемы</li>
<li>Создание необходимых моделей</li>
<li>Написание кода экшнов</li>
<li>Наведения марафета</li>
<li>Деплой на хероку</li>
</ol>
<h5>1. Написание требований</h5>
<p>Целью данной CMS должно быть введение новичков, таких же как и я, в богатый и интересный мир Ruby. Поэтому приложение не должно быть перенасыщено функциональстью, чтобы не отвлекать от главных моментов. &#171;Рюшечки&#187; мы всегда сумеем прикрепить. Поэтому основные требования заключаются в следующем:</p>
<ul>
<li>Backend
<ul>
<li>Создание/редактирование/удаление статичных страниц
<ul>
<li>должна будет отображаться форма с текстовыми полями, контентное поле должно быть заменено wysiwyg, я выбрал для этих целей <strong>redactor.js</strong> (давно хотел с ним познакомиться, видимо, время пришло)</li>
<li>у каждой страницы будет две метки времени: метка создания (заполняется автоматически при создании новой страницы) и метки обновления (время изменения страницы)</li>
</ul>
</li>
<li>Отображение списка страниц в возможностью из него удалить или редактировать любую.</li>
<li>Должна быть реализована базовая аутентификация, чтобы люди с улицы не смогли проникнуть в &#171;админку&#187;</li>
<li>Приятный интерфейс</li>
<li>Редирект на список страниц после создания/редактирования или удаления</li>
</ul>
</li>
<li>Frontend
<ul>
<li>Динамически строемое меню, содержащее все страницы в виде ссылок, чтобы можно было &#171;погулять&#187; по разделам</li>
<li>Приятный интерфейс</li>
<li>Ссылки вида <em>/contacts.html</em>, чтобы выглядело эстетично.</li>
<li>При заходе на главную (/) пользователь видит домашнюю страницу, также со списком всех имеющихся страниц.</li>
</ul>
</li>
</ul>
<h5>2. Используемые гемы</h5>
<p>Теперь перейдем непосредственно к реализации написанной выше функциональности. В первую очередь нам понадобится <em>data_mapper</em>, гем который очень облегчает жизнь разработчикам, которые используют базы данных, правда некоторые выбирают Active Record, но разъяснение разницы лежит за пределами этой заметки.<br />
Итак, Datamapper &#8212; прослойка между БД и объектом &#8212; не нужно писать ни строчки sql кода, создавать таблицы напрямую и изменять их структуру. Datamapper возьмет на себя всю эту грязную работу. Сначала установка<br />
<strong>sudo apt-get install libsqlite3-dev</strong><br />
На локальной машине мы будем работать с backend&#8217;ом в виде sqlite3, на хероку &#8212; postgres. Но нам по этому поводу не нужно переживать: всю грязную работу сделают datamapper и heroku.<br />
Устанавливаем необходимый гем командой<br />
<strong>gem install data_mapper</strong><br />
Чтобы не томить нетерпеливых сразу приведу конечный <strong>Gemfile</strong>, вот так он выглядит у меня:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">source <span style="color:#ff3333; font-weight:bold;">:rubygems</span><br />
gem <span style="color:#996600;">'data_mapper'</span><br />
gem <span style="color:#996600;">'sinatra'</span><br />
gem <span style="color:#996600;">'dm-postgres-adapter'</span><br />
gem <span style="color:#996600;">'dm-sqlite-adapter'</span></div></td></tr></tbody></table></div>
<h5>3. Создание необходимых моделей</h5>
<p>Модель, спешу я вас обрадовать или огорчить, будет у нас всего одна &#8212; это Страница. Для нашего скромного и минималистичного приложения ее будет более чем достаточно. Сначала отвлечемся на config.ru &#8212; файл, без которого наше приложения на запустится (о нем я писал в <a href="/2012/02/ruby-application-heroku/">заметке о деплое ruby приложения</a>). Собственно <strong>config.ru</strong>:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'./bootstrap.rb'</span><br />
run <span style="color:#6666ff; font-weight:bold;">Sinatra::Application</span></div></td></tr></tbody></table></div>
<p>Здесь, надеюсь, не нужно разъяснения. Далее мы подходим к модели поближе. Перед тем, как описывать подель, нам необходимо подготовить соединение, где-то ведь нам необходимо данные сохранять.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#008000; font-style:italic;"># coding: utf-8</span><br />
<br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'data_mapper'</span><br />
<br />
DataMapper.<span style="color:#9900CC;">setup</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:default</span>, ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'DATABASE_URL'</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#996600;">'sqlite:./db/page.db'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>Первая строчка необходима для того, чтобы можно было в исходный код писать символы в utf-8 кодировке. Далее тремя последующими строчками мы подключаем необходимые файлы, один из которых Sinatra, другой &#8212; Datamapper. Последняя строчка самая интересная. Она сообщает Datamapper&#8217;у, что если не установлена переменная окружения <em>DATABASE_URL</em> (значит, мы на heroku сервере), то использовать локальную базу данных, которая будет находится в папке db. </p>
<p>Теперь непосредственно модель, которая представляет собой класс (неожиданно, неправда ли?), к котому строкой <em>include DataMapper::Resource</em> добавляется множество методов для манипуляции самого Datamapper&#8217;а. Точнее вся это функциональность добавляется не к самому класса, к инстансам этого класса. Код модели представлен чуть ниже:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">class</span> Page<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">DataMapper::Resource</span><br />
<br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:id</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial<br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:name</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; property :<span style="color:#9966CC; font-weight:bold;">alias</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:short</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Text<br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:full</span>, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Text<br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:seo_title</span>, &nbsp; &nbsp; &nbsp; &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:seo_keywords</span>, &nbsp; &nbsp; <span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:seo_description</span>, &nbsp;<span style="color:#CC0066; font-weight:bold;">String</span><br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:created_at</span>, &nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">DateTime</span><br />
&nbsp; property <span style="color:#ff3333; font-weight:bold;">:updated_at</span>, &nbsp; &nbsp; &nbsp; <span style="color:#CC00FF; font-weight:bold;">DateTime</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>В классе мы объявляем необходимые свойства: id &#8212; как и ожидается, является первичным ключом, остальные свойства, я думаю, итак понятны, всем ведь уже не раз приходилось проектировать базы данных.<br />
Этот код яйца выеденного не стоит без создания таблиц, соответствющих этой модели. Этим займется команда</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DataMapper.<span style="color:#9900CC;">finalize</span><br />
<span style="color:#008000; font-style:italic;">#DataMapper.auto_migrate!</span></div></td></tr></tbody></table></div>
<p>Первая строка говорит Datamapper&#8217;у, что все, хватит, больше мы добавлять поля не будем, поэтому можешь не беспокоиться, закоментированная же строка применялась мною на этапе разработки, потому что количество столбцов и их тип менялись очень часто.<br />
С моделью в общих чертах разобрались, все необходимые моменты будут расталкованы мною чуть дальше, когда мы коснемся момента реализации.</p>
<h5>4. Написание кода экшнов</h5>
<p>На стороне backend&#8217;а у нас будет 6 так называемых экшнов, т.е. действий, которые будут выполняться в зависимости от контекста.</p>
<h6>Создание страницы:</h6>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/admin/create'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:create_form</span> <br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Здесь все просто, когда пользователь запрашивает страницу /admin/create (метод get), ему нужно отобразить форму для добавления новой страницы (<em>erb :create_form</em> &#8212; рендерит <em>./views/create_form.erb</em>). Код формы выглядит очень просто:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h3</span>&gt;</span>Форма страницы<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h3</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/create&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span>&gt;</span>Имя страницы:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span>&gt;</span>Псевдоним:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span>&gt;</span>Краткое описание:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span>&gt;</span>Контент:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;wysiwyg&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span>&gt;</span>SEO заголовок:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span>&gt;</span>SEO ключевые слова:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span>&gt;</span>SEO описание:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span> <span style="color: #000066;">rows</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Создать&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;btn btn-primary&quot;</span>&gt;</span><br />
<br />
<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Единственно место, на которое стоит обратить внимание это свойства тега form, а именно</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">method=&quot;post&quot; action=&quot;/admin/create&quot;</div></td></tr></tbody></table></div>
<p>, тем самым мы устанавливаем метод отправки формы в post (по умолчанию все формы отправляются get-методом) на страницу <em>/admin/create</em>, где мы полученные данные и будем поджидать, чтобы записать в базу данных.</p>
<h6>Сохранение страницы:</h6>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">post <span style="color:#996600;">'/admin/create'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; params.<span style="color:#9900CC;">delete</span> <span style="color:#996600;">'submit'</span><br />
&nbsp; params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:updated_at</span><span style="color:#006600; font-weight:bold;">&#93;</span> = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:created_at</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#41;</span> <br />
&nbsp; redirect <span style="color:#996600;">'/admin/pages'</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p><em>params</em> &#8212; содержит все переменные нам переданные. Для начала нам необходимо исключить свойство submit (это кнопка отправки формы), которого нет в нашей модели. Дальше мы присваеваем меткам и создания, и обновления текущее время и дату, а команда <em>Page.create(params)</em> &#8212; создает новую запись в таблице и сохраняет ее с переданными нами из формы данными. Последняя строчка перенаправляет пользователя на страницу, где отображаются все записи, мы к ней еще вернемся.</p>
<h6>Редактирование страницы:</h6>
<p>С этим моментом все очень похоже, кроме нескольких моментов: 1) перед отправкой формы нам необходимо ее заполнить уже имеющимися данными, 2) применить не метод create (как при создании), а присвоить атрибуты напрямую и сохранить.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/admin/edit/:id'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:edit_form</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Если пользователь нажал на ссылку из списка страниц (<em>/admin/edit/1</em>, к примеру) и мы допускаем, что запись в таблице с таким id содержится (проверка на корректность &#171;раздула&#187; бы код и усложнила бы его понимание, поэтому данный момент я оставлю на вашей совести).<br />
<em>@page = Page.get(params[:id])</em> &#8212; получаем запись из таблицы с заданным id, дальше нам остается отрендерить страницу <em>./views/edit-form.erb</em> и ждать пока пользователь нажмет на кнопку submit.<br />
А пока <strong>./views/edit_form.erb</strong>:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h3</span>&gt;</span>Форма страницы<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h3</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/edit/&lt;%= @page.id %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span>&gt;</span>Имя страницы:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;name&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.name %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span>&gt;</span>Псевдоним:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;alias&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.alias %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span>&gt;</span>Краткое описание:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;short&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.short %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span>&gt;</span>Контент:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;wysiwyg&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;full&quot;</span>&gt;&lt;%<span style="color: #66cc66;">=</span> @page.full %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span>&gt;</span>SEO заголовок:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_title&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.seo_title %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span>&gt;</span>SEO ключевые слова:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_keywords&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.seo_keywords %&gt;</span></span>&quot;&gt;<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">label</span> <span style="color: #000066;">for</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span>&gt;</span>SEO описание:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">label</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;seo_description&quot;</span> <span style="color: #000066;">rows</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;2&quot;</span>&gt;&lt;%<span style="color: #66cc66;">=</span> @page.seo_description %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">br</span>&gt;</span><br />
<br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">value</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Сохранить&quot;</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;btn btn-primary&quot;</span>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Единственное отличие &#8212; это заполненные значения полей формы значениями из таблицы в базе данных. После того, как пользователь отправлят форму, нам нужно записать в базу данных новые значения, этим займется следующий метод.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">post <span style="color:#996600;">'/admin/edit/:id'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; params.<span style="color:#9900CC;">delete</span> <span style="color:#996600;">'submit'</span><br />
&nbsp; params.<span style="color:#9900CC;">delete</span> <span style="color:#996600;">'id'</span><br />
&nbsp; params.<span style="color:#9900CC;">delete</span> <span style="color:#996600;">'splat'</span><br />
&nbsp; params.<span style="color:#9900CC;">delete</span> <span style="color:#996600;">'captures'</span> <br />
&nbsp; params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:updated_at</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span>.<span style="color:#9900CC;">attributes</span> = params<br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span>.<span style="color:#9900CC;">save</span><br />
&nbsp; redirect <span style="color:#996600;">'/admin/pages'</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Он у меня получился самым раздутым, скорее всего, из-за не знания языка, но я только учусь, а как говорится лучшее &#8212; враг хорошего, поэтому не обращаем на это внимание и продолжаем двигаться дальше.<br />
После первой строки <em>@page = Page.get(params[:id])</em>, <em>@page</em> &#8212; является строкой в таблице, следующие 4 строки удаляют ненужные параметры, пришедшие к нам из формы, или из фреймворка (последние 2 подсовывает нам Sinatra).<br />
<em>params[:updated_at] = Time.now</em> &#8212; обновляет временную метку, почти не отличается от строки в создании новой странице, только тут мы не трогаем дату и время создания, потому что она остается неизменной на протяжении всей жизни записи.<br />
Строки <em>@page.attributes = params</em>  и <em>@page.save</em> обновляют свойства и записывают уже измененную модель в базу данных. Последняя строка вам уже известна, она перенаправляет пользователя на страницу списка записей. Тут, по-хорошему, нужно было добавить проверку на успешность записи и вслывающее сообщение после редиректа, пусть будет это для вас как домашнее задание, кому интересно.</p>
<h6>Удаление страницы:</h6>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/admin/delete/:id'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; Page.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">destroy</span><br />
&nbsp; redirect <span style="color:#996600;">'/admin/pages'</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Тут все, я думаю, понятно без моих комментариев, находим запись и удаляем его, и снова редирект.</p>
<p>Сейчас разберем список страниц, который отбражается на странице /admin/pages</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/admin/pages'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@pages</span> = Page.<span style="color:#9900CC;">all</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:pages</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>После этих панипуляций @pages содержит все записи из таблицы, и эта переменная доступна нам в шаблоне, а шаблон, как вы, наверное, уже успели догадаться, называться будет <strong>./views/pages.erb</strong>, вот его код:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h6</span>&gt;</span>Список страниц<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h6</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">table</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;table-striped table&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">thead</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Имя<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Псевдоним<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Заголовок<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Создана<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span>Изменена<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">th</span>&gt;</span><span style="color: #ddbb00;">&amp;nbsp;</span><span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">th</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">thead</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tbody</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;% @pages.each do |page| %&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/edit/&lt;%= page.id %&gt;</span></span>&quot;&gt;<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> page.<span style="color: #000066;">name</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> page.alias %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> page.seo_title %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> page.created_at.strftime<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;%d.%m.%Y %H:%M&quot;</span><span style="color: #66cc66;">&#41;</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;%<span style="color: #66cc66;">=</span> page.updated_at.strftime<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;%d.%m.%Y %H:%M&quot;</span><span style="color: #66cc66;">&#41;</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">td</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/delete/&lt;%= page.id %&gt;</span></span>&quot; onclick=&quot;javascript: return confirm('Вы уверены в этом?')&quot;&gt;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">i</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;icon-remove&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">i</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">td</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tr</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;% end %&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">tbody</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">table</span>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h5</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/admin/create&quot;</span>&gt;</span>Создать новую страницу<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h5</span>&gt;</span></div></td></tr></tbody></table></div>
<p>По сути это проста таблица, каждая строка которой является строкой в таблице в базе данных. Строкой <em>@pages.each do |page|</em> мы начинаем цикл по всем записям переменной @pages, помните, которую мы объявили немногим ранее? Прозорливые умы, наверное, догадались, что означает конструкция</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">page.<span style="color:#9900CC;">created_at</span>.<span style="color:#9900CC;">strftime</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;%d.%m.%Y %H:%M&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>Вы правы, этой строкой мы превращаем дату и время из формата, в котором она хранится в базе данных в удобочитаемый формат понятный и приятный глазу человеческому.</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">onclick=&quot;javascript: return confirm('Вы уверены в этом?')&quot;</div></td></tr></tbody></table></div>
<p>Отображает стандартное браузерное окошко с вопросом, если пользователь отвечает на него утвердительно, то строка из таблицы удаляется, иначе же ничего не происходит (примитивная защита от дурака).</p>
<p>С backend&#8217;ом почти разобрались, остались небольшие штришки, давайте перейдем к frontend&#8217;у, чтобы можно было посмотреть на результат своей нелегкой деятельности.</p>
<h5>Отображаем главную страницу</h5>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'mainpage'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@pages</span> = Page.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span>.<span style="color:#9966CC; font-weight:bold;">not</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'mainpage'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:page</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<blockquote><p>Небольшое отступление: Поиск страниц у нас будет осуществляться по полю alias, т.е. псевдоним, в базе данных он будет храниться в виде строки, к примеру, mainpage, contacts, about и т.д. Mainpage с маленькой буквы я буду использовать для задания главной страницы, которая и будет отбражаться по адресу &#8216;/&#8217;.</p></blockquote>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'mainpage'</span><span style="color:#006600; font-weight:bold;">&#41;</span></div></td></tr></tbody></table></div>
<p>находит первую попавшуюся страницу, в поле alias которой стоит значение &#8216;mainpage&#8217; (по-хорошему, нужно было на это поле поставить индекс и сделать его уникальным, но не об этом речь). Следующая строка получает все страницы, кроме mainpage (будем строить простейшее меню на сайте).</p>
<p>И отображаем страницу <strong>./views/page.erb</strong>:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span3&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;&lt;%<span style="color: #66cc66;">=</span> @page.<span style="color: #000066;">name</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span7&quot;</span>&gt;&lt;%<span style="color: #66cc66;">=</span> @page.full %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></td></tr></tbody></table></div>
<p>Где все остальное спросите вы, не торопитесь, отвечу я, все будет <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Ruby для начинающих CMS" class='wp-smiley colorbox-834' title="Ruby для начинающих CMS" /> .<br />
Что за странные классы с непонятными именами предчувствую вопрос и сразу отвечу на него. Т.к. из меня верстальшик, тем более дизайнер, некудышний (я уже смирился с этим), приходится использовать готовые решения, такие как css-фреймворки, в данном проект используется twitter bootstrap &#8212; аккуратный, легкий, приятный глазу, что несказанно облегчает жизнь таким как я разработчикам, которые хотят разрабатывать проекты, но &#171;верстальным&#187; талантом их обделили высшие силы <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Ruby для начинающих CMS" class='wp-smiley colorbox-834' title="Ruby для начинающих CMS" /> . Twitter, с тебя $10 за рекламу <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Ruby для начинающих CMS" class='wp-smiley colorbox-834' title="Ruby для начинающих CMS" /> .</p>
<p>Давайте сначала разберем последний на стороне backend&#8217;а экшн и перейдем непосредственно к шаблонам. Итак,</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/:alias.html'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@page</span> = Page.<span style="color:#9900CC;">first</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> params<span style="color:#006600; font-weight:bold;">&#91;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; not_found <span style="color:#996600;">'Страница не найдена'</span> <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@page</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@pages</span> = Page.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span>:<span style="color:#9966CC; font-weight:bold;">alias</span>.<span style="color:#9966CC; font-weight:bold;">not</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'mainpage'</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; erb <span style="color:#ff3333; font-weight:bold;">:page</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
<br />
not_found <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; erb :<span style="color:#996600;">'404'</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>:layout <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Получилось сразу два: первый почти ничем не отличается от предыдущего, рассмотренного нами, кроме вызова <em>not_found</em>, если <em>@page.nil?</em> (если страница не найдена), второй является хелпером, который вызывается, если страница не найдена.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">erb :<span style="color:#996600;">'404'</span>, <span style="color:#006600; font-weight:bold;">&#123;</span>:layout <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">false</span><span style="color:#006600; font-weight:bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>рендерит ./views/404.erb с отключенным шаблоном. </p>
<h5>Пару слов о шаблонах</h5>
<p>Шаблон представляет собой двухуровневый рендеринг: сначала рендерится непосредственно сама страница экшна, указанного нами в конструкции erb :page, дальше, если не указано обратное, рендерится файл <em>./views/layout.erb</em> и в часть, где указано <em>=yield</em>, вставляется первый кусок, что заметно облегчает жизнь, сокращая код представлений экшнов. Самое главное в этом моменте правильно вычленить повторяющиеся во всех страницах элементы от изменяющихся.<br />
Раз уж коснулись шаблонов, приведу шаблон, который рендерится на стороне frontend&#8217;а, <strong>./views/layout.erb</strong>:</p>
<div class="codecolorer-container html4strict railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE html&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span> <span style="color: #000066;">lang</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;en&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">charset</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;utf-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;description&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.seo_description %&gt;</span></span>&quot;&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;keywords&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;&lt;%= @page.seo_keywords %&gt;</span></span>&quot;&gt;<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">meta</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;author&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;@vredniy&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;&lt;%<span style="color: #66cc66;">=</span> @page.seo_title %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/bootstrap.css&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;container-fluid&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;row-fluid&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span2&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h3</span>&gt;</span>Главное меню<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h3</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&quot;</span>&gt;</span>Главная<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;% @pages.each do |page| %&gt;</span><br />
&nbsp; &nbsp;<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/&lt;%= page.alias %&gt;</span></span>.html&quot;&gt;<span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> page.<span style="color: #000066;">name</span> %&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;% end %&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;span10&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;%<span style="color: #66cc66;">=</span> yield %&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></div></td></tr></tbody></table></div>
<p>В нем не должно быть непонятных моментов, переменные нами уже заполнены, единственное, что кажется на первый взгляд немного сложным, это цикл, отображающий меню, точнее все страницы, кроме главной, но и с ним мы чуть выше знакомились.</p>
<p>Шаблон для административной части я не буду приводить здесь, для экономии места, в конце будет ссылка на работающий репозиторий, который вы можете склонировать и запустить у себя локально или задеплоить на heroku.</p>
<p>Осталось еще пара недосказанных моментов: аутентификация и изменения шаблона для закрытой (backend) части.<br />
Что касается первого, то тут все предельно просто, будем использовать базовую аутентификацию, которую нам представляет прослойка в виде Rack. Реализуем, как рекомендуют на сайте документации Sinatra, через хелперы, вот и сам код:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">helpers <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> protected!<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> authorized?<br />
&nbsp; &nbsp; &nbsp; response<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'WWW-Authenticate'</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006600; font-weight:bold;">%</span><span style="color:#006600; font-weight:bold;">&#40;</span>Basic realm=<span style="color:#996600;">&quot;Cms's restricted area&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; throw<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:halt</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">401</span>, <span style="color:#996600;">&quot;Not authorized<span style="color:#000099;">\n</span>&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> authorized?<br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@auth</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#6666ff; font-weight:bold;">Rack::Auth::Basic::Request</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>request.<span style="color:#9900CC;">env</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@auth</span>.<span style="color:#9900CC;">provided</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> <span style="color:#0066ff; font-weight:bold;">@auth</span>.<span style="color:#9900CC;">basic</span>? <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> <span style="color:#0066ff; font-weight:bold;">@auth</span>.<span style="color:#9900CC;">username</span> <span style="color:#006600; font-weight:bold;">&amp;&amp;</span> <span style="color:#0066ff; font-weight:bold;">@auth</span>.<span style="color:#9900CC;">credentials</span> == <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'admin'</span>, <span style="color:#996600;">'password'</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>В экшне, который мы хотим закрыть от посторонних глаз нужно будет написать <em>protected!</em>, тем самым вызвать хелпер, который проверит, авторизован пользователь или нет, если нет, отобразит стандартное окно браузера с полями для ввода логина и пароля.</p>
<p>Т.к., мы, программисты, люди ленивые, нам сложно писать для каждого экшна /admin* слово protected!, поэтому мы пойдем другим путем, а именно используя фильтр before, который вызывается перед каждым запросом, напишем две строки кода.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">before <span style="color:#996600;">'/admin/*'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; protected!<br />
&nbsp; <span style="color:#0066ff; font-weight:bold;">@default_layout</span> = <span style="color:#ff3333; font-weight:bold;">:admin</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Первая строка, как и упоминали &#171;защищает&#187; от посторонних глаз все закрытые части приложения, вторая же для всех закрытых частей меняет шаблон по умолчанию на admin, т.е. ./views/admin.erb</p>
<h5>5. Наведения марафета</h5>
<p>Чтобы придать немного эстетичности нашему простому приложению мы будем использовать сторонние инструменты, в частности <a href="http://twitter.github.com/bootstrap/" rel="nofollow">twitter bootstrap</a> и <a href="http://imperavi.com/redactor/" rel="nofollow">redactor от imperavi</a>. Все эти файлы уже имеются в репозитории на github, тут они будут лишь занимать ценное место. Еще приведу структуру папок данного приложения, чтобы вы не путались что и куда.</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<br />
├── bootstrap.rb<br />
├── config.ru<br />
├── db<br />
│   └── page.db<br />
├── Gemfile<br />
├── Gemfile.lock<br />
├── public<br />
│   ├── css<br />
│   ├── favicon.ico<br />
│   ├── img<br />
│   └── js<br />
├── README<br />
└── views<br />
&nbsp; &nbsp; ├── 404.erb<br />
&nbsp; &nbsp; ├── admin.erb<br />
&nbsp; &nbsp; ├── create_form.erb<br />
&nbsp; &nbsp; ├── edit_form.erb<br />
&nbsp; &nbsp; ├── layout.erb<br />
&nbsp; &nbsp; ├── page.erb<br />
&nbsp; &nbsp; └── pages.erb</div></td></tr></tbody></table></div>
<h5>6. Деплой на хероку</h5>
<p>Деплой почти ни чем не отличается от деплоя из предыдущей заметки, кроме переноса локальной базы данных на удаленный сервер heroku.</p>
<div class="codecolorer-container text railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">heroku db:push &nbsp;sqlite://db/page.db</div></td></tr></tbody></table></div>
<p>Молодцы heroku и эту возможность предусмотрели, после успешного выполнения данной команды, локальная база данных из sqlite3 скопируется в удаленную postgres.</p>
<blockquote><p>
если у вас на локальной машине стоял ruby 1.9.3, как у меня, то придется откатиться до версии 1.9.2. Это нужно для того, чтобы запушить локальную базу данных на хероку. Если вам это не нужно, то пропустите это шаг.
</p></blockquote>
<h5>Заключение</h5>
<p>Этой заметкой я закрпеляю небольшой логический этап в освоении мною нового для меня языка ruby. Язык мне очень нравится, но сразу переключиться на него попросту не могу. Синтаксис приятный глазу, легкие конструкции, шустрые фреймворки, работающие из коробки. Осталось только поделиться ссылкой на <a href="https://github.com/vredniy/simple-sinatra-cms" rel="nofollow">репозиторий на github</a> и работающий <a href="http://vredniy-sinatra.heroku.com/" rel="nofollow">проект на heroku</a>. Оставляйте комментарии, задавайте вопросы, поправляйте, если найдете неточности &#8212; я открыт для обсуждений, на этом я прощаюсь с вами и до новых встреч <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Ruby для начинающих CMS" class='wp-smiley colorbox-834' title="Ruby для начинающих CMS" /><br />
P.S.: вот так должно выглядеть приложение в конце<br />
<img src="http://vredniy.ru/wp-content/uploads/2012/02/sinatra-cms-heroku-800x483.jpg" alt="sinatra cms heroku 800x483 Ruby для начинающих CMS" title="sinatra-cms-heroku" width="600" height="362" class="aligncenter size-large wp-image-839 colorbox-834" /></p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/CzV7tb0464s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/02/ruby-sinatra-cms-heroku/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/02/ruby-sinatra-cms-heroku/</feedburner:origLink></item>
		<item>
		<title>Деплой ruby приложения на heroku</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/QJTP-Hxv8Rk/</link>
		<comments>http://vredniy.ru/2012/02/ruby-application-heroku/#comments</comments>
		<pubDate>Fri, 03 Feb 2012 19:51:25 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sinatra]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=823</guid>
		<description><![CDATA[Здравствуйте, уважаемые программисты или те, кто попал сюда случайно, сегодня речь пойдет о деплои ruby приложения на heroku. Бесплатный для небольших приложений хостинг, полюбившийся многим ruby, python разработчикам. Почему heroku? В первую очередь, потому что бесплатный, во-вторых, удобная развертка приложения позволяет сосредоточиться на разработке, а не на решении разнообразных проблем околопрограммерского плана. Инструментарий для деплоя [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fruby-application-heroku%2F"><br />
				<img class="colorbox-823"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2012%2F02%2Fruby-application-heroku%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=deploy,ruby,sinatra&amp;b=2" height="61" width="50" title="Деплой ruby приложения на heroku" alt=" Деплой ruby приложения на heroku" /><br />
			</a>
		</div>
<p><img src="http://vredniy.ru/wp-content/uploads/2012/02/heroku-150x150.jpg" alt="heroku 150x150 Деплой ruby приложения на heroku" title="heroku-deploy-sinatra" width="150" height="150" class="alignleft size-thumbnail wp-image-826 colorbox-823" />Здравствуйте, уважаемые программисты или те, кто попал сюда случайно, сегодня речь пойдет о деплои ruby приложения на heroku. Бесплатный для небольших приложений хостинг, полюбившийся многим ruby, python разработчикам.<br />
<span id="more-823"></span></p>
<h3>Почему heroku?</h3>
<p>В первую очередь, потому что бесплатный, во-вторых, удобная развертка приложения позволяет сосредоточиться на разработке, а не на решении разнообразных проблем околопрограммерского плана.</p>
<h3>Инструментарий для деплоя</h3>
<p>*nix система, куда без нее? ) установленный ruby, git, если вы знаете слово деплой, значит, для вас это до боли знакомые слова )</p>
<h3>Итак, начнем</h3>
<p>Регистрируемся на сайте <a href="https://api.heroku.com/signup" rel="nofollow">heroku</a> (куда в наши дни без регистрации? ). Создаем папку где будем размещать наше sinatra-приложение (почему именно sinatra? потому что мне нравится этот фреймворк &#8212; он легкий, несложный и позволяет сосредоточиться на изучении языка) на локальной машине, пусть это будет <strong>~/projects/heroku-sinatra</strong>.<br />
Далее создаем (как и для всех Rack-подобных приложений) файлы в корне <strong>config.ru</strong> и <strong>Gemfile</strong><br />
<strong>config.ru</strong> будет содержать следующее:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'./app/bootstrap.rb'</span><br />
<br />
run <span style="color:#6666ff; font-weight:bold;">Sinatra::Application</span></div></td></tr></tbody></table></div>
<p>этим самым мы подключаем файл приложения и запускаем оное.</p>
<p>Далее <strong>Gemfile</strong> для управления зависимостями, т.к. наше приложение простое и создано специально для ознакомления, нам достаточно написать пару строк:</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">source <span style="color:#ff3333; font-weight:bold;">:rubygems</span><br />
<br />
gem <span style="color:#996600;">'sinatra'</span></div></td></tr></tbody></table></div>
<p>Далее создадим файл <strong>./app/bootstrap.rb</strong>, который и будет являться нашим несложным приложением для экспериментов.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span><br />
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'sinatra'</span><br />
<br />
get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;erb <span style="color:#996600;">&quot;Hello, world, from Heroku at #{Time.now}&quot;</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Осталось несколько команд до деплоя. Тут вступает в дело gem heroku</p>
<p><strong>gem install heroku</strong> &#8212; устанавливаем необходимый гем, если вы еще не сделали этого ранее.</p>
<p>Далее нужно рассказать heroku кто же собирается деплоить (или попросту представиться, воспитанные ведь мы), для этого пишем в консоли</p>
<p><strong>heroku login</strong></p>
<p>и вписываем почту, которую вы указали в первом шаге (мы ведь ее еще помним, правда?) и пароль, который придет на email.</p>
<p>Половина дела сделана, остались сущие пустяки.</p>
<p><strong>git init</strong> &#8212; инициализируем git репозиторй<br />
<strong>git add .</strong> &#8212; добавляем в него все файлы (рекурсивно)<br />
<strong>git commit -am &#8216;hello heroku&#8217;</strong> &#8212; сохраняем изменения в локальном репозитории<br />
<strong>heroku create %желаемое имя приложения%</strong> &#8212; мы ведь хотим чтобы наше первое приложение имело благозвучное имя, если нет, то последний параметр можно опустить, heroku тоже умеет придумывать неплохие имена )</p>
<p><strong>git push -u heroku master</strong> &#8212; отправляем приложение на сервер</p>
<h3>После успешного деплоя</h3>
<p>Если все прошло гладко, такое разве бывает спросите вы, бывает &#8212; отвечу я. <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Деплой ruby приложения на heroku" class='wp-smiley colorbox-823' title="Деплой ruby приложения на heroku" /><br />
<strong>heroku open</strong> запустит нам наше приложение в браузере (нам ведь сложно оторваться от так полюбившейся консоли и взять в руки мышку, чтобы запустить браузер)</p>
<h3>Возможные проблемы</h3>
<p>Здесь небольшой список проблем, с которыми вы можете столкнуться (с которыми столкнулся я) при деплое.</p>
<p>Проблема с ключами &#8212; &#171;Permission denied (publickey)&#187;, то<br />
<strong>heroku keys::add ~/.ssh/id_rsa.pub</strong>  &#8212; отправляем наши публичные ключики на сервер, чтобы heroku знал с кем имеет дело. Если нет ключа, то генерируем его </p>
<p><strong>ssh-keygen -t rsa</strong> &#8212; и клацаем несколько раз Enter.<br />
<br />
В приложение закралась ошибка, то<br />
<strong>heroku logs</strong> &#8212; отобразит логи, в которых можно будет отыскать &#171;косячное&#187; место, исправить его и попробовать снова. Нам, разработчикам, сдаваться никак нельзя <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Деплой ruby приложения на heroku" class='wp-smiley colorbox-823' title="Деплой ruby приложения на heroku" /> </p>
<p>Теперь ваше &#8216;Hello, world&#8217; на Ruby, можно показывать друзьям/подругам/бабушке, да вообще кому захотите. Удачи вам в кодинге и меньше коварных ошибок в приложениях.<br />
В комментариях жду вопросов, если таковые появятся или предложения от руби-гуру, где накосячил я, я исправлюсь, чесслово <img src='http://vredniy.ru/wp-includes/images/smilies/icon_smile.gif' alt="icon smile Деплой ruby приложения на heroku" class='wp-smiley colorbox-823' title="Деплой ruby приложения на heroku" /> </p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/QJTP-Hxv8Rk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2012/02/ruby-application-heroku/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2012/02/ruby-application-heroku/</feedburner:origLink></item>
		<item>
		<title>Sinatra и Whois gem: маленькое приложение</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/Jzg-1SHALdw/</link>
		<comments>http://vredniy.ru/2011/11/ruby-sinatra-whois/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 22:26:34 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sinatra]]></category>
		<category><![CDATA[whois]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=800</guid>
		<description><![CDATA[Здравствуйте, уважаемые коллеги и те, кто может случайно забрел на мой блог. Сегодня речь пойдет о Ruby, но я не буду вдаваться в подробное описание языка, поэтому ограничимся базовой функциональностью замечательного фреймворка Sinatra. Вступление Мой отпуск подходит плавно к концу, но чтобы не зря тратить время решил я посвятить его изучению нового для меня языка [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2011%2F11%2Fruby-sinatra-whois%2F"><br />
				<img class="colorbox-800"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2011%2F11%2Fruby-sinatra-whois%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=ruby,sinatra,whois&amp;b=2" height="61" width="50" title="Sinatra и Whois gem: маленькое приложение" alt=" Sinatra и Whois gem: маленькое приложение" /><br />
			</a>
		</div>
<p>Здравствуйте, уважаемые коллеги и те, кто может случайно забрел на мой блог. Сегодня речь пойдет о Ruby, но я не буду вдаваться в подробное описание языка, поэтому ограничимся базовой функциональностью замечательного фреймворка Sinatra.</p>
<h3>Вступление</h3>
<p>Мой отпуск подходит плавно к концу, но чтобы не зря тратить время решил я посвятить его изучению нового для меня языка программирования. Почему Ruby, возможно назреет у вас вопрос. Отвечу так: я долго шел к смене языка программировани, нет, это не из-за того, что мне не нравится PHP, отнюдь, но захотелось чего-то другого во время отпуска, тем более, что время позволяет. Прежде чем остановиться на Ruby, мною было прочитано много килобайт материала, просмотрено много мегабайт видео презентаций и скринкастов, и я решил более не задаваться глупыми вопросами, а может Python, может еще что-нибудь, решил просто попробовать.</p>
<p><span id="more-800"></span></p>
<p><img src="http://vredniy.ru/wp-content/uploads/2011/11/ruby-sinatra-300x197.png" alt="ruby sinatra 300x197 Sinatra и Whois gem: маленькое приложение" title="ruby sinatra" width="300" height="197" class="alignleft size-medium wp-image-806 colorbox-800" />Почему Sinatra, а не Rails? Все просто: чтобы понять как работает такой большой веб-фреймворк, как Rails, понадобится намного больше времени, да и понять его без хорошего знания Ruby, я не рискну, а Sinatra в этом отношении в разы полегче, можно сказать, что это чистый Ruby.</p>
<h3>Постановка задачи</h3>
<p>Задача будет проста до безумия: у нас будет иметься одна страница с одним текстовым полем. Если мы введем туда корректное имя домена, приложение ответит нам доступен ли домен для регистрации и срок истечения, если домен зарегистрирован. </p>
<h3>Используемый инструментарий</h3>
<p>В первую очередь нам, конечно же, понадобится сервер с установленным на нем Ruby, локальный вполне подойдет. В этой короткой заметке я не буду рассказывать как его [сервер] установить, в интернете полным-полно подобных мануалов и раскрывают они тему исчерпывающе. В дополнение к гему sinatra, нам также понадобятся: whois (http://goo.gl/0jEJA) и гем json (им мы будем отдавать ответ).</p>
<h3>Реализация</h3>
<p>Приложение у нас будет состоять из двух экшнов: первый это главная страница, на которой и будет отображаться текстовый элемент и экшн, который будет отвечать за прием данных по средством AJAX, отправку запроса серверу whois и возвращению ответ в формате JSON.<br />
Шаблонизатором у нас будет выступать HAML, очень удобная и простая штука, так что приведу код шаблона главной страницы в формате haml.</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">!!!<br />
<span style="color:#006600; font-weight:bold;">%</span>html<br />
&nbsp; <span style="color:#006600; font-weight:bold;">%</span>head<br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>meta<span style="color:#006600; font-weight:bold;">&#123;</span>:content <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/html; charset=UTF-8&quot;</span>, <span style="color:#996600;">&quot;http-equiv&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;content-type&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">/</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>script<span style="color:#006600; font-weight:bold;">&#123;</span>:type <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'text/javascript'</span>, <span style="color:#ff3333; font-weight:bold;">:src</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'http://yandex.st/jquery/1.7.0/jquery.min.js'</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>script<span style="color:#006600; font-weight:bold;">&#123;</span>:type <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'text/javascript'</span>, <span style="color:#ff3333; font-weight:bold;">:src</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/javascripts/default.js'</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>title Маленькое приложение на Руби <span style="color:#006600; font-weight:bold;">&#40;</span>Sinatra, Whois, Json<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#006600; font-weight:bold;">%</span>body<br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>div<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span><span style="color:#CC0066; font-weight:bold;">p</span> Впишите какой<span style="color:#006600; font-weight:bold;">-</span>нибудь, желательно, корректный домен и нажмите Enter<br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>form<span style="color:#006600; font-weight:bold;">&#123;</span>:method <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'post'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'/ajax.json'</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>input<span style="color:#006600; font-weight:bold;">&#123;</span>:type <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;domain&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">%</span>ul<span style="color:#006600; font-weight:bold;">&#123;</span>:id <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'info'</span><span style="color:#006600; font-weight:bold;">&#125;</span></div></td></tr></tbody></table></div>
<p>Также приведу исходных код экшна главной страницы, который занимает всего 1 строчку. Его задача только отобразить шаблон. </p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">get <span style="color:#996600;">'/'</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp;haml <span style="color:#ff3333; font-weight:bold;">:index</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>Наш AJAX экшн будет срабатывать по POST запросу при отсылке данных по адресу /ajax.json</p>
<div class="codecolorer-container ruby railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; post <span style="color:#996600;">'/ajax.json'</span> <span style="color:#9966CC; font-weight:bold;">do</span> &nbsp;<br />
&nbsp; &nbsp; domain = params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:domain</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">begin</span><br />
&nbsp; &nbsp; &nbsp; info = Whois.<span style="color:#9900CC;">query</span><span style="color:#006600; font-weight:bold;">&#40;</span>domain<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">Whois::ServerNotFound</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span> <br />
&nbsp; &nbsp; content_type <span style="color:#ff3333; font-weight:bold;">:json</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:domain</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> domain, <span style="color:#ff3333; font-weight:bold;">:info</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#123;</span>:available <span style="color:#006600; font-weight:bold;">=&gt;</span> info.<span style="color:#9900CC;">available</span>?, <span style="color:#ff3333; font-weight:bold;">:registered</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> info.<span style="color:#9900CC;">registered</span>?, <span style="color:#ff3333; font-weight:bold;">:expires</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> info.<span style="color:#9900CC;">expires_on</span><span style="color:#006600; font-weight:bold;">&#125;</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">to_json</span> <span style="color:#9966CC; font-weight:bold;">unless</span> info.<span style="color:#0000FF; font-weight:bold;">nil</span>?<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></td></tr></tbody></table></div>
<p>В первой строке которого мы получаем имя домена через форму. Далее получаем необходимую информацию о домене, для того чтобы не сыпались в приложении исключения я оборачиваю вызов кода, который легко может выбросить исключения в обертку аля PHP try-catch. <strong>content_type json</strong>, как вы догадались, устанавливает формат ответа. В последней строке мы формируем JSON. Что удобно в Ruby, так это то, что не нужно возвращать значения, данный язык делает это сам, т.е. последняя строка в методе возвращает значение.</p>
<p>Осталось только связать нашу форму на главной странице и AJAX экшн. Для этих целей очень хорошо подойдет несколько строк на замечательном JavaScript-фреймворке jQuery. Задача &#8212; отправить AJAX запрос методом POST, дождаться ответа от сервера и заполнить список полями из полученного JSON.</p>
<div class="codecolorer-container javascript railscasts" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'form'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; $.<span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/ajax.json'</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">serialize</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Что-то пошло не так ('</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; <br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ul#info &gt; *'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">info</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>field<span style="color: #339933;">,</span> value<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ul#info'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;li&gt;&lt;strong&gt;'</span> <span style="color: #339933;">+</span> field <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&lt;/strong&gt; '</span> <span style="color: #339933;">+</span> value <span style="color: #339933;">+</span> <span style="color: #3366CC;">'&lt;/li&gt;'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'json'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<h3>Исходный код</h3>
<p>Исходный код вы можете посмотреть на гитхабе, <a href="https://github.com/vredniy/sinatra-whois" rel="nofollow">здесь</a>.</p>
<h3>Заключение</h3>
<p>Это была моя первая заметка на тему Ruby, надеюсь, мой блог и дальше будет пополняться подобными постами, потому что язык мне очень нравится, нравится своей гибкостью и необычностью (как программист на PHP говорю). Спасибо зв внимание и до новых встреч.</p>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/Jzg-1SHALdw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2011/11/ruby-sinatra-whois/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2011/11/ruby-sinatra-whois/</feedburner:origLink></item>
		<item>
		<title>Здоровый образ жизни и я</title>
		<link>http://feedproxy.google.com/~r/vredniy-ru/~3/zP-vWEBwl88/</link>
		<comments>http://vredniy.ru/2011/09/health-sport/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 19:34:39 +0000</pubDate>
		<dc:creator>Вредный</dc:creator>
				<category><![CDATA[программирование]]></category>
		<category><![CDATA[здоровье]]></category>
		<category><![CDATA[спорт]]></category>
		<category><![CDATA[фитнес]]></category>

		<guid isPermaLink="false">http://vredniy.ru/?p=792</guid>
		<description><![CDATA[Здравствуйте, уважаемые читатели моего техничесого блога. Сегодня занимательный для моего блога день &#8212; день, когда я решил разбавлять свои технические заметки заметками о спорте, книгаж, жизни и просто интересных вещах, в моей жизни которые происходят. Сегодня немного о спорте: в тренажерный зал записался два с половиной месяца назад и за это время (выполнял только базовые [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fvredniy.ru%2F2011%2F09%2Fhealth-sport%2F"><br />
				<img class="colorbox-792"  src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fvredniy.ru%2F2011%2F09%2Fhealth-sport%2F&amp;source=vredniy&amp;style=compact&amp;service=TinyURL.com&amp;hashtags=%D0%B7%D0%B4%D0%BE%D1%80%D0%BE%D0%B2%D1%8C%D0%B5,%D1%81%D0%BF%D0%BE%D1%80%D1%82,%D1%84%D0%B8%D1%82%D0%BD%D0%B5%D1%81&amp;b=2" height="61" width="50" title="Здоровый образ жизни и я" alt=" Здоровый образ жизни и я" /><br />
			</a>
		</div>
<p>Здравствуйте, уважаемые читатели моего техничесого блога. Сегодня занимательный для моего блога день &#8212; день, когда я решил разбавлять свои технические заметки заметками о спорте, книгаж, жизни и просто интересных вещах, в моей жизни которые происходят. </p>
<p>Сегодня немного о спорте: в тренажерный зал записался два с половиной месяца назад и за это время (выполнял только базовые упражнения, чтобы мыщцы после долгой пассивно-сидячей жизни привести в тонус) достиг кое-каких результатов. Веса может быть и стали намного больше, может и вообще больше не стали, но чувствовать я себя стал заметно лучше: ремень на джинсах стал застегиваться на одну-две дырки меньше, чем раньше. Футболки стали немного малы в основании рук &#8212; бицепсы и трицепсы дают о себе знать. От живота, конечно, я полносью не исправился, оказывается, сложно это сделать после многолетнего опыта пивопития, неправильного питания и пассивного образа жизни. Но живот стал меньше, хоть и кубиков пока не видать. </p>
<p><span id="more-792"></span></p>
<p><img src="http://vredniy.ru/wp-content/uploads/2011/09/healthy_skin_healthy_lifestyle-300x200.jpg" alt="healthy skin healthy lifestyle 300x200 Здоровый образ жизни и я" title="Здоровый образ жизни" width="300" height="200" class="alignleft size-medium wp-image-793 colorbox-792" />Сегодня забрал у тренера свою новую программу, по которой отзанимался шестое занятие. Тренировка расписана на 4 дня тренировки и 3 дня отдыха, т.к. тренажерный зал находится недалеко от места моей работы, поэтому посещение его в выходные дни для меня нецелесообразно. </p>
<p>Теперь подробнее о тренировках: первое что я делаю после того, как вступил в &#171;тренажерку&#187;, так это встаю на беговую дорожку и прохожу иногда и пробегаю 10-15 минут, дальше обязательная разминка, чтобы для мыщц упражнения не были большим стрессом. Дальше сам комплекс упражнений, после которого обязательные три подхода упражнений для пресса (3 вида упражнений). Завершает все пробежка 10-15 минутная.</p>
<h4>Упражнения:</h4>
<h6>Понедельник (ноги, спина, бицепс)</h6>
<ol>
<li>Сгибание ног</li>
<li>Жим ногами</li>
<li>Разгибание ног</li>
<li>Тяга вертикального блока к груди руками</li>
<li>Тяга Т-образного грифа</li>
<li>Тяга гантелей одной рукой</li>
<li>Сгибание рук со штангой стоя</li>
<li>Попеременный подъем гантелей стоя.</li>
</ol>
<h6>Вторник (грудь, плечи, трицепс)</h6>
<ol>
<li>Жим штанги на скамье под углом 45 градусов</li>
<li>Жим штанги на горизонтальной скамье</li>
<li>Жим гантелей на скамье под углом 45 градусов</li>
<li>Жим сидя</li>
<li>Задняя дельта</li>
<li>Махи гантелями в стороны сидя</li>
<li>Брусья</li>
<li>Разгибание &#171;канатом&#187;</li>
</ol>
<h6>Среда (отдых)</h6>
<h6>Четверг (ноги, спина, бицепс)</h6>
<ol>
<li>Жим ногами</li>
<li>Сведение ног</li>
<li>Тяга вертикального блока к груди широким хватом</li>
<li>Тяга горизонтального блока</li>
<li>Сгибание рук через пюпитр</li>
<li>Сгибание рук (&#171;молот&#187; или &#171;блок&#187;</li>
</ol>
<h6>Пятница (грудь, плечи, трицепс)</h6>
<ol>
<li>Разводка гантелей (30 градусов)</li>
<li>Сведение рук в тренажере</li>
<li>Жим гантелей сидя</li>
<li>&#171;Протяжка&#187;</li>
<li>&#171;Французский жим&#187; лежа</li>
<li>
<p>Разгибание одной рукой.</p>
<p>Вот мой комплекс упражнений и мой способ вести здоровый образ жизни. Может тем кто захотел начать пригодится данная заметка. Даже если нет, все равно удачи вам в любых начинаниях. </p>
</li>
</ol>
<img src="http://feeds.feedburner.com/~r/vredniy-ru/~4/zP-vWEBwl88" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://vredniy.ru/2011/09/health-sport/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://vredniy.ru/2011/09/health-sport/</feedburner:origLink></item>
	</channel>
</rss>

