Что такое Ruby on Rails 1.0?

Перевод Дмитрия Сабанина. Оригинал What is Ruby on Rails by Curt Hibbs.

В этой статье:

  1. Высокая продуктивность и высокая скорость разработки
  2. Как Rails это делает?
  3. Компоненты Rails
  4. Основные возможности
  5. Active Record
  6. Action Pack
  7. Action Mailer
  8. Action Web Service
  9. Размышления о разделении
<!-- Introduction -->

Прошло около года с момента публичного дебюта 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.

<!-- End of introduction --> <!-- High productivity and reduced development time -->

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

На уровне возможностей, 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.

<!-- How rails does it? -->

Как 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

Rails это MVC (модель, вид, представление) фреймворк, она предоставляет компоненты для каждого уровня которые безупречно работают друг с другом. Другие фреймворки часто реализуют только часть решения, обязывая разработчика интегрировать несколько различных фреймворк в приложение, а затем заставить их работать вместе. (К примеру, Java разработчик может использовать Hibernate, Struts и Tiles для полной поддержки MVC.)

Rails is an MVC (model, view, controller) framework where Rails provides all the layers and they work together seamlessly. Other frameworks often implement only part of the solution, requiring the developer to integrate multiple frameworks into the application and then coerce them into working together. (For example, a Java developer might use Hibernate, Struts, and Tiles to get full MVC support.)

Соглашение вместо конфигурации

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

Convention over configuration means an end to verbose XML configuration files--in Rails, there aren't any! Instead of XML sit-ups, a Rails application uses a few simple programming conventions that allow it to figure everything out through reflection and discovery. For example, Rails uses intelligent reflection to automatically map database tables to Ruby objects. Your application code and your running database already contain everything Rails needs to know.

Меньше кода

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

Following the simple Rails programming conventions does more than just eliminate the need for configuration files. It also means that Rails can automatically handle myriad lower-level details without you having to tell it to do so. This means that you write fewer lines of code to implement your application. Keeping your code small means faster development and fewer bugs, which makes your code easier to understand, maintain, and enhance.

Генераторы

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

Rails' use of runtime reflection and metaprogramming eliminates much of the boilerplate code that you would otherwise have to create. You can often avoid what little boilerplate code remains by using the built-in generator scripts to create it for you. This leaves you with more time to concentrate on the code that really matters--your business logic.

Быстрая отдача

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

The typical development cycle for testing a change to a web app has steps such as configure, compile, deploy, reset, and test. This is very time consuming. The Rails development environment has none of this. You simply make a change and see it work. Don't make the mistake of dismissing this as a minor point. It's hard to overstate how much this improves productivity and helps you maintain a creative flow without interruption.

Скаффолдинг (Scaffolding — строительные леса, подмости. Прим. пер.)

Rails может автоматически создать полный набор CRUD (Create, Retrieve, Update, and Delete) операций и представления для любой таблицы базы данных. Эта функциональность называется скаффолдингом и помогает вам быстрее начать манипулировать своими таблицами. Со временем, вы можете постепенно заменить сгенерированные операции и представление своими собственными — которые, разумеется, будут намного красивее и функциональнее.

Rails can automatically create a full set of CRUD (Create, Retrieve, Update, and Delete) operations and views on any database table. This scaffolding can get you up and running quickly with manipulating your database tables. Over time, you can incrementally replace the generated CRUD operations and views with your own--presumably much prettier and more functional.

<!-- End of how rails does it --> <!-- Rails components -->

Компоненты Rails

Rails сама по себе состоит из нескольких компонентов, которые вы можете установить и использовать отдельно. Хотя они были спроектированы так, чтобы работать как единое целое, и разработчики почти всегда используют их вместе:

Rails itself consists of several components, which you can install and use separately. They are designed to work together seamlessly, though, and developers almost always use them together:

  • Active Record это слой объектно-реляционного отображения (ORM) который связывает бизнес объекты (модели) с таблицами базы данных. Это реализация паттерна активная запись описанного Мартином Фаулером.
  • Action Pack это компонент который реализует два слоя архитектуры MVC: контроллер и представление. Контроллер управляет входящими запросами от браузера пользователя и отправляет их к соответствующему методу класса-контроллера. Представление строит ответ браузеру используя шаблонную систему на подобии ASP или JSP.
  • Prototype это компонент который реализует Ajax, drag'n'drop и визуальные эффекты на ваших страницах.
  • Action Mailer это тот компонент который отвечает за отправку и получение электронной почты.
  • Action Web Service позволит вам легко добавить API веб службы к своему приложению. Action Web Service поддерживает SOAP, XML-RPC и WSDL.
  • Active Record is the object-relational mapping (ORM) layer that connects business objects (models) to database tables. It is an implementation of the Active Record pattern described by Martin Fowler.
  • Action Pack is the component that implements both the view and controller portions of the MVC architecture. The controller part handles incoming requests from the user's browser and routes them to the correct method of a controller class. The view part builds the response to send back to the browser using a templating system similar to that of ASP or JSP.
  • Prototype is the component that implements the Ajax, drag-and-drop, and visual effects within your web pages.
  • Action Mailer is the component that handles the sending and receiving of email.
  • Action Web Service is the component that makes it easy to add web service APIs to your web application. Action Web Service supports SOAP, XML-RPC, and WSDL.
<!-- End of rails components --> <!-- General features -->

Основные возможности

У Rails есть некоторые основные и специфичные характеристики.

Rails has some general and some specific characteristics.

Веб серверы

Rails можно запустить практически на любом веб сервере который поддерживает CGI. Однако, производительность CGI никуда не годится, поэтому предпочитаемый способ развёртывания это использование FastCGI. Довольно хорошо протестирован способ развёртывания Rails приложений на Apache и LightTPD. Кстати, недавно появился новичок, SCGI, который предоставляет производительность FastCGI без сложностей его установки.

Rails can run on just about any web server that implements CGI. However, the performance of CGI is notoriously bad, so the preferred deployment of a Rails application is to use FastCGI. There have been extensive tests of Rails application deployments with both Apache and LightTPD. There is also a newcomer, SCGI, which rivals the performance of FastCGI without the complicated setup.

Во время разработки, чаще всего самым простым способом является использование WEBrick — веб сервера который поставляется вместе с Ruby.

During development, it is usually easiest just to use the WEBrick web server that comes built-in to Ruby.

Базы данных

На данный момент Rails поддерживает следующие СУБД:

Rails currently contains support for the following databases:

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server
  • DB2
  • Oracle

Сам адаптер базы данных состоит из примерно 100 строк Ruby кода, поэтому расширить этот лист ещё одним элементом не составит большого труда.

It takes approximately 100 lines of Ruby code to implement a database adapter, so adding to this list is not particularly onerous.

Отладка

Когда что-нибудь в вашем Rails приложении идёт не так как надо, обычно вы получите довольно детальное сообщение об ошибки в вашем браузере (если вы работаете в режиме разработки). Часто, этого достаточно чтобы обнаружить проблему. Если нет, то у вас есть следующие варианты отладки:

When something goes wrong inside your Rails web app, you normally get a pretty detailed error display in your browser (when running in development mode). Often this is enough to diagnose the problem. When it's not, you have other options:

  • Вставить отладочный вывод в контроллер. Например:
    render_text "Дошёл до сюда"
    or
    render_text "объект user = " + user_obj
  • Проверить логи Rails. (Используйте tail на *nix системах.) Посмотрите на файлы development.log, production.log и fastcgi.crash.log. Помните, что ваш веб сервер тоже ведёт логи.
  • Использовать брейкпоинты.
  • Использовать коммерческую среду разработки (такую как ArachnoRuby) со встроенным отладчиком.
  • Insert debugging output in your controller. For example:
    render_text "Got here"
    or
    render_text "user object = " + user_obj
  • Check the Rails log files. (Use tail on *nix systems.) Look for the files development.log, production.log, and fastcgi.crash.log. Remember that your web server has log files, too.
  • Use breakpoints.
  • Use a commercial IDE (like ArachnoRuby) with a built-in debugger.

Настраиваемые (красивые) URL

То, как Rails по умолчанию привязывает URL к действиям контроллера очень просто понять. Rails очень старается чтобы пользователь видел только "красивые" URL адреса. URL в Rails простые и понятные, а не длинные и зашифрованные.

The default Rails mapping of URLs to controller actions is very simple and easy to understand. Rails tries very hard to present the user with pretty URLs. Rails URLs are simple and straightforward, not long and cryptic.

Несмотря на это, вы всё равно можете настроить адреса URL используя систему роутинга Rails. URL роутинг в Rails достаточно гибок для того, чтобы позволить вам создать практически любую схему привязки URL.

Even so, you can still customize your URLs by using the Rails routing facility. Rails' URL routing is flexible enough to allow you to create virtually any URL mapping scheme.

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

The Rails routing facility is pure Ruby code that even allows you to use regular expressions. Because Rails does not use the web server's URL mapping (like mod_rewrite in Apache), your custom URL mapping will work the same on every web server.

Модульное тестирование

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

Rails actively facilitates unit testing:

  • Генерация новых контроллеров, моделей и скаффолдига, также создаёт соответствующие скелеты модульных тестов.
  • Чёткое следование архитектуре MVC как результат приводит к хорошо тестируемым действиям и компонентам.
  • Rails включает в себя Rake (Ruby Make) скрипт, который может автоматически запускать все ваши модульные тесты.
  • Generating new controllers, models, and scaffolding also creates corresponding unit test skeletons.
  • The strict MVC architecture tends to naturally result in testable actions and components.
  • Rails includes a Rake (Ruby Make) script that will automatically run all your unit tests.

Детали процесса подробно описаны в Руководстве о тестировании в Rails.

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.

Документация класса ActiveRecord::Base описывает процесс автоматической привязки подробней.

The ActiveRecord::Base documentation explains more about Active Record's automatic mapping.

Ассоциации

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

No table stands alone. Well, not usually, anyway. Most database applications use multiple tables with specific relationships between those tables. You can tell Active Record about these relationships in your model classes, and Active Record will generate a slew of navigation methods that make it easy for your code to access related data. The following models:

class Firm < ActiveRecord::Base
  has_many   :clients
  has_one    :account
  belongs_to :conglomerate
end

позволяет вам написать следующий код:

allow you to write code such as this:

my_firm = Firm.find(:last)
STDOUT.print my_firm.account.name
STDOUT.print my_firm.conglomerate.employee_count
for c in my_firm.clients
  STDOUT.print "Клиент: " + c.name + "\n"
end

Этот код будет работать корректно если в базе данных есть таблицы clients и accounts в каждой из которых есть поле name, и таблица conglomerates с полем employee_count.

This code will work correctly when the database has a clients and accounts table, of which each has a name column, and a conglomerates table that has an employee_count column.

Документация модуля ActiveRecord::Associations подробно объясняет все тонкости ассоциаций в Rails.

The ActiveRecord::Associations documentation explains more about associations.

Валидация

Поскольку вы скорей всего не хотите хранить в своей базе что попало, вы скорей всего захотите проверить свои данные перед сохранением. Active Record содержит набор макро-подобных валидаторов которые вы можете добавить к своей модели.

Because you don't want to store just any old thing in your database, you probably want to validate your data before you store it. Active Record contains a suite of macrolike validators that you can add to your model.

class Account < ActiveRecord::Base
  validates_presence_of     :subdomain, :name, :email_address, :password
  validates_uniqueness_of   :subdomain
  validates_acceptance_of   :terms_of_service, :on => :create
  validates_confirmation_of :password, :email_address, :on => :create
end

Если встроенные макросы валидации не могут дать вам то, что нужно, вы всегдо можете написать свой метод для валидации.

If the built-in validation macros can't do what you need, you can always write your own validation methods.

class Person < ActiveRecord::Base
  protected
    def validate
      errors.add_on_empty %w( first_name last_name )
      errors.add("phone_number", "has invalid format") unless phone_number =~ /[0-9]*/
    end

    def validate_on_create # only runs the first time a new object is saved
      unless valid_discount?(membership_discount)
        errors.add("membership_discount", "has expired")
      end
    end

    def validate_on_update
      errors.add_to_base("Изменений не было") if unchanged_attributes?
    end
end

person = Person.new("first_name" => "David", "phone_number" => "what?")
person.save                         # => false (and doesn't do the save)
person.errors.empty?                # => false
person.count                        # => 2
person.errors.on "last_name"        # => "can't be empty"
person.errors.on "phone_number"     # => "has invalid format"
person.each_full { |msg| puts msg } # => "Last name can't be empty\n" +
                                            "Phone number has invalid format"
person.attributes = { "last_name" => "Heinemeier", "phone_number" => "555-555" }
person.save # => true (и person сохраняется в базе данных)

Если метод validate существует, Rails вызовет его прямо перед записью любого объекта в базу данных. Если валидация провалилась, она не запишет объект в базу. Методы validate_on_create и validate_on_update похожи, за исключением того, что первый вызывается только тогда когда Rails создаёт в базе новую запись, тогда как последний вызывается только когда Rails собирается обновить существующую.

If the validate method exists, Rails will call it just before writing any object to the database. If validation fails, it does not write the object to the database. validate_on_create and validate_on_update are similar, except that the first is called only before Rails creates a new record in the database, while the second is called only when Rails is about to update an existing record.

Документация модуля ActiveRecord::Validations подробно описывает все тонкости.

The ActiveRecord::Validations documentation explains more about validation.

Обратные вызовы

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

As Active Record creates and destroys model objects and creates and updates them in the database, you can monitor these events in the object's life cycle using callbacks. You can use callbacks to handle complex business logic, modify data before Rails writes it to the database (or after Rails reads it from the database), or just about anything else you like.

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

For example, the save method that saves a model object's data to the database has eight callbacks defined:

  1. before_validation
  2. before_validation_on_create
  3. after_validation
  4. after_validation_on_create
  5. before_save
  6. before_create
  7. after_create
  8. after_save

Это даёт вам полный контроль над объектами модели тогда, когда он вам нужен.

This gives you fine-grained control over your model objects when you need it.

class CreditCard < ActiveRecord::Base
  # Выдрать всё, кроме цифр, так чтобы пользователь мог ввести "555 234 34" или
  # "5552-3434". Чтобы оба варианта значили "55523434"
  def before_validation_on_create
    self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
  end
end

class Subscription < ActiveRecord::Base
  before_create :record_signup

  private
    def record_signup
      self.signed_up_on = Date.today
    end
end

class Firm < ActiveRecord::Base
  # Уничтожает ассоциированных клиентов и людей, когда уничтожается фирма
  before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
  before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }
end

Документация модуля ActiveRecord::Callbacks подробно рассказывает о методах обратного вызова.

The ActiveRecord::Callbacks documentation covers callbacks.

Транзакции

Транзакции необходимы если вы выполняете несколько операций над базой данных которые все должны пройти успешно перед тем как данные в базе изменятся. Если одна из них проваливается, данные не должны измениться. Используйте блоки транзакций чтобы включить этот режим.

A transaction is necessary when you have multiple database operations that all must succeed before the data in the database can change. If any one of them fails, the data in database should not change. Use transaction blocks to ensure this.

transaction do
  david.withdrawal(100)
  mary.deposit(100)
end

Транзакции уровня базы данных, показанные выше, не допустят снятие денег со счёта David'а в случае если не получится зачислить эти деньги на счёт Mary. Однако, это не защитит объекты david и mary от изменения. Чтобы добиться этого, вам следует использовать транзакции уровня объектов:

The database-level transaction shown above will prevent the withdrawal from David's account if the deposit into Mary's account should fail. It will not, however, protect the david and mary objects from being modified. To do that, you must use object-level transactions.

Account.transaction(david, mary) do
  david.withdrawal(100)
  mary.deposit(100)
end

Любой сбой в этом коде вернёт назад предыдущее состояние объектов, также как и базы данных.

Any failure in this code will roll back the value of the objects as well as the database.

Документация модуля ActiveRecords::Transactions объясняет подробнее.

The ActiveRecords::Transactions documentation explains more.

И это далеко не всё

Active Record содержит в себе намного больше, чем я могу здесь описать. Чтобы узнать больше, загляните в Active Record API.

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.

<html>
  <head>
    <title>Счета для <%= @name %></title>
  </head>
  <body>
    <% render_partial "invoices_by_customer" %>
  </body>
</html>

По умолчанию, 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("подчёркнутый")    # => <em>подчёркнутый</em>
xm.em { xmm.b("emp & bold") }    # => <em><b>emph & bold</b></em>
xm.a("A Link", "href"=>"http://onestepback.org")    # => <a href="http://onestepback.org">A Link</a>
xm.div { br }    # => <div><br/></div>
xm.target("name"=>"compile", "option"=>"fast")
    # => <target option="fast" name="compile"\>
    # ВНИМАНИЕ: порядок аттрибутов не сохраняется.

xm.instruct!    # <?xml version="1.0" encoding="UTF-8"?>
xm.html {    # <html>
  xm.head {    #   <head>
   xm.title("История")    #     <title>История</title>
 }    #   </head>
  xm.body {    #   <body>
    xm.comment!  "HI"    #     <!-- HI -->
   xm.h1("Заголовок")    #     <h1>Заголовок</h1>
   xm.p("параграф")    #     <p>параграф</p>
 }    #   </body>
}    # </html>

Роутинг 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.

Смотрите руководство по роутингу в Rails для подробного описания.

See the Routing in the Rails manual to learn more.

Фильтры

Фильтры позволяют вам выполнять предварительный код перед тем как Rails выполнит действие, а также после его выполнения. Это может быть полезно для таких вещей как кэширование или аутентификация перед вызовом действия, и компрессия или локализация ответа после его вызова. Фильтр before_filter может либо разрешить действию быть выполненным в нормальном режиме, возвратив true, либо отменить вызов вернув false (или выполнив операцию render или redirect).

Filters allow you to run preprocessing code before Rails executes an action and post-processing code after it completes an action. They are useful for such things as caching or authentication before calling the action, and compression or localization of the response after calling an action. The before_filter processing can either allow the action to be called normally by returning true, or abort the action by returning false (or by performing a render or redirect operation).

Например:

class BankController < ActionController::Base
  before_filter :audit

  private
    def audit
      # записать действие и параметры в лог для аудита
    end
end

class VaultController < BankController
  before_filter :verify_credentials

  private
    def verify_credentials
      # убедиться что пользователь имеет доступ в хранилище
    end
end

Остальные детали в документации класса ActionController::Filters.

 

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" } %>

создаёт ссылку на действие 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" }
%>

Это создаёт ссылку на метод index контроллера HelpController. Текстом ссылки будет "Содержание справки."

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.)

<form action="save_person" method="post">
  Имя:
  <%= text_field "person", "name", "size" => 20 %>

  Пароль:
  <%= password_field "person", "password", "maxsize" => 20 %>

  Холост?:
  <%= check_box "person", "single" %>

  Описание:
  <%= text_area "person", "description", "cols" => 20 %>

  <input type="submit" value="Сохранить">
</form>

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

<form action="save_person" method="post">
  Имя:
  <input type="text" id="person_name" name="person[name]" size="20" value="<%= @person.name %>" />

  Пароль:
  <input type="password" id="person_password" name="person[password]"
         size="20" maxsize="20" value="<%= @person.password %>" />

  Холост?:
  <input type="checkbox" id="person_single" name="person[single] value="1" />

  Описание:
  <textarea cols="20" rows="40" id="person_description"
           name="person[description]">
    <%= @person.description %>
  </textarea>

  <input type="submit" value="Сохранить">
</form>
<!-- End of general features -->

Есть помощники для создания тэгов 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 текущей страницы, часто фрагмент подставляется содержимым в тэг <div>.
  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 <div>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:

<html>
  <head>
    <title>Демонстрация списка с AJAX</title>
    <%= javascript_include_tag "prototype" %>
  </head>
  <body>
    <h3>Добавить к списку с помощью AJAX</h3>
    <%= form_remote_tag(:update => "my_list",
                           :url => { :action => :add_item },
                           :position => "top" ) %>
      Текст нового элемента:
      <%= text_field_tag :newitem %>
      <%= submit_tag "Добавить элемент через AJAX" %>
    <%= end_form_tag %>
    <ul id="my_list">
      <li>Начальный элемент... добавьте ещё!</li>
    </ul>
  </body>
</html>

Статья AJAX on Rails и API JavaScript помощников рассказывают о поддержке AJAX в Rails более подробно.

The article Ajax on Rails and the JavaScript Helpers API explain more about Rails' Ajax support.

Библиотека Prototype также предоставляет Rails разработчику целый набор визуальных эффектов на стороне браузера. Script.aculo.us содержит документацию и живую демонстрацию эффектов Prototype. Prototype также позволяет легко добавить к своему приложению drag-and-drop функциональность, об этом также можно узнать на сайте script.aculo.us.

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:

<html>
  <head>
    <title><%= @page_title %></title>
  </head>
  <body>
    <div>Шапка для этого макета</div>
    <div><%= @content_for_layout %></div>
    <div>Низ этого макета</div>
  </body>
</html>

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.

Чтобы узнать о макетах больше, смотрите документацию ActionController::Layout.

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.

Документация ActionView::Partials содержит подробную информацию. На Pointstorm есть более детальная презентация partials, но она несколько устарела, поскольку использует устаревший синтаксис вызова partials.

The ActionView::Partials documentation explains more. На Pointstorm has a more in-depth presentation of Ruby partials, but it is a little out of date because it uses the older, obsolete syntax for rendering partials.

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

Components are similar to partials in that they embed the rendering of another template within the current template. The difference is that you specify the name of a controller and action, and its template is the one to render and insert into the current template.

<%= render_component :controller => "calendar", :action => "today" %>

Загляните в раздел Компоненты руководства по Rails если хотите узнать больше.

Скаффолдинг (scaffolding)

Скаффолдинг позволяет вам получить быструю реализацию CRUD (Create, Retrieve, Update, and Delete) операций для любой таблицы базы данных. Они не очень красивы, но позволяют получить немедленный доступ через веб-интерфейс к вашим таблицам. С течением времени, вы можете постепенно заменить сгенерированные операции и шаблоны на свои.

Scaffolding allows you to get an instant implementation of CRUD (Create, Retrieve, Update, and Delete) operations on any database table. They're not pretty, but they do give you immediate web-based access to your tables. Over time, you can incrementally replace the generated CRUD operations and views with your own.

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

Rails supports static or dynamic scaffolding. Static scaffolding physically generates model, controller, and template files. This lets you see how it works and start tweaking this existing code. To generate static scaffolding, navigate in the file system to the root of your Rails web application and run a command similar to:

$ ruby script/generate scaffold invoices

Эта команда найдёт таблицу invoices в вашей базе данных и использует её схему для генерации модели, контроллера и всех шаблонов представления, скелетов для модульного тестирования и другой всячины. По мере хода процесса на экран будет выводиться список сгенерированных файлов.

This will look for an invoices table in your database and use its schema to generate the model, the controller, all of the view templates, the unit test skeletons, and more. The command displays a list of all the files that it generates.

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

The advantage of static scaffolding is that you get to see and modify the generated code. The disadvantage is that if you change you database table, the scaffolding will not reflect those changes. However, if you haven't modified the scaffolding, you can just regenerate it.

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

Dynamic scaffolding does not generate any files. Rails simply creates what it needs dynamically as your web app runs. This means that every time you change the database table, the scaffolding's CRUD views immediately show those changes. To request dynamic scaffolding, place a single line of code in the controller:

class AccountController < ActionController::Base
  scaffold :account
end

И много всего другого

Также как и в Active Record, в Action Pack очень много вещей о которых я не могу здесь рассказать. Если хотите узнать больше, посмотрите на Action Pack API.

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 "system@example.com"

  attachment :content_type => "image/jpeg", :body => File.read("an-image.jpg")

  attachment "application/pdf" do |a|
    a.body = generate_your_pdf_here()
  end
end

Узнать больше можно в Action Mailer API и главе 19 книги Agile Web Development with Rails.

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.

Вот часть MetaWeblog API реализованного Typo (open source блог система написанная на Rails):

Here is part of the MetaWeblog API as implemented by Typo (open source weblog software written in Rails):

 

class MetaWeblogApi < ActionWebService::API::Base

  api_method :getRecentPosts,
    :expects => [ {:blogid => :string},
                  {:username => :string},
                  {:password => :string},
                  {:numberOfPosts => :int} ],
    :returns => [[MetaWeblogStructs::Article]]

  api_method :deletePost,
    :expects => [ {:appkey => :string},
                  {:postid => :string},
                  {:username => :string},
                  {:password => :string},
                  {:publish => :int} ],
    :returns => [:bool]
end

class MetaWeblogService < TypoWebService
  web_service_api MetaWeblogApi

  def getRecentPosts(blogid, username, password, numberOfPosts)
    articles = Article.find_all(nil, "created_at DESC", numberOfPosts)
    articles.to_a.collect{ |c| article_dto_from(c) }
  end

  def deletePost(appkey, postid, username, password, publish)
    article = Article.find(postid)
    article.destroy
    true
  end
end

Этот отрывок показывает только два из семи методов API определённых Typo в этом классе.

Если хотите узнать больше, прочтите руководство по Action Web Service

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, чтобы самому убедиться о чём же собственно весь шум.



Опубликовал admin
31 Мар, Суббота 2007г.



Программирование для чайников.