Прошло около года с момента публичного дебюта Ruby on Rails в 25 июля, 2004. За этот довольно короткий срок, Rails превратилась из уже достаточно впечатляющей версии 0.5 в устрашающе-вдохновляющую, готовящуюся к выходу версию 1.0, которой удалось сохранить свою простоту использования и продуктивность, в то же время добавив будоражащий ум массив новых возможностей. Эта статья познакомит вас с компонентами грядущей версии Ruby on Rails 1.0 и постарается рассказать, о чём же собственно столько разговоров.

In this short time, Rails has progressed from an already impressive version 0.5 to an awe-inspiring, soon-to-be-released version 1.0 that managed to retain its ease of use and high productivity while adding a mind-boggling array of new features. This article introduces the components of the upcoming Ruby on Rails 1.0 and shows you what the fuss is all about.

Я не намереваюсь учить вас как использовать Rails для создания веб приложений. Для этого, вам скорей всего следует начать со статьи Rolling with Ruby on Rails . Эта статья, является введением и картой к огромному количеству возможностей Rails.

I don"t intend to teach you how to use Rails to write web applications. For that, you probably ought to start with Rolling with Ruby on Rails. This is an introduction and road map to the many features of Rails.

Высокая продуктивность и высокая скорость разработки

На уровне возможностей, Ruby on Rails не предлагает ничего нового. Существующие веб фреймворки уже всё это делали. В чём же тогда дело? Различие лежит в том, как это делает Ruby on Rails. Когда вы можете закончить простое веб приложение за дни вместо недель и более сложное за недели вместо месяцев, люди обращают на это внимание!

Это внимание было бы недолгим, если бы получавшиеся приложения были запутаны и их было бы тяжело поддерживать или расширять. К счастью, Ruby on Rails действительно облегчает правильные методы программирования, что приводит к хорошо сформированному и легко поддерживаемому коду.

Внимание также оказалось бы недолгим, если бы Ruby on Rails не имела глубины - то есть, если бы раз попробовав использовать её для чего-то сложнее самого простого веб приложения, вы сразу натыкались бы на стену, не имея возможности продолжить из-за ограничений системы. Опытные разработчики, которые знают толк во всемирной паутине и программировании не перестают повторять, что для Rails это не так. К примеру, автор Tomcat, Ant и Servlet API, James Duncan Davidson недавно написал:

The attention would also be short-lived if Ruby on Rails had no depth--that is, if once you tried to use it for anything beyond the simplest of web applications, you suddenly found yourself hitting a wall, unable to proceed due to inherent limitations. Experienced developers who know their way around the Web have repeatedly reported that this is not the case with Rails. For example, Tomcat, Ant, and the Servlet API author James Duncan Davidson recently wrote:

Rails это самая хорошо продуманная среда веб разработки которую я когда-либо использовал. И это за десять лет моей работы веб разработчиком. Я разрабатывал свои фреймворки, помогал разрабатывать Servlet API, и создал больше пары веб серверов с нуля. До Rails, никто раньше так не делал. Я не хочу сказать что они всё сделали правильно. Ни под каким видом она не совершенна. У меня есть несколько придирок к тому как всё собрано вместе. Но дело не в совершенстве. Дело в том, что Rails позволяет работать очень быстро, при том что есть глубина которая помогает вам двигаться вперёд. И у Rails это очень хорошо получается.

Rails is the most well thought-out web development framework I"ve ever used. And that"s in a decade of doing web applications for a living. I"ve built my own frameworks, helped develop the Servlet API, and have created more than a few web servers from scratch. Nobody has done it like this before. That"s not to say they got it all right. It"s by no means "perfect". I"ve got more than a few nits and picks about how things are put together. But "perfect" isn"t the point. The point is that it gets you up and going fast and has plenty of depth to keep you going. And Rails does that very well.

Может быть сложно поверить в то, что это возможно без какого-то значительного недостатка. К счастью, вам не придётся верить мне на слово (также как кому-либо ещё). Вы можете легко доказать себе за день или меньше просто пройдя через учебник по Ruby on Rails и тут же разработав скромное приложение на свой выбор. В конце концов, лучше один раз увидеть, чем сто раз услышать. Если вы не хотите смотреть на себя сверх продуктивного, вы всегда можете посмотреть на кого-то ещё, кто за вас делает всё это в новом Rails видео.

It may be hard to believe that this is possible without a significant downside. Fortunately, you don"t have to take my word for it (or anyone else"s). You can easily prove it to yourself in a day or less by going through a Ruby on Rails tutorial and then developing a modest web application of your own choosing. After all, seeing is believing! If you don"t want see yourself be amazingly productive, you can always watch someone else do it in the new Rails video.

Как Rails это делает?

Как хороший рецепт, Rails помогает вам достичь этого нового уровня продуктивности сочетая правильные ингриденты в правильном количестве. Вот несколько из важных ингридиентов который делают Rails такой, какая она есть.

Like a good recipe, Rails helps you achieve this new level of productivity by combining the right ingredients in the right amounts. Here are a few of the most important ingredients that make Rails what it is.

Ruby

Большая часть мощи Rails кроется в языке программирования Ruby. Уникальный дизайн Ruby делает легким создание языков для разных предметных областей и метапрограммирование. Rails пользуется этим на полную катушку.

Much of the power of Rails comes from the Ruby programming language. Ruby"s unique design makes it easy to create domain-specific languages and to do metaprogramming. Rails takes full advantage of this.

Полная реализация MVC

You can find more details in A Guide to Testing Rails.

Active Record

Active Record это часть Rails которая отвечает за автоматическую динамическую привязку таблиц вашей базы данных к объектам моделей. Это буква M в MVC, и это реализация слоя ORM в Rails.

Active Record is the part of Rails that handles the automatic mapping of your database tables to your runtime model objects. It"s the M in MVC, and it is Rails" implementation of an ORM layer.

Для самых распространённых случаев использования (и не таких уж распространённых), вам никогда не придётся видеть или писать SQL код для доступа к или обновления вашей базы. Цель Active Record - работать исключительно с реляционными базами данных; она не пытается абстрагироваться от использования SQL. Когда надо, Active Record облегчает использование ваших собственных SQL запросов, для тех сложных случаев где это необходимо. Но даже в таких случаях, часто можно обойтись без написания SQL кода вручную.

For all the common uses (and some of the not-so-common ones), you"ll never need to see or use SQL when accessing or updating your database. Active Record"s goal is specifically to work with relational databases; it does not try to abstract away its SQL usage. Active Record makes it easy to use your own custom SQL for those complicated cases where it is necessary. Even so, it is rarely needed.

Автоматическая привязка

Active Record автоматически привязывает таблицы к классам, строки к объектам (экземплярам класса модели), и поля к аттрибутам объекта. Например код:

Active Record automatically maps tables to classes, rows to objects (instances of the model classes), and columns to object attributes. For example:

Class Product < ActiveRecord::Base end

автоматически привязывается к таблице с именем products, такой как:

automatically maps to the table named products, such as:

CREATE TABLE products (id int(11) NOT NULL auto_increment, name varchar(255), PRIMARY KEY (id));

а также автоматически создаёт аттрибут name который вы можете использовать так:

which also automatically creates a name attribute that you can use like this:

My_product = Product.find(:first) STDOUT.print my_product.name my_product.name = "Название нового продукта"

Active Record использует правила плюрализации английского языка для привязки классов к таблицам. Имя класса модели состоит в единственном числе и пишется с заглавной буквы, а имя таблицы в множественном и в нижнем регистре. Вот несколько примеров:

Active Record uses English pluralization rules to map classes to tables. The model class name is singular and capitalized, while the table name is plural and lowercased. Examples include:

  • Класс модели Invoice привязывается к таблице invoices.
  • Класс модели Person привязывается к таблице people.
  • Класс модели Country привязывается к таблице countries.
  • Класс модели SecurityLevel привязывается к таблице security_levels.
  • An Invoice model class maps to an invoices table.
  • A Person model class maps to a people table.
  • A Country model class maps to a countries table.
  • A SecurityLevel model class maps to a security_levels table.

Соглашение о единственных/множественных числах выливается в довольно натурально читаемый код. Заметьте как разумна привязка в своём использовании правил плюрализации английского. Также обратите внимание, что имена классов используют CamelCase (правило Ruby), в отличии от таблиц, имена которых все в нижнем регистре со знаками нижнего подчёркивания между словами.

This singular/plural convention results in code that reads fairly naturally. Notice how this mapping is intelligent in its use of English pluralization rules. Also note that the class names use CamelCase (a Ruby convention), while the table names are all lowercase with underscores between words.

В тех случаях когда это не срабатывает (например тогда, когда вам приходится работать с устаревшей базой данных, где вы не имеете контроля над именами таблиц), вы можете прямо указать Active Record какое имя следует использовать.

In cases where this does not work (such as interfacing with a legacy database with which you have no control over the names), you can also explicitly tell Active Record what name it should use.

There is a lot more to Active Record than I can cover here. To learn more, consult the Active Record API.

Action Pack

Action Pack реализует уровни контроллера и представления в Rails.

Action Pack implements both the view and controller part of Rails.

Шаблоны представления

Шаблоны представления формируют HTML который возвращается в ответе браузеру. Шаблоны являются файлами rhtml (HTML со встроенным Ruby) которые очень похожи на ASP или JSP файлы. Текст внутри <% %> это Ruby код который будет запущен, а текст внутри <%= %> это Ruby код который будет также запущен и результат запуска которого будет подставлен обратно в HTML.

View templates specify the HTML to return in response to a browser request. View templates are rhtml files (HTML with embedded Ruby) that are very similar to ASP or JSP files. Text within <% %> is Ruby code to execute, and text within <%= %> is also Ruby code to execute and substitute the results back into the HTML.

Счета для <%= @name %> <% render_partial "invoices_by_customer" %>

По умолчанию, Rails попытается найти шаблон чьё имя совпадает с действием которое сейчас выполняется. Если например, Rails выполняет действие edit в вашем InvoiceController, тогда она попытается найти и вывести шаблон представления .../app/views/invoices/edit.rhtml .

By default, Rails will try to find a template whose name matches the currently executing action. If, for example, Rails executes an edit action in your InvoiceController, then it will attempt to find and render the view template .../app/views/invoices/edit.rhtml.

Вы можете также конструировать XML (или HTML) вывод в действии вашего контроллера. Это полезно, к примеру, для построения RSS лент или ответа на XML-RPC запросы. В следующем примере, xm это экземпляр класса XmlMarkup .

You can also build up XML (or HTML) output programmatically in your controller action. This is useful, for example, for building RSS feeds or responding to XML-RPC requests. In the following example, xm is an XmlMarkup object.

Xm.em("подчёркнутый") # => подчёркнутый xm.em { xmm.b("emp & bold") } # => emph & bold xm.a("A Link", "href"=>"http://onestepback.org") # => A Link xm.div { br } # =>


xm.target("name"=>"compile", "option"=>"fast") # => # ВНИМАНИЕ: порядок аттрибутов не сохраняется. xm.instruct! # xm.html { # xm.head { # xm.title("История") # История } # xm.body { # xm.comment! "HI" # xm.h1("Заголовок") #

Заголовок

xm.p("параграф") #

параграф

} # } #

Роутинг URL

Запрашиваемый URL всегда привязывается к какому-то действию внутри контроллера. Контроллер это простой класс Ruby и каждое действие реализованное контроллером это публичный метод этого класса. По умолчанию, URL привязан к действию по следующей схеме:

An incoming URL always maps to some action within a controller. A controller is simply a Ruby class, and each action implemented by the controller is a public method within the controller class. The default mapping from URL to action method is (in "Rails-speak"):

/:controller/:action/:id

Это легче всего объяснить на примере. Если Rails получает URL http://myapp.com/invoices/show/37 , то она автоматически привяжет его к классу-контроллеру InvoicesController и к методу этого класса под именем show. Rails также передаст значение 37 в метод как часть хэша параметров под именем id. Хэш параметров содержит в себе значения полей запроса(взятых из URL) и данные элементов форм. Код может выглядеть следующим образом:

This is easiest to explain by an example. If Rails received the URL http://myapp.com/invoices/show/37 , Rails would route this to a controller class named InvoicesController and within that class to a method named show. Rails would also pass the 37 to the method as the id member of the parameter hash that also holds the values of query parameters and form fields. The code might look like this:

Class InvoicesController def show @invoice = Invoice.find(params[:id]) end end

Поскольку действия это методы сгруппированные внутри контроллера (вместо отдельных командных объектов), они могут легко разделять между собой вспомогательные методы.

Because actions are methods grouped within a controller (instead of separate command objects), they can easily share helper methods.

Если стандартный способ привязки URL вас не устраивает, вы можете с лёгкостью указать свои правила роутинга, даже используя регулярные выражения. Поскольку Rails реализует свой механизм URL роутинга, вам не надо связываться с Apache mod_rewrite и ваши правила роутинга будут работать одинаково на всех веб серверах.

If the default URL routing does not meet your needs, you can easily specify your own routing rules, even using regular expressions. Because Rails implements its own URL routing, you don"t need to mess with Apache"s mod_rewrite, and your routing rules will work the same under all web servers.

Правила роутинга URL в Rails это простой Ruby код. Вот пример:

Rails routing rules are Ruby code. Here is an example:

Map.connect "date/:year/:month/:day", :controller => "blog", :action => "by_date", :month => nil, :day => nil, :requirements => {:year => /\d{4}/, :day => /\d{1,2}/, :month => /\d{1,2}/}

С этим правилом роутинга становятся рабочими следующие адреса:

With this routing rule, the following URLs are valid:

Http://myblog.com/date/2005 http://myblog.com/date/2005/08 http://myblog.com/date/2005/08/01

Это правило разбивает URL содержащий дату, которую, блог может использовать для отображения постов за конкретное число. URL который совпадает с правилом будет привязан к классу BlogController и к методу by_date. Хэш параметров будет содержать значения для года из четырёх цифр(/\d{4}/ это регулярное выражение Ruby) и месяц и день из двух. Также, месяц и день не обязательны; если значение не присутствует, в хэше параметров будет сохранено значение по умолчанию - nil.

This rule decomposes a URL containing a date that, perhaps, a blog might use to display the postings for a particular date. A URL that matches this form will map to the BlogController class and the by_date method. The parameter hash will contain values for a four-digit year (/\d{4}/ is a Ruby regular expression), a two-digit month, and a two-digit day. Further, the month and day are optional; if no values are present, the parameter hash will contain the default value of nil.

The ActionController::Filters documentation has more details.

Помошники (helpers)

Помошники это умные методы (функции) которые помогают вашим шаблонам представления генерировать HTML. Они используют ваши объекты модели и классы контроллеров для создания HTML и в дальнейшем, избавят вас от траты лишнего времени и усилий. Конечно, это также значит что вам придётся писать меньше строк кода, но держу пари, об этом вы уже итак догадались.

Helpers are smart methods (functions) that help your view templates generate HTML. They know to use your model objects and controller classes to create just the right HTML and, in the process, save you a lot of time and effort. Of course, this also means you write fewer lines of code, but I bet you already guessed that.

Вы можете создавать своих собственных помошников, но как вы могли догадаться несколько помошников поставляется встроенными в Rails. Помошник link_to, например, генерирует тэги ссылок которые ссылаются на контроллеры и действия. Пример:

You can write your own helpers, but as you might expect, several come built into Rails. The link_to helper, for example, generates anchor tags that create links to controllers and actions. For example:

<%= link_to "Помощь", { :action => "help" } %>

creates a link to the help action (method) in the current controller (whatever controller is handling the current request). The text of the link (what the user sees) is Help.

<%= link_to "Содержание справки", { :controller => "help", :action => "index" } %>

This creates a link to the index method in the HelpController class. The text of the link will be Master Help Index.

<%= link_to "Удалить этот счёт", { :controller => "invoices", :action => "delete", :id => @invoice.id }, :confirm => "Вы действительно хотите это удалить?" %>

Это создаст ссылку на метод delete в классе InvoiceController, и передаст параметр id (в качестве указателя на то, какой счёт нужно удалить). Здесь также используется специальная опция confirm которая создаёт всплывающее окно подтверждения через JavaScript.

This creates a link to the delete method in the InvoicesController class, and passes an id parameter (presumably the ID of the invoice to delete). This also uses a special confirm option that creates JavaScript to pop up a confirmation dialog letting the user continue or abort.

Существует большой набор помощников для создания форм просмотра и обновления значение объектов ваших ActiveRecord моделей, то есть -- для значений в вашей базе данных. Предположим что в вашей базе данных есть таблица people со столбцами для имени, пароля, описания и булева значения определяющего женат человек или холост (ОК, довольно странная табличка вышла:). Вот часть шаблона с примером тэгов формы которые можно было бы использовать. (Допустим что переменная @person содержит объект класса Person, считанный из строки в таблице people.)

There is a substantial set of helpers for creating form fields to display and update values in your Active Record model objects, which effectively means values in your database. Assume that your database has a people table with columns for the name, the password, a description, and a Boolean value to indicate whether the person is single or married (OK, so this is a strange table--just humor me). Here"s a partial view template with a sampling of form tags that could be used. (Assume that the variable @person contains a person object read from a row of the people table.)

Имя: <%= text_field "person", "name", "size" => 20 %> Пароль: <%= password_field "person", "password", "maxsize" => 20 %> Холост?: <%= check_box "person", "single" %> Описание: <%= text_area "person", "description", "cols" => 20 %>

Данный код генерирует следующий HTML ответ:

Имя: Пароль: Холост?: Описание:

Есть помощники для создания тэгов option для списков select из набора строк считанных из базы данных; помощники для работы с датами, числами и валютой; и много других.

There are helpers to create the option tags for a select list from a collection of rows read from the database; helpers for working with dates, numbers, and currency; and much more. There are different categories of built-in helpers, in several actual files. To learn more about them, see:

AJAX и JavaScript помощники

Rails включает в себя JavaScript библиотеку Prototype для реализации своей поддержки AJAX, визуальных эффектов и drag-n-drop возможностей.

Rails integrates the Prototype JavaScript library to implement its browser-side Ajax support, visual effects, and drag-and-drop abilities.

Модель того, как Rails реализует AJAX операции проста и надёжна. Как только браузер обработал и отобразил первоначальную страницу, различные действия пользователя могут вызвать либо отображение новой страницы (как в традиционных веб-приложениях) либо инициировать AJAX действие:

Rails has a simple, consistent model for how it implements Ajax operations. Once the browser has rendered and displayed the initial web page, different user actions cause it to display a new web page (like any traditional web app) or trigger an Ajax operation:

  1. Срабатывает триггер. Это может быть кликом пользователя на кнопку или ссылку, изменение данных в форме или поле, или просто временный триггер (на основе таймера).
  2. Клиент асинхронно отсылает данные ассоциированные с триггером (поле или целую форму) к действию-обработчику на стороне сервера через XMLHttpRequest.
  3. На стороне сервера действие-обработчик выполняет какие-то действия над данными и возвращает HTML фрагмент в качестве ответа.
  4. JavaScript на стороне клиента (код генерируется Rails автоматически) принимает этот HTML фрагмент и использует его для обновления конкретной части HTML текущей страницы, часто фрагмент подставляется содержимым в тэг
    .
  1. A trigger action occurs. This could be the user clicking on a button or link, the user making changes to the data on a form or in a field, or just a periodic trigger (based on a timer).
  2. The client sends data associated with the trigger (a field or an entire form) asynchronously to an action handler on the server via XMLHttpRequest.
  3. The server-side action handler takes some action based on the data, and returns an HTML fragment as its response.
  4. The client-side JavaScript (created automatically by Rails) receives the HTML fragment and uses it to update a specified part of the current page"s HTML, often the content of a
    tag.

Вся прелесть в том, как просто Rails позволяет реализовать всё это в вашем веб-приложении. Следующий простой пример добавляет новые элементы в список:

The real beauty is how easy Rails makes it to implement all of this in your web application. The following simple example adds new items to a list:

Демонстрация списка с AJAX <%= javascript_include_tag "prototype" %>

Добавить к списку с помощью AJAX

<%= form_remote_tag(:update => "my_list", :url => { :action => :add_item }, :position => "top") %> Текст нового элемента: <%= text_field_tag:newitem %> <%= submit_tag "Добавить элемент через AJAX" %> <%= end_form_tag %>
  • Начальный элемент... добавьте ещё!

The Prototype library also provides the Rails developer with a wealth of browser-side visual effects. Script.aculo.us provides documentation and live demos of the Prototype library effects. Prototype also lets you easily add drag-and-drop features to your web application. Script.aculo.us also has live demos and documentation for Prototype"s drag-and-drop support.

Макеты (Layouts)

Макеты позволюят вам указать набор основных элементов для отображения на каждой странице выдаваемой контроллером. Это обычно полезно для вывода общей шапки, низа и боковых панелей. По умолчанию, Rails смотрит в свой каталог layouts в поисках rhtml файла чьё имя совпадает с именем контроллера. Шаблон макета может выглядеть вот так:

Layouts let you specify a common set of display elements for every page rendered by a controller. This is typically useful for common headers, footers, and sidebars. By default, Rails looks in its layouts directory for an rhtml file whose name matches the controller"s name. A layout template might look like this:

<%= @page_title %>

Шапка для этого макета
<%= @content_for_layout %>
Низ этого макета

Rails подставит HTML который сгенерируется действием в этот макет, в то место где написано @content_for_layout.

Rails will substitute the HTML that an action renders into the above layout where it says @content_for_layout.

Контроллер также может прямо указывать какой макет следует использовать для всех его действий. Это упрощяет задачу использования одного макета для нескольких контроллеров. Вы можете менять шаблон макета даже динамически, в режиме runtime. Например, использовать разные макеты для пользователей вошедших в систему и для анонимных посетителей.

The controller can also directly specify the name of the layout template to use for all its actions. This makes it easy to use the same layout for multiple controllers. You can even dynamically choose a layout template at runtime. For example, you could use one layout for logged-in users and a different one for anonymous users.

To learn more about layouts, see the ActionController::Layout documentation.

Partials и компоненты

Компоненты и partials (части, отрывки. прим.пер.) позволяют вам разделить ваши шаблоны представления на модули.

Components and partials allow you to modularize your view templates.

Проще всего использовать partials, которые позволяют вам выделить общую часть шаблона в отдельный файл и затем отображать его из множества других шаблонов (или много раз в одном шаблоне).

Шаблоны partials всегда имеют знак нижнего подчёркивания (_) перед названием их файла, чтобы было легче отлечить их от полных шаблонов.

The simplest are partials, which allow you to extract a common piece of a template into a separate file and then render it from many other templates (or many times within a single template). Partial templates always have a leading underscore on their filenames to distinguish them from full templates.

Типичный пример использования partials это отображение массива (или другой коллекции) элементов.

A typical use of a partial is for rendering a collections of items.

<% for ad in @advertisements %> <%= render:partial => "adview", :locals => { :item => ad } %> <% end %>

Это отобразит шаблон partial _adview.rhtml несколько раз (по разу на каждый элемент массива @advertisments). Для каждого отображения, Rails будет передавать в _adview.rhtml локальную переменную с именем item которая содержит объект ad.

This renders the partial template _adview.rhtml multiple times (once for each ad in the collection @advertisements). For each rendering, Rails will pass _adview.rhtml a local variable named item that contains the ad object to use.

As with Active Record in the previous section, there is a lot more to Action Pack than I can cover here. To learn more, look at the Action Pack API.

Action Mailer

Action Mailer это простая технология для отправки и приёма email в вашем веб-приложении. Вот метод для отправки email с вложением:

Action Mailer is a simple facility for sending and receiving email in your web application. Here"s a method that sends an email with an attachment:

# отправляем email с вложением def signup_notification(recipient) recipients recipient.email_address_with_name subject "Информация о новом аккаунте" from "[email protected]" attachment:content_type => "image/jpeg", :body => File.read("an-image.jpg") attachment "application/pdf" do |a| a.body = generate_your_pdf_here() end end

To learn more, see the Action Mailer API, and Chapter 19 of the book Agile Web Development with Rails.

Action Web Service

Action Web Service реализует серверную поддержку для протоколов веб-служб SOAP и XML-RPC, позволяет просто создавать свои API и публиковать их через WSDL.

Action Web Service implements server-side support for the SOAP and XML-RPC web service protocols and makes it easy for you to create web service APIs and publish them via WSDL.

This snippet shows only two of the seven API methods defined in this class by Typo. To learn more, see the Action Web Service Manual.

Мысли о разделении

Обычно можно разделить фреймворки для создания веб-приложения и разработчиков которые их используют на две отдельных категории. В одном конце спектра находятся фреймворки-тяжеловесы для "серъёзных" программистов, на другой -- лёгкие, простые для использования фреймфорки для любителей "поиграть." Каждая из этих групп чаще всего относится друг к другу без всякого уважения.

You can usually divide web application frameworks and the developers who use them into two distinct categories. At one end of the spectrum, you have the heavy-duty frameworks for the "serious" developers, and at the other end you have the lightweight, easy-to-use frameworks for the "toy" developers. Each of these groups generally regards the other with disdain.

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

One of the most interesting things is that Rails is attracting developers from both camps. The high-end developers are tired of the repetitive, low-productivity routine that they have been forced to endure, while the low-end developers are tired of battling a mess of unmanageable code when their web apps move beyond the simple. Both of these disparate groups find that Rails provides sustainable relief for their pain. I don"t know about you, but I find this quite remarkable!

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

At the moment, Ruby on Rails barely captures a tiny percentage of web development projects. Yet it is rapidly gaining mind share, and many respected software development leaders have been testing the waters with Rails and publicly singing its praises.

Возможно настало время вам тоже попробовать Rails, чтобы самому убедиться о чём же собственно весь шум.

Добрый день, друзья. Не так давно мы с друзьями-коллегами решили поизучать Ruby on Rails – что это такое и с чем едят – для использования в будущем при разработке своих проектов.

Так как знаний по данной теме не было вообще, то и двигаться решили постепенно. При начальной установке Ruby с Rails 3.0 мы столкнулись с некоторыми трудностями, о которых в мануалах так сходу никто не упоминал. Поэтому я решил написать это небольшое руководство (которое является обобщением собственного опыта и перевода мануала на guides.rubyonrails.org/getting_started.html) по изначальной установке и настройке Ruby on Rails 3.0 для того, чтобы помочь таким же начинающим как я найти полезную информацию в одном месте и сэкономить свое время.

Манипуляции проводились на системе Windows XP SP2. На Windows 7 все то же самое, а на Висте рельсы у меня не поставились, но об этом позже.

Итак, для начала надо скачать Ruby installer . Инсталляция там нетрудная и все ясно (только сразу обновите переменную PATH, как это предлагается сделать).

Потом запустить командную строку с поддержкой Ruby.

Теперь нам нужно установить рельсы. В командной строке пишем:

gem install rails

На Висте ничегошеньки не получилось – при запуске этой команды появлялось сообщение о том, что не удалось найти папку C:\Users\Владелец. Наверняка, дело тут было в кириллице в названии папки, но особо в детали я вдаваться не стал.

Мы для своих начальных нужд будем использовать базу sqlite3. Чтобы все прошло корректно, нужно будет скачать 2 архива: и и распаковать их в папку с RoR 3.

Теперь в командной строке набираем:

gem install sqlite3-ruby

После завершении установки библиотек sqlite3 нам надо будет создать свое приложение, в нашем случае блог. В командной строке пишем:

rails new blog

Наш блог создан, теперь надо перейти в папку приложения:

Приложения Rails для управления gem-зависимостями по умолчанию используют Bundler. Так как кроме тех gem’ов, что у нас уже есть, других не требуется, можно просто написать:

bundle install

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

Тут я приведу часть дефолтного файла конфигурации (config/database.yml) с информацией по соединению для среды разработки:

Теперь, после конфигурации базы данных, самое время скомандовать рельсам создать пустую базу. Это можно сделать с помощью команды rake:

rake db:create

После этого в папке db/ будут созданы базы development и test.

Собственно, теперь у нас уже есть функционирующее Rails-приложение. Чтобы в этом убедиться, нужно запустить веб-сервер командой:

rails server

Увидеть свое приложение в действии можно если открыть браузер и набрать в адресной строке localhost :3000

Страница «Welcome Aboard» - это тест для Rails-приложения, позволяющий убедиться, что вы сконфигурировали программное обеспечении верно. Посмотреть информации о среде вашего приложения можно кликнув на ссылку «About your application’s environment».

Чтобы заставить Rails сказать «Привет», нужны, как минимум, котроллер и представление (view). К счатью, для их создания понадобится всего лишь одна команда:

rails generate controller home index

Rails создаст несколько файлов, включая app/views/home/index.html.erb. Это образец, который будет использоваться для отображения результатов метода index в контроллере home. Откройте этот файл в текстовом редакторе и отредактируйте таким образом, чтобы он содержал лишь одну строчку кода:

  1. < h1 > Hello, Rails!

Теперь, после того как мы создали котроллер и представление, нам надо как-то сказать рельсам когда отображать страницу «Hello Rails». В нашем случае, мы хотим, чтобы эта страница отображалась по корневому URL нашего сайта localhost :3000, вместо тестовой страницы «Welcome Aboard». Первым делом надо удалить дефолтную страницу из нашего приложения:

Del index.html

Теперь нам надо сообщить Rails, где находится наша нынешняя домашняя страница. Откройте файл config/routes.rb в текстовом редакторе. Это файл маршрутизации нашего приложения, который содержит точки входа, написанные на специальном языке DSL (domain-specific language). В этом файле содержится множество примеров путей (они закомментированы), и один из них как раз показывает как соединить свою корневую страницу с конкретным контроллером и выполнить действие. Найдите строчку, которая начинается с root:to, раскомментируйте её и поменяйте, чтобы она выглядела примерно вот так:

root:to => «home#index» скажет Rails отображать действие root на действие (метод) index контроллера home.

Теперь если вы зайдете на localhost :3000, то увидите надпись «Hello, Rails!»

В Rails есть понятие строительных лесов (Scaffold) - это быстрый способ создания главных частей приложения. Если вы хотите создать модели, представления и контроллеры, то это именно тот инструмент, который следует использовать.

В нашем случае (приложение-блог) можно начать с создания при помощи Scaffolding ресурса Post, который будет представлять собой пост в блоге. Для этого нужно написать такую команду:

rails generate scaffold Post name:string title:string content:text

Один из файлов, создаваемых командой rails generate scaffold это миграция базы данных (database migration). Миграции – это классы Ruby, которые разработаны для того, чтобы упростить создания и изменение таблиц баз данных. Для запуска миграций Rails использует команды rake, и есть возможность отменить миграцию после того, как она была применена к базе данных. Название файла миграции включает в себя временную метку, для того, чтобы легко было убедиться в том, что миграции запускаются в порядке их создания.

Если вы откроете файл db/migrate/20100917061914_create_posts.rb (помните, что название вашего файла будет слегка отличаться), то увидите там следующее:

  1. class CreatePosts < ActiveRecord::Migration
  2. def self.up
  3. create_table:posts do |t|
  4. t.string :name
  5. t.string :title
  6. t.text:content
  7. t.timestamps
  8. def self.down
  9. drop_table:posts

Эта миграция создает два метода up, вызываемых при запуске миграции в базу данных, и down, который используется в случае, когда нужно откатить изменения, сделанные в базе данных этой миграцией. Команда up создает таблицу posts с двумя строковыми столбцами и одним текстовым столбцом. Также она генерирует два поля для временных меток, которые нужны для отслеживания создания записей и изменения данных.

Теперь можно запустить миграцию командой:

rake db:migrate

Rails выполнит эту миграцию и сообщит о создании таблицы Posts.

Чтобы подключить посты к домашней странице, которую мы создали ранее, можно добавить ссылку на неё. Откройте файл app/views/home/index.html.erb и измените его следующим образом:

  1. < h1 > Hello, Rails!
  2. <% = link_to "My Blog" , posts_path %>

Метод link_to - один из встроенных в Rails помощников (helper). Он создает гиперссылку, основанную на тексте, который надо отображать и на том пути, куда надо обращаться – в данном случае путь к постам.

Теперь всё готово для того, чтобы начать работу с постами. Чтобы это сделать, нужно открыть ссылку

Гэри Гэри Полличе (Gary Pollice)
Опубликовано 27.05.2008

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

В поисках большей отдачи на единицу трудовых затрат

С тех пор, как программисты начали создавать программы, они не перестают думать о том, как вложить больше потребительской ценности в программы при тех же трудовых затратах. В последние пятьдесят лет появилось немало теорий о том, как этого добиться. Мы, безусловно, стали свидетелями эволюции языков программирования высокого уровня. Но постепенное совершенствование высокоуровневых языков вряд ли заставит нас подпрыгнуть на стуле, хлопнуть себя по лбу и воскликнуть "ну надо же!" Даже динамичные языки программирования, которые в 90-е годы были отнесены к категории "языков сверхвысокого уровня" (Very High Level Language, VHLL), не смогли предложить тех преимуществ, которые большинство из нас хотели бы получить и которые необходимы для обеспечения соответствия все возрастающим требованиям к программному обеспечению.

Мы предлагали идеи по поводу того, как повысить производительность труда программиста при помощи многократно используемых инфраструктур, перекрестных технологий, например, аспектно-ориентированного программирования, компонентной разработки, сервис-ориентированных архитектур, архитектуры, управляемой моделями, и многое другое. Все это давало определенный прирост производительности при условии правильного применения. Хотя мы до сих пор не создали технологии,которая позволила бы создавать программы без участия программиста (а именно об этом мечтают некоторые специалисты), мы сделали большой шаг вперед в направлении повышения производительности труда программистов. Тем не менее, мы все еще не получили 10-100 кратного повышения производительности, о котором мы мечтаем.

Прежде чем продолжить рассказ, хочу предупредить, что инфраструктура Rails также не дает нам такого выигрыша в общем случае. Однако в предметной области создания Web-приложений я наблюдал примеры, в которых Rails обеспечивал именно такую производительность.

Что такое Rails?

Rails - это инфраструктура, построенная на базе языка программирования Ruby и предназначенная для разработки, обслуживания и развертывания Web-приложений. С некоторыми допущениями инфраструктуру можно определить как генератор приложений или полуфабрикат приложения, который можно приспособить для различных целей (использования в различных предметных областях). Вот и все! Rails представляет собой расширение общего назначения для языка Ruby. Эта инфраструктура разработана для конкретной предметной области - Web-разработки. Rails строится на нескольких базовых принципах, которые значительно облегчают некоторые обычные задачи и делают возможным выполнение тех задач, которые недостижимы обычными средствами. Rails щедро вознаграждает программистов за соблюдение соглашений, принятых проектировщиками этой инфраструктуры, тем, что генерирует большую часть типичного Web-приложения, требуя очень небольшого объема программирования. Вы можете удивить своих коллег и руководителей, создавая мастерски сделанные Web-приложения, даже если вы всего лишь новичок в сфере Web-технологий.

Rails, в некоторых статьях называемый также "Ruby on Rails" - детище Дэвида Хейнемейера Ханссона (David Heinemeier Hansson), разработчика Web-приложений из Дании, использующего в работе язык программирования Ruby. Он заметил, что в процессе создания приложений ему приходится выполнять много общих задач. Как многие хорошие разработчики, он приступил к поиску способов автоматизации этой работы. Результатом этих поисков стала инфраструктура Rails. Hansson создал Rails на основе приложения под названием Basecamp. Фактически, Rails был извлечен из Basecamp и подвергнут генерализации путем выделения общих моментов и инкапсуляции изменчивости. Именно этот принцип мы обычно используем для создания языков, специфичных для различных предметных областей.

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

Простой пример

Вероятно, каждая статья или книга о Rails начинается простым примером. Я не стану приводить такой пример и подробно его описывать, просто продемонстрирую вам особенно яркие моменты примера из самой популярной книги по Rails, Agile Development with Rails (Динамичная разработка при помощи Rails), авторы Томас (Thomas) и Ханссон (Hansson). Этот пример представляет собой основу сайта интернет-магазина. Продукты, которые мы хотим продавать, имеют наименование, описание, изображение и цену. После того, как я потратил полчаса на чтение и изучение текста, я нашел в приложении точку, в которой можно добавлять продукты в базу данных, изменять информацию о них и удалять их. Это приложение использует обычную архитектуру Model-View-Controller (Модель-представление-контроллер), а Rails облегчает сохранение разделения ответственностей, поскольку эта инфраструктура автоматически генерирует корректные исходные файлы в отдельных каталогах, что делает очевидным их назначение.

Тело окончательной Web-страницы, которую я создал, показано на рисунке 1. В моем каталоге на данный момент только два продукта, но на этой странице мы можем увидеть некоторые моменты. Если продукт имеет изображение типа моей схемы механизма по наклейке этикеток, оно отображается на странице. Отображается первая часть описания продукта вместе с разметкой HTML. Рядом с каждым продуктом имеются три ссылки, чтобы можно было увидеть, как выглядит продукт, когда мы отображаем его, редактируем элемент или удаляем его. Кроме того, имеется ссылка на страницу создания нового продукта. Мы явно не готовы предъявить эту Web-страницу миру, но зато можем приступить к работе с заинтересованными лицами, которые предъявляют требования к нашему приложению. Это позволяет нам использовать итеративный подход к получению определенных требований, их реализации, анализу работы и внесению изменений перед следующей итерацией.

Рисунок 1. Страница управления каталогом продукции

Внешняя отделка моей Web-страницы вряд ли может кого-либо удивить, но то, что мне пришлось сделать к этому моменту, отличается поразительно малым объемом. Я измеряю объем работы количеством команд, которые мне пришлось ввести с терминала, количеством строк кода на языке Ruby, HTML и встроенного Ruby (ERb), которое мне пришлось написать. Я немного сократил работу, скопировав файл CCS (Cascading Style Sheets, каскадная таблица стилей) из загружаемых файлов к книге Томаса и Ханссона, поэтому в своей оценке трудовых затрат эти строки я не учитываю. В таблице 1 представлены результаты моих подсчетов.

Таблица 1. Трудовые затраты на управление каталогом продукции

Цифры в таблице 1 были округлены, поскольку я немного экспериментировал с кодом. Но если бы я даже написал в два раза больше строк кода на языке Ruby, общее количество строк, введенных мной в редакторе или строк команд в оболочке терминала было бы гораздо меньше 100. Вы можете спросить, а что я на самом деле получил, написав несколько десятков строк программного кода? Вот список:

Кроме того, я обнаружил еще более восхитительные моменты, которыми мне не пришлось заниматься:

  • Я не написал ни одной строки кода SQL, тем не менее мое приложение оснащено реляционной базой данных;
  • Мне нужно было всего лишь написать метод проверки корректности, чтобы гарантировать корректное указание цены;
  • Мне не пришлось писать специальный код для обновления кода моего приложения при изменении схемы базы данных.

Я не являюсь разработчиком Web-приложений. (Я не слишком преуспел в изучении технологий, поскольку уделял больше внимания другим аспектам разработки программного обеспечения. В одно и то же время можно сделать лишь определенный объем вещей из всех доступных.) Но, имея явно недостаточные знания языков Ruby и HTML, я произвел хорошее впечатление на своих студентов, демонстрируя свои познания в области Web-разработки.

Принципы Rails

Каким образом Rails обеспечивает описанный объем функциональности при столь небольших требованиях к трудовым затратам разработчика? Один из принципов многократного использования заключается в том, что существует обратно пропорциональная зависимость между универсальностью приложения и многократностью его использования. Если вы хотите, чтобы ваш компонент или система лучше поддерживали многократное использование - то есть, имели бы больше элементов многократного использования - то вам придется сузить предметную область, в которой они применяются. Это первое, что мне пришло в голову при работе с Rails. Rails - это не обычная инфраструктура, которая позволяет вам создавать Web-приложения любым способом; скорее, он предназначен для поддержки конкретного принципа разработки Web-приложений. Если вы будете выполнять рекомендации, то сможете добиться потрясающей многократности использования. Но если вы отойдете от заданного направления, то многократность использования заметно понизится.

Model-View-Controller (Модель-представление-контроллер)

Разработчикам программного обеспечения хорошо известна архитектура Model-View-Controller (Модель-представление-контроль). Эта архитектура лежала в основе ранних систем графического интерфейса пользователя (GUI) типа интерфейса среды Smalltalk-80. Концепция не отличается сложностью: система делится на три разных части (см. рисунок 2).

Рисунок 2. Архитектура Model-View-Controller

Архитектура MVC делит сферы ответственности в приложении на три разных части. Модель отвечает за обслуживание состояния приложения. Оно не только извлекает и хранит данные, но также гарантирует их целостность. Бизнес-логика, которая должна применяться к этим данным, инкапсулирована в модель. Представление отвечает за отображение модели для пользователя в одном или нескольких форматах. Это позволяет отображать модель различными способами, в зависимости от потребностей пользователя. Контроллер отвечает за обеспечение того, чтобы другие компоненты осуществляли нужные действия в нужное время. Он получает запросы от пользователя и распределяет их по соответствующим компонентам. MVC - надежная, эффективная архитектура для многих типов приложений, в том числе, для клиент-серверных Web-приложений.

Соблюдая соглашения Rails, вы получите превосходное разделение вопросов по этим трем компонентам. На рисунке 3 показан фрагмент макета моего простого приложения. Мы видим, что это приложение имеет отдельные каталоги для всех компонентов, и еще один для всех вспомогательных объектов, необходимых для их поддержки.

Рисунок 3. Фрагмент структуры приложения

На данный момент разработки у нас всего один контроллер, контроллер admin. Rails получает информацию о том, какой контроллер необходимо вызвать, из текущего URL в адресной строке браузера. В данном случае, это указывается в URL после адреса Web-cервера. Тестируя приложение, я указываю в адресной строке браузера URL http://localhost:3000/admin , после чего localhost:3000 подключается к используемому мной серверу -- в данном случае, к серверу по умолчанию WEBrick, который поставляется с Rails. Контроллер приложений Rails направляет запрос классу AdminController. Если вам интересно содержимое этого класса, можете изучить файл в архиве, прилагаемом к данной статье. Вы сможете сопоставить большую часть методов этого класса со ссылками на Web-странице, показанной на рисунке 1. Большая часть реальной работы сделана классом ApplicationController, который расширяет класс AdminController. Не беспокойтесь, если вы не понимаете всех деталей. Файл, содержащий определение класса AdminController, admin_controller.rb - это один из самых больших файлов в приложении, и я не написал ни одной строки в этом файле. Он был полностью сгенерирован Rails по одной моей команде.

Представлением Web-приложения являются Web-страницы, которые отображаются перед пользователем. Rails генерирует для вас большую часть Web-страниц, но вы все же должны иметь базовые знания HTML и обладать достаточными навыками программирования на языке Ruby, чтобы написать несколько строк ERb. В представлении в Rails нет ничего уникального. Просто для каждого действия мы должны создать файл.rhtml (Ruby HTML).

К этому моменту модель моего приложения достаточно проста, в базе данных имеется только одна таблица для продуктов, а продукт имеет четыре свойства, о которых я уже говорил ранее. Я решил сделать URL изображения необязательным свойством, поэтому для него не предусмотрена проверка корректности. Для всех остальных полей производится проверка корректности. Ниже представлен полный текст файла product.rb. Правда, он не слишком велик?

class Product < ActiveRecord::Base validates_presence_of:title, :description validates_numericality_of:price validates_uniqueness_of:title, :message => "We already have that in our catalog" protected def validate errors.add(:price, "must be worth something") if price.nil? || price < 0.01 end end

Первые три метода validates_ methods являются встроенными методами Rails, при этом метод проверки корректности автоматически вызывается для любого продукта, поступающего в систему. Я добавил проверку, чтобы гарантировать, что цена любого продукта будет не менее 0,01 доллара.

Возможно, вы поинтересуетесь, как была создана таблица для записи продуктов, если я не написал ни строки SQL? В Rails есть достаточно волшебный компонент, который называется Active Record. Active Record представляет собой объектно-реляционное отображение (object-relational mapping, ORM), использующее стандартную ORM-модель. В своей основе он представляет собой абстрактную реализацию шаблона проекта ActiveRecord. То есть, таблицы отображаются в классы, объекты отображаются в строки, а свойства объектов отображаются в столбцы. Active Record, как и Rails в целом, использует стандартный способ управления отображением. Он не поддерживает полной универсальности без определенной дополнительной работы. Однако если вы намерены использовать его стандартные возможности по умолчанию, то вам придется сделать совсем немного. Следующий код представляет содержимое файла, который создает таблицу:

class CreateProducts < ActiveRecord::Migration def self.up create_table:products do |t| t.column:title, :string t.column:description, :text t.column:image_url, :string end end def self.down drop_table:products end end

Все, что я написал в этом коде - это три строки t.column.... . Они определяют свойства наименование, описание и URL изображения. Чтобы получить готовую и настроенную базу данных, я выполнил следующие действия:

  1. В командной строке я ввел команду:

    Mysqladmin -u root create depot_development

    В результате этой команды была создана база данных для моей разработки;

  2. Я перешел в корневой каталог приложения и ввел следующую команду:

    Ruby script/generate model product

    В базе данных была создана таблица PRODUCT. Кроме того, было создано несколько файлов, в том числе, файл 001_create_products.rb в каталоге db/migrate приложения. Именно этот файл был показан в предыдущем листинге;

  3. Я отредактировал файл, добавив в него три определения для столбцов;
  4. Я ввел команду:

    Rake db:migrate

    В таблице PRODUCT были созданы столбцы. Команда rake - это аналог команды make, который используется в Rails.

При каждом обновлении схемы базы данных приходится генерировать файл миграции примерно таким же образом, как в предыдущей последовательности. Каждый файл миграции начинается с порядкового номера, который на единицу больше, чем в предыдущем файле миграции, и этот номер соответствует версии схемы, которая хранится в особой таблице базы данных. Теперь вы можете пополнять базу данных и производить откат изменений с минимальными усилиями. Rails все сделает за вас.

На этом мы закончим изучение архитектуры MVC, основы приложения Rails, и перейдем к другим принципам.

Соглашение по поводу конфигурации

Я уже продемонстрировал этот принцип в действии. Приложение Rails довольно жестко соблюдает некоторые соглашения. Одни соглашения представляют собой обычные соглашения о назначении имен, а другие больше относятся к архитектуре приложения. Rails имеет весьма четкий взгляд на построение Web-приложения, он использует умолчания, основанные на этой модели. Допущение умолчаний позволяет сгенерировать гораздо большую часть приложения, чем это было бы возможно для инфраструктуры в противном случае. Это также избавляет разработчика от необходимости длительной настройки конфигурации сред для разработки, тестирования и развертывания. Существует два конфигурационных файла, которые можно изменять, если нужно добавить MIME-типы или другую информацию, которая не вписывается в обычные сценарии применения. Один из файлов, который, вероятно, придется редактировать, это файл database.yml, описывающий основные параметры для сред разработки, тестирования и развертывания. Когда я создавал приложение, этот файл был сгенерирован со значениями по умолчанию, как показано в следующем листинге.

# MySQL (установки по умолчанию). Рекомендуется использовать версии 4.1 и 5.0. # # Установка драйвера MySQL: # gem install mysql # На MacOS X: # gem install mysql -- --include=/usr/local/lib # На Windows: # gem install mysql # Выберите сборку win32. # Установите MySQL и поместите сборку в каталог /bin, указанный в переменной path. # # Убедитесь, что вы мспользуете новый стиль хэширования пароля: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html development: adapter: mysql database: depot_development username: root password: host: localhost # Внимание: База данных, определенная как "test", будет стерта и #сгенерированна повторно из вашей разработанной базы данных, когда вы запустите "rake". # Не присваивайте этой БД того же имени, которое было при разработке # или при реальной эксплуатации. test: adapter: mysql database: depot_test username: root password: host: localhost production: adapter: mysql database: depot_production username: root password: host: localhost

Обратите внимание, что этот код использует три разных базы данных для каждой среды. Комментарий над каждой конфигурацией среды тестирования рассказывает о какой-либо дополнительной функции разработки приложений при помощи Rails. Тестирование - это привилегированная фаза в процессе разработки Rails. Когда вы расширяете и изменяете приложение в соответствии с соглашениями, Rails помогает вам, генерируя автоматизированные тесты, которые выполняются без помощи утилиты rake. Тесты автоматически выполняются в отдельной среде, интерфейс которой не пересекается ни со средой разработки, ни с рабочей средой.

Принцип DRY

Последний принцип, который используется в приложениях Rails - это принцип DRY (Don"t Repeat Yourself, не повторяйся). Хорошие проектировщики и программисты используют этот принцип на практике. Они знают, что если что-то делается один раз, в одном месте, то проекты становятся более простыми, а работа гораздо более управляемой.

Способ организации и генерации приложений в Rails с соблюдением принципа DRY не представляет сложности, если соблюдать соглашения. Если вы научитесь ориентироваться в базовом коде для одного из приложений Rails, то можно считать, что вы сумеете разобраться в любом приложении Rails, в котором соблюдаются соглашения. Ничто не повторяется. Все находится в одном месте и все имеет смысл.

Но будет ли приложение масштабируемым?

Когда я встречал что-либо, кажущееся столь же простым, как Rails, я удивлялся, если оно могло работать в реальной сильно загруженной рабочей среде. Я видел слишком много инструментов, которые обещали значительный прирост производительности. Они хорошо показывали себя на "игрушечных" проектах, но терпели полный крах при первых же попытках применить их для решения реальных проблем. Я знаю довольно много историй успеха, связанных с Rails, но настоящая уверенность пришла ко мне в прошлом году, когда мы успешно применили Rails в нашем институте.

Один из моих коллег по Вустерскому политехническому институту (Worcester Polytechnic Institute) занимался разработкой интеллектуальной обучающей системы под названием Assistments, которая должна была помочь преподавателям и студентам различных курсов в изучении и преподавании различных предметов. Так же, как во многих штатах, учащиеся начальной и средней школы нашего штата в процессе обучения должны сдать серию стандартизированных тестов, что, в конечном итоге, необходимо для получения документа об образовании. Эти тесты, так называемые тесты MCAS , предлагаются на каждой ступени обучения, чтобы можно было оценить уровень подготовки учащихся по основным учебным дисциплинам. Обучающая система Assistments показала свою эффективность в помощи учащимся в получении необходимых знаний и навыков. В прошлом году система Assistment использовалась небольшой группой студентов в Вустере, штат Массачусетс, но группе моего коллеги, которая занималась Assistments, скоро пришлось готовиться к более масштабному развертыванию.

Assistments представляет собой типичное клиент-серверное Web-приложение. Оно не только помогает учителям и студентам себя использовать, но также поддерживает исследователей в разработке новых обучающих методик и предоставлении функций оценки. В прошлом году система Assistments насчитывала больше 50 000 строк программного кода, главным образом, на языке Java. Код включал множество пакетов и классов, которые были разработаны за несколько лет аспирантами и студентами. К сожалению, группе разработчиков не доставало последовательности, поэтому код превратился в крайне неуправляемый - то есть, с каждым днем становился все более хрупким. Что могла предпринять группа для обеспечения качества, необходимого для крупномасштабного развертывания?

У нас было три возможных варианта. Во-первых, можно было продолжать попытки управления и расширения существующей системы. Это вряд ли могло долго продолжаться. Во-вторых, мы могли бы заново написать систему с нуля или попытаться развить существующую архитектуру в нужную нам систему. Это было бы связано с программированием на Java. Сначала группа склонялась к выбору именно этого варианта.

Третий вариант мы получили благодаря одному из аспирантов, принимавших участие в работе над Assistments - он предложил переписать систему при помощи Rails. Можно себе представить, какое раздражение вызвало это предложение у его товарищей и профессора, курировавшего группу. Студент потратил несколько недель на разработку главного приложения, которое содержало большую часть функций системы Assistments. Для этого ему пришлось написать тысячу строк программного кода.

Ему удалось убедить всех. Группа утвердила процесс разработки и приступила к работе. Новая система имеет все функции старой системы и несколько новых, в том числе, улучшенный пользовательский интерфейс. Согласно последней полученной мной информации, группе пришлось написать и обслужить меньше 5 000 строк кода. Это означает более чем 10-кратное повышение производительности, при этом количество дефектов, обнаруженных в системе, меньше, чем средний показатель.

Да, Rails - это не игрушка.

Вместо заключения

Идея автоматической генерации программ не нова. Однако в последние годы мы значительно усовершенствовали эту технологию. Rails - это одна из очень эффективных инфраструктур для создания определенного вида программ понятным, непротиворечивым способом с минимальными трудовыми затратами. Можно ожидать появления систем, подобных Rails, для других предметных областей. Это совсем неплохо в экономическом смысле. Фактически, в сфере создания Web-приложений существует еще два явления. Это две похожих на Rails инфраструктуры, написанные на языке PHP. Они называются Symfony и CakePHP. Недавно появилось еще одно интересное явление в этой области, это Project Zero, инкубаторный проект IBM. Project Zero не является генератором приложений, но он предоставляет соглашения и структуру, напоминающую Rails

Если вы еще не сделали решительный шаг в направлении разработки Web-приложений, надеюсь, эта статья даст вам пищу для размышлений и подвигнет на то, чтобы потратить немного времени, получить некоторое удовольствие и начать использовать Rails.

Примечания

1 На этом пути вам могут помочь многочисленные учебные руководства. Некоторые из них перечислены в разделе Ресурсы в конце этой статьи. Изучите учебное руководство, и вы удивитесь, насколько просто можно создать Web-приложение.

2 Первая бета-версия Rails была выпущена в июле 2004 года. Rails 1.0 увидела свет в декабре 2005 года. В примерах, приведенных в данной статье, используется версия 1.2.2.

10 Massachusetts Comprehensive Assessment System (Комплексная обучающая система Массачусетского университета) См.

Привет. Я использую Rails уже значительное время - 5 лет (это, по-моему, значительное). В этой статье я попробую подытожить свой опыт и ответить на вопрос: почему я все еще использую Rails и почему его должны (или не должны) использовать вы.

Для начала ответим на вопрос из заголовка. Действительно ли Rails популярен сейчас, в середине 2015 года?

Вот эта забавная таблица сравнений по критериям популярности репозитория на GitHub и количества вопросов на StackOverflow (https://hotframeworks.com/) говорит что Rails всё ещё в топе:

class Customer < ActiveRecord :: Base has_many :orders end class Order < ActiveRecord :: Base belongs_to :customer end

И это все. Это работает без единой строчки конфигурации. По умолчанию предполагается, что в базе у вас есть таблицы orders и customers . В orders есть внешний ключ с именем customer_id . Первичные ключи называются id . На этом все. Вы соблюдаете соглашения именования и все само работает. Теперь вы можете строить и выполнять SQL-запросы совершенно очевидным и естественным способом:

customer . orders #=> order . customer #=> customer

Окей, идем дальше. Маршрутизация запросов (routes). Это поразительно. Вы можете все, и очень многое из этого “всего” бесплатно. Но это если вы руководствуетесь соглашениями. Пример маршрута из документаци

resources :books

Благодаря магии Rails эта одна скромная строчка способна создать пачку маршрутов для CRUD:

$ bundle exec rake routes | grep book books GET /books(.:format) books#index POST /books(.:format) books#create new_book GET /books/new(.:format) books#new edit_book GET /books/:id/edit(.:format) books#edit book GET /books/:id(.:format) books#show PATCH /books/:id(.:format) books#update PUT /books/:id(.:format) books#update DELETE /books/:id(.:format) books#destroy

Опять-таки, по соглашениям именования у вас должен быть класс BooksController и аналогичные методы index/create в нём, т.е. books#index соответствует BooksController#index . Добавьте к этому ограничения (constraints), пространства имен (namespaces), модули (modules).

HTML-формы. Что тут можно улучшить? Нtml есть html, от него никуда не убежишь, но можно попытаться уменьшить боль. Пример создания формы из документации :

<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %> <%= f.text_field:title %> <%= f.text_area:body, size: "60x12" %> <%= f.submit "Create" %> <% end %>

Предполагается что @article это ActiveRecord модель, но по факту здесь может быть любой произвольный объект. В том числе, если использовать шаблон FormObject, здесь может быть объект абсолютно отвязанный от слоя ORM.

Миграции базы данных. Здесь все стандартно. Можно, просто и быстро.

Аутентификация пользователя и сопутствующий функционал - регистрация, вход, выход, восстановление пароля. Чтобы это все заработало, вам нужно воспользоваться одной из нескольких доступных библиотек: Devise, Authlogic итд. Вам надо добавить всего несколько стандартных строк для подключения.

Развертывание (deploy) приложения на сервер. Есть стандартное решение - capistrano. Пример стандартного скрипта с комментариями: (ссылка на gist).

# config/deploy.rb # config valid only for current version of Capistrano lock "3.4.0" set :application , "aircat" set :repo_url , "[email protected]:applabsservice/aircat.git" set :deploy_to , "/var/www/apps/aircat" set :git_shallow_clone , 1 set :deploy_via , :copy set :branch , "master" set :host , "127.0.0.1" set :user , "deploy" role :app , %w{[email protected]} role :web , %w{[email protected]} role :db , %w{[email protected]} namespace :db do desc "Make symlinks" task :symlink do on roles (:app ) do execute "ln -nfs #{ shared_path } /config/database.yml #{ release_path } /config/database.yml" end end end after "deploy:updating" , "db:symlink" # дальше идут другие callback"и для перезапуска веб-сервера

Что это дает? При каждом развертывании новая версия приложения копируется в отдельный каталог релиза, рядом с предыдущими. Запускаются миграции, идет компиляция/склейка/минификация статичных css/js файлов, и когда всё готово, веб-сервер переключается на каталог с новым релизом. В случае ошибки на любом из шагов можно просто вернуться на предыдущий релиз. Новый код запускается уже на обновленной базе. Есть нюанс, что во время миграций некоторое время с обновленной базой работает старый код. Но это тоже решается.

class Post < ActiveRecord :: Base has_attached_file :image , styles : { standard : "1280x1280>" }, default_url : "/images/:style/missing.png" validates_attachment_content_type :image , content_type : /\Aimage\/.*\Z/ has_attached_file :video end

И это все. Можно автоматически сгенерировать миграцию, чтобы сохранять метаданные файла в базе и это уже работает:

post . image = File . read ("test.jpeg" ) post . save

Все, файл помещен в правильный каталог на диске. Если это картинка, её можно обрезать, cконвертировать, сжать. Сделать несколько вариантов разрешений парой магических строчек.

Локализация - да, есть как у всех, всё просто и стандартно.

Тестирование. В стандартной библиотеке Ruby есть фреймворк для unit-тестирования. В Rails из коробки есть поддержка функциональных и интеграционных тестов, но намного круче воспользоваться связкой RSpec для модульных тестов и Capybara + webdriver для интеграционных. Представьте - вы можете в интеграционных тестах запускать настоящий браузер, установленный в системе (например через Selenium Webdriver), или headless браузер на базе WebKit. Второй вариант пока что надежнее, стабильнее и быстрее.

Из минусов для разработки можно выделить следующее:

  • Rails даёт вам соглашения. Вы следуете им. Ваш код лаконичен, красив, покрыт тестами, всё сделано по Rails-way. Но есть и обратная сторона. Вы получаете большую связанность компонентов, толстые контролеры или толстые модели. Rails предлагает шаблон MVC, но ничего сверх этого. Нет никакого стандартного слоя абстракции - это решение ложится на ваши плечи. Если вы заметили, что стандартные компоненты (views, models, controllers) уже перенасыщены несвойственной им логикой, вы должны что-то делать. Какие у вас варианты? Можете начать рефакторить, выносить логику в отдельные слои - об этом уже немало написано. Можно использовать Form-объекты, выносить сложный SQL в независимые объекты, отделить бизнес-логику от ORM/контроллеров.
  • Документация для Rails и популярных библиотек отличная, но это всё равно не избавит вас от изучения их исходного кода, чтобы разобраться с упущенными в документации моментами. Иногда код скажет даже больше.
  • Скорость развития инструментов и библиотек имеет очевидную обратную сторону - вам периодически придётся обновляться до последних версий. Это относится и к версиям Rails, и к библиотекам. Переход на другую мажорную версию библиотеки для тестирования может занять не один и не два дня. Возможен вариант, когда появляется какой-то удачный аналог используемой вами библиотеки. Ваша библиотека постепенно перестает развиваться и поддерживаться, и внезапно вы обнаруживаете, что она не работает в очередной версии Rails и придётся переходить на аналоги. Ничто из этого не специфично только для Rails, но в долгоживущем проекте вы с этим столкнетесь с большой вероятностью.

Когда вам нужен Rails?

  • Вы разрабатываете обычное веб-приложение. Вы ожидаете, что проект будет жить долго. Вам нужно, чтобы инструмент продолжал развиваться и жить, нужна поддержка от сообщества или от какой-нибудь компании, возможность нанять специалиста. В таком случае, Rails - прекрасный выбор. Альтернатив хватает, выбирать есть из чего. Но вы все равно выберете Rails, ведь это по-прежнему модно;-)
  • Вы предполагаете постоянное изменение требований и функционала, вектора развития проекта. У вас нет постоянной концепции продукта, она меняется и зависит от обратной связи с пользователями. Rails в этом случае отличный выбор.
  • Вам нужно “быстрое прототипирование”. Rails до сих пор хорош для этого. Альтернативы, конечно же, найдутся, но Rails очень хорош и в этом.

Когда вам не нужен Rails?

  • Вы отчётливо понимаете требования к проекту и функционалу. Вы не ожидаете быстрых изменений функционала. К примеру, у вас уже есть прототип или вы уже делали что-то очень похожее и можете сразу отливать архитектуру в бронзе.
  • Вы ищете то, чего никогда не найдёте в динамически типизированном языке, - высокую (высочайшую) скорость работы и низкое потребление ресурсов сервера.
  • У вас уже есть команда профессионалов которые хотят использовать другой фреймворк.

Ну вот и всё. В заключение я добавлю, что получаю большое удовольствие, используя Rails и Ruby. Это очень удобные инструменты, мягкие и податливые, как пластилин. В умелых руках они помогают создавать волшебные вещи.

В то время, как это все еще нарушает принцип единственной обязанности, это своеобразный минимум, который фреймворк Rails требует от контроллера.

Ошибка 2. Слишком много логики в представлении

ERB, “коробочный” шаблонный движок Rails, открывающий потрясающие возможности по созданию страниц с различным контентом. Однако, если не быть осторожным, то можно в конечном счете получить большой файл, в котором будет перемешан HTML и Ruby-код, которым будет трудно управлять и который будет проблематично поддерживать. Также это может привести к большому количеству повторений, которые вызовут нарушение принципов DRY (don’t repeat yourself).

Это может проявиться множеством способов. Одним из них является чрезмерная условная логика в представлении. В качестве простого примера рассмотрим случай, когда у нас есть доступный метод current_user, который возвращает только что авторизованного в системе пользователя. Часто в логике представления будут появляться, например, такие логические структуры:


Welcome,
<% if current_user %>
<%= current_user.name %>
<% else %>
Guest
<% end %>

Лучший способ справиться с подобным: убедиться, что объект возвращаемый current_user всегда выбран, независимо от того, вошел ли кто-то в систему или нет, и что он отвечает методам, использованным в представлении разумным образом (иногда упоминается как null ). Например, вы можете определить хелпер current_user в app/controllers/application_controller таким образом:

require "ostruct"
helper_method:current_user

def current_user
@current_user ||= User.find session[:user_id] if session[:user_id]
if @current_user
@current_user
else
OpenStruct.new(name: "Guest")
end
end

Это позволило бы заменить предыдущий код представления всего одной строчкой:

Welcome, <%= current_user.name -%>

  • Используйте шаблоны представления и разделяемые методы для инкапсуляции вещей, которые повторяются на ваших страницах.
  • Используйте декораторы, такие, как Draper gem для инкапсуляции логики представления в Ruby-объект. Затем вы можете добавить методы в этот объект, чтобы представить логические операции, которые в противном случае были бы внутри кода представления.

Ошибка 3. Слишком много логики в модели

Ну, не совсем.

Многие Rails-разработчики на самом деле делают эту ошибку и в конечном счете их классы моделей в ActiveRecord, ведущие к файлам Mongo, — не только нарушают принцип единственной обязанности, но и являются кошмаром для техподдержки.

Такая функциональность, как генерация email-оповещений, обращение ко внешним сервисам, конвертирование данных в другие форматы и тому подобное не стоит делать с помощью ActiveRecord-моделей, назначение которых — делать чуть больше, чем поиск и хранение данных в базе.

Но если такая логика не должна храниться в представлении, в контроллере и модели — то где же тогда?

Давайте поговорим о “простых старых Ruby-объектах” (POROs). С таким всеобъемлющим фреймворком, как у Rails, неопытные разработчики часто не хотят создавать свои собственные классы вне фреймворка. Однако, часто вынесение логики модели внутрь POROs — это то, что доктор прописал во избежание усложнения моделей. С POROs вы можете инкапсулировать такие вещи, как email-уведомления или взаимодействия с API в их собственные классы, а не хранить их внутри ActiveRecord-модели.

Итак, исходя из сказанного, единственная логика, которая может остаться в вашей модели, это:

  • Конфигурация ActiveRecord (например, взаимосвязи и валидация).
  • Простые методы мутации для инкапсуляции обновления части параметров и сохранения их в базе.
  • Врапперы доступа, которые скрывают внутреннюю информацию модели (метод full_name, который сочетает поля first_name и last_name в базе данных).
  • Сложные запросы (более сложные, чем find). Вообще говоря, вы не должны использовать этот метод или любой другой метод построения очереди за пределами класса модели как такового.

Ошибка 4. Свалка из общих вспомогательных классов

Эта ошибка — своего рода следствие ошибки 3. Как уже говорилось, структура Rails делает акцент на названных компонентах (таких, как модель, представление и контроллер) в качестве основы MVC. Есть неплохие определения видов сущностей, которые принадлежат классам каждого из этих компонентов, но иногда нам бывают нужны методы, которые не подходят ни одному из трех.

Генераторы в Rail создают директорию хелпера и новые класс хелпера. Становится слишком заманчивым начать создавать функциональность, которая вовсе не понадобится ни модели, ни представлению, ни контроллеру.

Хотя Rails, конечно, и является MVC-центрированным фреймворком, ничто не мешает вам создать свои собственные типы классов и добавить подходящие каталоги для кода этих классов. Если у вас предусмотрена дополнительная функциональность, подумайте, какие методы группируются и найдите хорошие названия для классов, которые содержат эти методы. Используя Rails не повод, чтобы позволить лучшим практикам объектно-ориентированного проектирования отойти на второй план.

Ошибка 5. Использование слишком большого количества гемов

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

Это приводит к нескольким проблемам Rails. Злоупотребление гемами делает размер Rails-процессов больше, чем нужно. Это может замедлить производительность на продакшне. В дополнение к разочарованию пользователя это может привести к необходимости большего объема памяти сервера, что увеличит операционные расходы. Также больше времени занимает запуск такого приложения, что замедляет процесс разработки и делает автоматическое тестирование медленным (и как правило, такие тесты запускаются нечасто).

Имейте в виду, что каждый гем, который вы подключаете к приложению, в свою очередь зависит от других гемов, а они от других и так далее. Добавление гемов может иметь совместный эффект. Например, добавление гема rails_admin добавит еще более 11 гемов, что на 10% больше, чем базовая конфигурация Rails.

На момент написания статьи дистрибутив свежего Rails 4.1.0 включал 43 гема в файле Gemfile.lock. Это явно больше, чем входит в Gemfile и представляет все гемы, которые набор стандартных гемов Rails добавляет в качестве зависимостей.

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

Ошибка 6. Игнорирование лог-файлов

В то время, как большинство Rails-разработчиков знают о доступности дефолтных лог-файлов во время разработки, они не уделяют много внимания информации в этих файлах. Хотя многие приложения полагаются на инструмента мониторинга логов, такие, как Honeybadger или New Relic на продакшне, также важно следить за своими логами во время процесса разработки и тестирования приложения.

Как уже упоминалось в этом уроке, структура Rails делает много “магии”, особенно внутри моделей. Использование ассоциаций позволяет очень просто построить взаимосвязями между таблицами и вывести все во вьюхах. Весь SQL-код генерируется автоматически. Но как вы узнаете, что сгенерированный SQL эффективен?

Одним из примеров, с которым вы часто будете работать, называется проблема запроса N+1. В то время, как проблема зафиксирована, единственный способ выяснить причину ее возникновения - посмотреть SQL-запросы в ваших логах.

Скажем, у вас есть следующий запрос в типичном приложении блога, где вы отображаете все комментарии для выбранного набора постов:


posts = Post.limit(3)
posts.flat_map do |post|
post.comments.to_a
end
end

Когда мы смотрим в лог-файл, ища запрос, который вызвал этот метод, мы видим что-то вроде того: один запрос вызвал три поста, после чего еще три запроса вызвали комментарии к каждому:

Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:13 -0700

Post Load (0.4ms) SELECT "posts".* FROM "posts" LIMIT 3
Comment Load (5.6ms) ELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?
Comment Load (0.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?
Comment Load (1.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = ?
Rendered posts/some_comments.html.erb within layouts/application (12.5ms)
Completed 200 OK in 581ms (Views: 225.8ms | ActiveRecord: 10.0ms)

Active Record в Rails позволяет существенно сократить число запросов, позволяя заранее уточнить все связи, которые будут загружены. Это делается путем вызова метода includes (или preload) метода в объекте Arel (ActiveRecord::Relation). C includes — ActiveRecord гарантирует, что все указанные связи будут загружены с минимальным количеством запросов, например:

def comments_for_top_three_posts
posts = Post.includes(:comments).limit(3)
posts.flat_map do |post|
post.comments.to_a
end
end

Когда выше приведенный код выполняется, мы видим в логах, что все комментарии были собраны единственным запросом вместо трех:

Started GET "/posts/some_comments" for 127.0.0.1 at 2014-05-20 20:05:18 -0700
Processing by PostsController#some_comments as HTML
Post Load (0.5ms) SELECT "posts".* FROM "posts" LIMIT 3
Comment Load (4.4ms) SELECT "comments".* FROM "comments" WHERE"comments "."post_id" IN (1, 2, 3)
Rendered posts/some_comments.html.erb within layouts/application (12.2ms)
Completed 200 OK in 560ms (Views: 219.3ms | ActiveRecord: 5.0ms)

Намного эффективней.

Решение проблемы N+1, которая в действительности может быть только примером того множества неэффективностей, которые живут “под капотом” вашего приложения, если вы не уделяете этому много внимания. Вывод из этого пункта состоит в том, что вам нужно проверять девелоперский и тестерский лог во время разработки — чтобы проверить (и устранить) неэффективности в коде, который занимается построением запросов.

Обзор логов — хороший способ локализовать неэффективный код и исправить его, прежде чем приложение уйдет в продакшн. В противном случае, вы не сможете быть уверенным в производительности вашей системы до тех пор, пока она не начнет “жить” — вероятно, та база данных, с которой вы работали в процессе разработки и тестирования, окажется куда меньше той, что будет на продакшне. Если вы делаете новое приложение, даже если ваша БД на продакшне изначально небольшая и все поначалу работает нормально, потом она вырастет и проблемы, описанные в этом примере будут делать работу системы все медленнее и медленнее.
Если вы обнаружите, что ваши логи забиты кучей ненужной вам информации, вы можете очистить их.

Ошибка 7. Отсутствие автоматических тестов

Ruby on Rails по умолчанию дает широкие возможности для автоматического тестирования. Многие Rails-разработчики пишут очень сложные тесты с использованием TDD и BDD-стилей, а также используют еще более мощные тест-фреймворки, поставляемые в гемах (rspec и cucumber).

Несмотря на то, как легко добавить автоматические тесты в ваше приложение, я был весьма удивлен, когда мне случалось присоединяться к проектам, где буквально не было ни одного написанного теста (или в лучшем случае, очень мало). В то время, как можно спорить насчет того, какими всеохватывающими тесты должны быть, совершенно ясно, что по крайней мере некоторые автоматические тесты должны присутствовать в каждом приложении.

Общее правило: должен быть как минимум один высокоуровневый интеграционный текст для каждого действия ваших контроллеров. В какой-то момент будущего другие разработчики захотят расширить или модифицировать код, или проапгредить версию Ruby on Rails, а тест-фреймворк позволит им убедиться, что базовая функциональность приложения работает. Дополнительным преимуществом будет то, что это дает будущим разработчикам четкое понимание полного набора функционала приложения.

Ошибка 8. Блокирование обращений ко внешним сервисам

Сторонние сервисы в Rails-сервисах как правило очень легко интегрируется в приложение с помощью гемов, которые содержат их API. Но что произойдет, если ваш внешний сервис начнет сбоить или работать очень медленно?

Чтобы избежать блокировки таких запросов вместо прямого обращения к ним внутри вашего приложения, вам нужно перевести их в фоновый режим, если это возможно. Некоторые популярные гемы:

В случаях, когда невозможно или неосуществимо перевести обработку в фоновый режим, вы должны убедиться, что ваше приложение достаточно хорошо обрабатывает ошибки и сбои — если внешний сервис “лежит” или испытывает проблемы. Вам также нужно протестировать ваше приложение без внешних сервисов (возможно, путем удаления сервера, на котором работает ваше приложение, из сети), чтобы убедиться, что это не приводит к непредвиденным последствиям.

Ошибка 9. Getting married to existing database migrations

Механизм миграции базы данных в Rails позволяет создавать команды, которые автоматически добавляют или удаляют таблицы и строки. Так как файлы, который содержат миграции, названы по порядку, вы можете проиграть их с самого начала, чтобы привести пустую БД к тому же виду, что БД на продакшне. Таким образом, это отличный способ управлять гранулированными изменениями в схеме БД вашего приложения, чтобы избежать проблем с Rails.

Хотя это хорошо работает в начале вашего проекта, время идет, процесс создания БД может занять некоторое время, и иногда миграции теряются, вставляются не в том порядке, или берутся из других Rails-приложений, использующих тот же сервер.

Rails создает представление вашей текущей схемы в файле db/schema.rb (по умолчанию), который обычно обновляется, когда запускается миграция. Файл schema.rb даже может быть сгенерирован, когда нет текущих миграций, через выполнение команды rake db:schema:dump. Частая ошибка — проверить новую миграцию в вашем исходном репозитории, но не обновить файл schema.rb.

Когда миграции выполняются слишком долго, разработчики не должны бояться очистить старую директорию миграции, сделать дамп новой схемы и продолжить с ней. Настройка новой среды разработки потребовала бы выполнения rake db:schema:load, а не rake db:migrate, на которую полагается большинство разработчиков.

Некоторые из этих вопросов также рассматриваются в руководстве по Rails.

Ошибка 10. Проверка конфиденциальной информации в репозитории исходного кода

Фреймворк Rails позволяет легко создавать безопасные приложения, защищающие от многих видов атак. Кое-что достигается с помощью секретного токена, который позволяет получить доступ к сессии браузера. Даже если этот токен хранится в config/secrets.yml , и этот файл считывает токен из окружения, отличного от продакшн-серверов — в последние версии Rails токен включен в config/initializers/secret_token.rb . Этот файл часто по ошибке включают в репозиторий вместе с остальной частью вашего приложения. Если это произойдет, тот, кто получит доступ в репозиторий, получит доступ к пользователям вашего приложения.

Таким образом, вы должны убедиться, что ваш файл конфигурации репозитория (например, .gitignore для пользователей git) исключает файл с токеном. Тогда ваши продуктовые сервера смогут забрать свой токен из окружения, отличного от них, или из механизма, как тот, что поставляет dotenv gem .

Итого

Rails — мощный фреймворк, который скрывает много нелицеприятных деталей, необходимых для построения надежного приложения. И хотя Rails-приложения намного быстрее, разработчики должны обратить внимание на потенциальные ошибки в коде и проектировании, чтобы убедиться, что их приложение легко расширяемое и его легко поддерживать.

Разработчики также должны быть в курсе проблем, которые могут сделать их приложения медленными, менее надежными или менее безопасными. Важно изучить основы фреймворка и убедиться, что вы полностью понимаете архитектуру, дизайн, код — на протяжении всего процесса разработки. Это позволит сделать качественное приложение с высокой производительностью.