» Главная
eXcode.ru » Статьи » Ruby
» Новости
» Опросы
» Файлы
» Журнал



Пользователей: 0
Гостей: 7





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




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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

Меньше кода

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

Генераторы

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

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

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

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

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

Компоненты Rails

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


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

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

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

Веб серверы

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

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

Базы данных

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

* MySQL
* PostgreSQL
* SQLite
* SQL Server
* DB2
* Oracle

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

Отладка

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

* Вставить отладочный вывод в контроллер. Например:

render_text "Дошёл до сюда"

or

render_text "объект user = " + user_obj

* Проверить логи Rails. (Используйте tail на *nix системах.) Посмотрите на файлы development.log, production.log и fastcgi.crash.log. Помните, что ваш веб сервер тоже ведёт логи.
* Использовать брейкпоинты.
* Использовать коммерческую среду разработки (такую как ArachnoRuby) со встроенным отладчиком.

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

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

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

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

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

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

* Генерация новых контроллеров, моделей и скаффолдига, также создаёт соответствующие скелеты модульных тестов.
* Чёткое следование архитектуре MVC как результат приводит к хорошо тестируемым действиям и компонентам.
* Rails включает в себя Rake (Ruby Make) скрипт, который может автоматически запускать все ваши модульные тесты.

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

Active Record

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

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

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

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

class Product < ActiveRecord::Base
end

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

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

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

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

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

* Класс модели Invoice привязывается к таблице invoices.
* Класс модели Person привязывается к таблице people.
* Класс модели Country привязывается к таблице countries.
* Класс модели SecurityLevel привязывается к таблице security_levels.

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

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

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

<h3>Ассоциации</h3>

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

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

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

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.

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

Валидация

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

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

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

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 emptyn" +
"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 собирается обновить существующую.

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

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

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

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

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

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

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 подробно рассказывает о методах обратного вызова.

Транзакции

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

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

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

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

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

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

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

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

Action Pack

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

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

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

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

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

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

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 привязан к действию по следующей схеме:

/:controller/:action/:id

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

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

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

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

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

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}/}

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

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.

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

Фильтры

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

Например:

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.

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

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

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

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

создаёт ссылку на действие help (метод) в текущем контроллере (том, который обрабатывает текущий запрос). Текст ссылки (видимый пользователем) будет "Помощь."

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

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

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

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

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

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

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

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

* Active Record Helpers
* Asset Tag Helpers
* Benchmark Helpers
* Cache Helpers
* Capture Helpers
* Date Helpers
* Debug Helpers
* Form Helpers
* Form Options Helpers
* Form Tag Helpers
* JavaScript Helpers
* Number Helpers
* Pagination Helpers
* Tag Helpers
* Text Helpers
* Upload Progress Helpers
* URL Helpers

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

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

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

1. Срабатывает триггер. Это может быть кликом пользователя на кнопку или ссылку, изменение данных в форме или поле, или просто временный триггер (на основе таймера).
2. Клиент асинхронно отсылает данные ассоциированные с триггером (поле или целую форму) к действию-обработчику на стороне сервера через XMLHttpRequest.
3. На стороне сервера действие-обработчик выполняет какие-то действия над данными и возвращает HTML фрагмент в качестве ответа.
4. JavaScript на стороне клиента (код генерируется Rails автоматически) принимает этот HTML фрагмент и использует его для обновления конкретной части HTML текущей страницы, часто фрагмент подставляется содержимым в тэг <div>.

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

<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 более подробно.

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

Макеты (Layouts)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

$ ruby script/generate scaffold invoices

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

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

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

class AccountController < ActionController::Base
scaffold :account
end

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

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

Action Mailer

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

# отправляем 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.

Action Web Service

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

Вот часть MetaWeblog API реализованного Typo (open source блог система написанная на 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

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

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

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

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

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

Автор: Дмитрия Сабанина
Источник: sabanin.ru
К началу статьи





Добавил: MadvEXДата публикации: 2008-02-11 00:59:20
Рейтинг статьи:5.00 [Голосов 1]Кол-во просмотров: 9375

Комментарии читателей

Всего комментариев: 500

2017-08-16 17:02:21
Barbaragaick
[b]Магазине По Низкой Цене С Бесплатной Доставкой. Купоны & Промокоды
[/b]
-----------------------------------
Белорусские рубли первого выпуска имели на лицевой стороне изображения животных и назывались расчетными билетами. Плюс к этому, в инструкции указан еще один проверенный и законный способ восстановления КБМ. Поставщики это 60 счет, соответственно, Д10К60, -постпупили материалы от поставщика; Д08.К.60 - поступило ОС. Идти в юр. Агенство это дорого, Снова подать документы это долго и ничего не даст. После чего, с вами свяжется наш сотрудник и предложит подходящие варианты, по необходимости, окажет юридическую помощь в вопросах кредитования. И эта карта не исключение. Брокер, в свою очередь, - это физическое или юридическое лицо, имеющее соответствующую лицензию и зарегистрированное в «Росстрахнадзоре». Остальные люди попросту боятся обращаться в банк чтобы получить кредит, ведь считают, что с низким доходом им откажут в кредитовании. Чешская крона — официальная валюта Чехии. Четыре тысячи сто двадцать пять евро. Вам придет ответное сообщение с разъяснениями. Это все элементы хозяйственного богатства, которые могут быть использованы в экономической деятельности в качестве источника прибыли. Без справки о доходах. Процессор МТК6589, который установлен вiPhone 5S, отвечает за производительность смартфона. Представители банков подчеркивают, что в некоторых случаях за рубежом действительно может понадобиться именно кредитная карта, особенно при бронировании номера в отеле или, как уже говорилось, при аренде автомобиля. Сотрудники также могут бесплатно проконсультироваться с личным тренером Олега Тинькова, который сам занимается в зале практически каждый день, когда находится в Москве.|После установки последнего на устройство стоит войти в личный кабинет, выбрать подменю «Платежи», услуги «Мобильная связь» и тип поставщика связи. После этого проценты по полученному займу в общем порядке включаются в состав прочих расходов с отнесением их в дебет счета 91 «Прочие доходы и расходы», субсчет «Прочие расходы». Каковы причины создания платежной системы «Мир»? К несомненному преимуществу можно отнести то, что некоторые банки бюджетникам и пенсионерам предлагают карты «Мир» с бесплатным обслуживанием. В разделе кредитные карты будет видно наименование банка-имитента карты, ее кредитный лимит, объем задолженности и сумма ближайшего платежа. Юридическое лицо может обратиться в банк «ТРАСТ» по телефону горячей линии 8(800)2001199. Звонок бесплатный из любого населенного пункта России. Ежемесячно наша команда проводит анализ сотен тарифов крупнейших сотовых операторов России и не только. Совмещать данную работу со своей основной работой (при её наличии) получится далеко не у всех – начальству вряд ли понравиться ваше активное общение с клиентами банка. Тинькофф банк – это первый банк Российской Федерации, который работает только онлайн. Тинькофф гарантирует надежность онлайн-сервиса и эффективную защиту от мошенников. Меня заинтересовало одно из предложений — агент банка в интернете, и я послал письмо на электронную почту в контактах вакансии (уже не помню, на каком сайте я её увидел). В рекламе банка почему-то делается упор на то, что такая работа идеально подходит молодым мамам.


[b]Перейдите ниже по ссылке, чтобы получить кредит:[/b]

http://kredit.bestsky.info/

2017-08-12 03:25:11
Barbaragaick
[b]Что Нужно Чтобы Взять Кредит?
[/b]
-----------------------------------
Жена скорее всего пойдет завтра испытывать удачу в очередной раз. О Вы что не смотрели что покупаете без скидки, раз расписались в полисе, то значит были согласны что скидки у вас не будет! Возмещение работником указанных сумм может быть произведено двумя путями: либо работник организации вносит наличные денежные средства в кассу организации, либо организация сумму ущерба удерживает из заработной платы работника. В течение десяти минут будет сообщено решение об одобрении заявки либо об отказе в кредитовании. По его словам, отсрочка возможна сроком на 1 год, так как необходимо отладить всю технологию, после чего решение может быть изменено. Для выхода в интернет-банк воспользуйтесь ссылкой https://www.tcsbank.ru/authentication/? Номиналы монет в обращении: 5, 10, 20, 50, 100, 200 форинтов. Но тут у МТС есть особенность — опция «Турбоночи», когда за 200 рублей подключается дополнительный ночной безлимит на месяц. Оплата принимается на расчетный счет или карту Сбербанка, а также карту Альфа-банка только с карт указанных банков или через оператора Сбербанка. В связи с этим «Россельхозбанк» является банком-агентом Правительства России, имеет большое количество кредитных организаций-партнеров за границей, и может выполнять любые целевые программы по развитию сельского хозяйства. Об этом уже шла речь выше, но этот момент важен для понимания и его не грех подчеркнуть еще раз: облигации не являются инструментом заработка, это инструмент сохранения.


[b]Перейдите ниже по ссылке, чтобы получить кредит:[/b]

http://kredit.bestsky.info/

2017-08-09 16:39:42
LarryHeilt
Хотим предложить вам чудодейственное средство для похудения сироп Мангустина. С ним можно избавиться от 15 kg за 14 суток.

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

Главным компонентом сиропа Mangoosteen являются фрукты с дерева мангостан, в которых содержится большое количество питательных микроэлементов. Благодаря веществу ксантону, которое в огромных количествах имеется во фрукте, сильно тормозятся окислительные процессы в теле. Ксантон признана одним из наиболее сильных антиоксидантов. В плодах дерева мангкут также есть различные группы витаминов и микроэлементы. Приобрести сироп Мансустина можно на интернет-сайте http://mangjoo77.mangoosteen.com.


2017-08-08 08:54:44
Barbaragaick
[b]Ремонт Айфон 5 С Киев
[/b]
-----------------------------------
Для этого рекомендуется посвящать этой работе примерно 30 часов в неделю. Еще надо сказать, что банк недавно выпустил, по сути, одноразовую карту «Нашествие» для дополнительной скидки в 10% на одноименном фестивале. Остаточная стоимость может составлять всего лишь 10% от реальной стоимости детали на рынке. IPhone может похвастаться качественной камерой, заменяющей полноценный фотоаппарат. В нашем магазине Вы можете купить дополнительный аккумулятор для iPhone 5 по самым демократичным ценам и самого лучшего качества. Иначе вы будете постоянно сидеть возле розетки или использовать внешний аккумулятор для подзарядки. Подробную информацию об условиях предоставления услуги и покрытия Вы можете получить, посетив ближайший к Вам офис АХА, по телефону инфолинии (8855,0 800 60 69 76) или на сайте. Вы познакомитесь со спецификой этого бизнеса. Если кредитная история отсутствует, то можно попробовать её создать. Кредитная история нулевая. Заранее спасибо за ответ. Согласно имеющейся информации в СМИ и интернете, руководству было вынесено предупреждение, однако банк не предпринял нужных действий по нормализации собственной деятельности.


[b]Перейдите ниже по ссылке, чтобы получить кредит:[/b]

http://kredit.bestsky.info/

2017-08-07 20:22:51
Barbaragaick
[b]Все Банки Йошкар-Олы И Марий Эл
[/b]
-----------------------------------
Если речь и идёт о выдаче кредитной карточки или экспресс кредитовании, вопрос рассматривается практически автоматически. Плюсом является и возможность быстрого оформления и получения карты в любом салоне мобильной связи Связного за 20 минут; и возможность использовать карту как дебетовую с начислением 3-7% годовых на остаток ежемесячно. Практически все современные карты сегодня изображаются видом сверху. Банк уже давно занимается выдачей кредитных карт населению без справок и с доставкой по всей России. В частности, Сбербанк работает с Объединенным бюро кредитных историй. Вся процедура онлайн оплаты через Сбербанк занимает немного времени — всего 5-10 минут. Калькулятор курса белорусского рубля поможет в режиме онлайн определить курс на нужную дату, а также перевести стоимость в белорусских рублях в другую валюту. C пересадкой в Краснодар из Сочи летают те же «ЮТэйр», а также «Аэрофлот», S7, «ВИМ-Авиа», «Победа» и «Уральские авиалинии». И все эти мошеннические действия многие годы остаются абсолютно безнаказанными, поскольку их же никто не проверяет, ни Центробанк, ни Генпрокуратура.


[b]Перейдите ниже по ссылке, чтобы получить кредит:[/b]

http://kredit.bestsky.info/

2017-08-07 06:01:32
Barbaragaick
[b]Живут В Офисах По 3 Дня И Готовы Отдать Пенсию За ОСАГО
[/b]
-----------------------------------
Петербурге Татьяна Бекенова. Она также отметила, что перевод продаж ОСАГО на управляющую структуру "Росгосстраха" в компании изначально рассматривали в качестве плана Б. Наш главный приоритет – высокий уровень обслуживания. Но кроме обслуживания, есть и продажи – что очень важно для банка. Для этого клиенту банка достаточно позвонить в центр обслуживания и заказать услугу по бесплатному телефону. Для этого напишите заявление на имя начальника загса, с требованием вернуть излишки. Если по каким-либо причинам вы являетесь заёмщиком банковских средств, не забывайте следить за своими платежами. Счет бухгалтерского учета 86 "Целевое финансирование" - счет предназначен для обобщения информации о движении средств, предназначенных для осуществления мероприятий целевого назначения, средств, поступивших от других организаций и лиц, бюджетных средств и др. ППС и сайт zenitbet25.win это одно и тоже, т.к. деньги приходят на счет. Только на нашем сайте Вы можете ознакомиться с быстрыми кредитами в тех микрофинансовых организациях, которые соответствуют требованиям Центрального Банка России. Собственный отдел взыскания работает с клиентами с просрочкой от 1 дня до 12 месяцев.|Свести то можно, но меня смущает 50% разница. Пока других способов компания не предлагает, но это вопрос времени. Кроме того, компания оставляет за собой право не заключать трудовой договор даже после прохождения обучения. Выражение «дебет», как и многие другие термины, русский язык заимствовал из немецкой речи, но есть мнение, что истоки уходят далеко в империю Рима (Debitum), где слово означает долг. Я купил полис, но не онлайн, а в офисе страховщика. Такой заем можно получить даже по временной регистрации, но придется дополнительно предъявить документ, подтверждающий постоянную регистрацию. Конечно же, начинка устройства далека от оригинала и в качестве операционной системы выступает Android, но внешне найти хотя бы минимальные отличия будет довольно проблематично. Можно ли получить деньги в кредит без справки о доходах в сумме более 10 000 гривен? Если же раньше молодые люди часто брали деньги у своих родителей, то сейчас все в корни изменилось. В "Открытии" же заявили, что кредитная организация уже обеспечивает клиентов картой "Мир".


[b]Перейдите ниже по ссылкам, чтобы получить кредит:[/b]

http://kredit.bestsky.info/

2017-08-07 02:03:24
LarryHeilt
Приобрести сироп Mangoosteen можно на веб-сайте http://mangjoo77.mangoosteen.com

Предлагаем нашим клиентам чудодейственное средство для снижения веса сироп Мангустина. С его помощью возможно сбросить около 15 kg за 14 дней.

Растение мангкут произрастает в Малайзии. Плоды данного дерева имеют потрясающие особенности. Во флакончике имеется более 20 плодов этого замечательного дерева. Плоды растения мангостин помогают убрать излишнею жировую ткань. И замечательно влияют на человека в комплексе. Специфика производства средства, и специальная упаковка позволяют сохранить все удивительные свойства мангостина.

Основным действующим компонентом сиропа Mangoosteen являются плоды с дерева гарциния, в них имеется огромное количество питательных элементов. Благодаря веществу ксантону, которое в громадных дозах имеется в плоде, значительно замедляются процессы окисления в теле. Ксантон признана одним из наиболее мощных антиокислителей. В плодах дерева мангостин к тому же есть разнообразные витамины и микроэлементы. Купить сироп Мансустина возможно на веб-сайте http://mangoo77.mangoosteen.com.


2017-07-23 16:34:32
Patrickguesk
Всё отлично, хорошая программа реабилитации. Отдельное спасибо персоналу клиники. Вышел пару недель назад – тяги к наркоте нет!

Даю ссылку - [url=https://krasnodar-deystvie.ru/kontakty]Телефон нарколога в Краснодаре[/url]

2017-07-05 17:58:50
arhankutvew
Не будем исследовать весь мир, остановимся на чудо-полуострове Крым.

Крым - это простор, где существует все для жизни, не просто для жизни усредненного каждого человека, у какого дом-работа-выходные и за окошком один и тот же ландшафт. А для жизни полной живописных ощущений и открытий. Крым, как шкатулка богатств, сколь бы ты раз ее не открывал, сокровища всегда обязательно будут блистать и поражать по-новому. Крым - это необъятное синее море, которое зовется Черным, это Генеральские, яшмовые, пустынные или, наоборот, людные пляжные берега с потрясающими видами. Это Беляус, Атлеш, Джангуль, Золотые ворота, Генуэзская крепость, заснеженный Херсонес, закат на подвесных мостах Ай-Петри, рассвет на горе Чатыр-Даг, осенние виноградники... Всего попросту не счесть. И все это на очень компактной местности, какую с запада на восток возможно проехать за полдня на автомобиле. Что касается экономики и инфраструктуры населенных пунктов, то с этим тоже все в полном порядке. Крым инициативно развивается и расширяется. Не стоит не вспоминать и про редкий климатические условия Крымского региона.


[url=https://tarhankut-servis.ru]https://tarhankut-servis.ru/[/url]

2017-07-05 16:07:22
arhankutvew
Не будем исследовать целый мир, остановимся на чудо-полуострове Крым.

Крым - это место, где сейчас имеется все для жизни, не только для существования среднестатистического каждого человека, у какого дом-работа-выходные и за окном один и тот же пейзаж. А для существования полной красочных ощущений и открытий. Крым, как шкатулка богатств, сколько бы ты раз ее не отворял, сокровища постоянно будут сверкать и удивлять по-новому. Крым - это безграничное синее море, какое зовется Черным, это Генеральские, яшмовые, безлюдные или, наоборот, людные пляжные берега с изумительными видами. Это Беляус, Атлеш, Джангуль, Золотые ворота, Генуэзская крепость, заснеженный Херсонес, закат на подвесных мостах Ай-Петри, рассвет на горе Чатыр-Даг, осенние виноградники... Всего попросту не счесть. И все это на весьма компактной территории, какую с запада на восток возможно проехать за полдня на автомобиле. Что касается экономики и инфраструктуры городов, то с этим тоже все в порядке. Крым динамично развивается и расширяется. Не стоит упускать из вида и про редкий климатические условия Крымского региона.


[url=https://tarhankut-servis.ru]https://tarhankut-servis.ru/[/url]
Ваше имя: *
Текст записи: *
Имя:

Пароль:



Регистрация

Какие книги вам больше нравятся?
Приключения
7% (12)
Фантастика и фэнтези
30% (50)
Детективы
5% (8)
Ужасы
0% (0)
Юмористические
1% (2)
Учебники и энциклопедии
12% (20)
Спец. литературу
22% (37)
Я не умею читать :(
17% (28)
Другие
5% (9)

Проголосовало: 166
Призвали как-то одного волосатого админа в армию служить, на границу. Поставили его в дозор. Вдруг админ слышит шаги...
- Стой! Пароль!.. ответ из темноты:
- Владивосток...
- Логин...
- ?!..
Рейтинг: 5/10 (2)
Посмотреть все анекдоты