Статьи

От CodeIgniter к Ruby on Rails: преобразование

Сегодня мы создадим простой чат с использованием PHP-фреймворка CodeIgniter. Затем мы будем портировать это точное приложение по частям на Ruby on Rails!


Конечный продукт

В этом руководстве мы создадим простое приложение shoutbox в CodeIgniter, а затем перенесем его на Ruby on Rails. Мы будем сравнивать код между двумя приложениями, чтобы увидеть, где они похожи и где они различаются. Изучать Rails намного проще, если вы уже знакомы со структурой инфраструктуры MVC (Model, View, Controller).

Да, или опыт работы с PHP и другими MVC-фреймворками (CakePHP, Zend и т. Д.). Ознакомьтесь с некоторыми другими учебными пособиями по CI здесь, на Nettuts , включая серию видео с нуля !

Хотя это поможет, нет. Я приложил все усилия, чтобы сделать прямые сравнения между Ruby и PHP, а также между Rails и CodeIgniter, поэтому, применяя имеющиеся у вас знания, это не будет слишком сложным.

Начните с загрузки платформы CodeIgniter на локальный / веб-сервер и настройте базу данных (я назвал ее ci_shoutbox ) с помощью следующих команд SQL:

01
02
03
04
05
06
07
08
09
10
11
12
13
CREATE TABLE `shouts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `message` text NOT NULL,
  PRIMARY KEY (`id`)
);
 
INSERT INTO `shouts` (`id`,`name`,`email`,`message`)
VALUES
  (1,’Dan Harper’,’[email protected]’,’Hello, World!’),
  (2,’Bob’,’[email protected]’,’This looks great!’),
  (3,’Dan Harper’,’[email protected]’,’Hey, thanks for the comment!’);

Как обычно в CodeIgniter, введите свои данные в /system/application/config/database.php :

1
2
3
4
$db[‘default’][‘hostname’] = «localhost»;
$db[‘default’][‘username’] = «root»;
$db[‘default’][‘password’] = «»;
$db[‘default’][‘database’] = «ci_shoutbox»;

Затем config.php :

1
2
3
4
5
$config[‘base_url’] = «http://localhost/shoutbox/»;
$config[‘global_xss_filtering’] = TRUE;
$config[‘rewrite_short_tags’] = TRUE;

И autoload.php :

1
2
3
4
$autoload[‘libraries’] = array(‘database’, ‘form_validation’, ‘session’);
$autoload[‘helper’] = array(‘url’, ‘form’);
$autoload[‘model’] = array(‘shout’);

Наконец, установите контроллер по умолчанию внутри routes.php :

1
$route[‘default_controller’] = «shouts»;

Поскольку это такое простое приложение, нам нужен только один контроллер и одна модель. Inside /controllers/ create shouts.php :

1
2
3
4
5
6
7
8
<?php
class Shouts extends Controller {
 
  function Shouts() {
    parent::Controller();
  }
 
}

И модель как /models/shout.php :

1
2
3
4
5
6
7
8
<?php
class Shout extends Model {
 
  function Shout() {
    parent::Model();
  }
 
}

Наша главная страница, индекс, выводит 10 последних криков из базы данных. Начните с добавления следующего в контроллер Shouts:

1
2
3
4
function index() {
  $data[‘shouts’] = $this->shout->all_shouts();
  $this->load->view(‘shouts/index.php’, $data);
}

В строке 2 мы вызываем all_shouts() из модели Shout.
После этого мы загружаем соответствующий файл представления и передаем в него переменную $data (CodeIgniter автоматически разберет массив $data , чтобы мы могли получить доступ к крикам просто как $shouts вместо $data['shouts'] ).

Давайте теперь создадим all_shouts() в нашей модели:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
function all_shouts() {
  $data = array();
  $this->db->order_by(‘id’, ‘DESC’);
  $q = $this->db->get(‘shouts’, 10);
   
  if ($q->num_rows() > 0) {
    foreach ($q->result() as $row) {
      $data[] = $row;
    }
  }
   
  return $data;
  $q->free_result();
}

Это относительно просто. Мы извлекаем 10 самых последних записей из таблицы «крики» и выводим их в порядке убывания. Это создаст следующую команду SQL за кулисами:

1
SELECT * FROM `shouts` ORDER BY `id` DESC LIMIT 10;

Если какие-либо записи были найдены, они добавляются в массив $data и возвращаются в контроллер.

Внутри каталога /views/ создайте следующие файлы и папки:

  • footer.php
  • header.php
  • /shouts/
    • index.php

Добавьте следующее в /shouts/index.php :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
$this->load->view(‘/header.php’);
 
if ($shouts) {
  echo ‘<ul>’;
  foreach ($shouts as $shout) {
    $gravatar = ‘http://www.gravatar.com/avatar.php?gravatar_id=’ .
    ?>
 
    <li>
      <div class=»meta»>
        <img src=»<?= $gravatar ?>» alt=»Gravatar» />
        <p><?= $shout->name ?></p>
      </div>
      <div class=»shout»>
        <p><?= $shout->message ?></p>
      </div>
    </li>
 
    <?php
  }
}
else {
  echo ‘<p class=»error»>No shouts found!</p>’;
}
 
$this->load->view(‘/footer.php’);

В строке 2 мы включаем header.php .
Если какие-либо крики были возвращены из базы данных, мы перебираем их с помощью foreach и создаем базовый список с Gravatar автора, его именем и сообщением. Если крики не были найдены, мы показываем сообщение об ошибке.
Наконец, мы включаем footer.php .

Обратите внимание, что в строке 7 мы создаем URL Gravatar . URL содержит хеш MD5 адреса электронной почты пользователя. Мы используем strtolower() PHP strtolower() чтобы гарантировать, что все письма будут в нижнем регистре, если служба Gravatar чувствительна к регистру.

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
echo form_open(‘shouts/create’);
  <h2>Shout!</h2>
 
  <div class=»fname»>
    <label for=»name»><p>Name:</p></label>
    <input type=»text» name=»name» value=»<?= set_value(‘name’) ?>» />
    </div>
 
  <div class=»femail»>
    <label for=»email»><p>Email:</p></label>
    <input type=»text» name=»email» value=»<?= set_value(’email’) ?>» />
  </div>
 
  <textarea name=»message» rows=»5″ cols=»40″><?= set_value(‘message’) ?></textarea>
 
  <p><input type=»submit» value=»Submit» /></p>
  <?php
echo form_close();
$this->load->view(‘/footer.php’);

В строке 1 мы используем form_open() из помощника form_open() по форме. Это создает открывающий тег <form> с соответствующими параметрами и будет указывать на shouts / create (функция Create внутри контроллера Shouts).
Остальное — обычная HTML-форма, за исключением того, что мы повторяем set_value() для каждого «значения». В ближайшее время мы добавим проверку в форму, и это гарантирует, что в случае каких-либо ошибок представленные данные автоматически повторно вводятся в форму.

Наконец, нам нужно создать верхний и нижний колонтитулы. Добавьте следующее в /views/header.php :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN»
«http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
 
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>Shoutbox in CodeIgniter</title>
<link rel=»stylesheet» href=»<?php echo base_url(); ?>css/style.css» type=»text/css» />
</head>
<body>
<div id=»container»>
 
  <h1>Shoutbox</h1>
  <h5>
    <a href=»http://www.danharper.me» title=»Dan Harper»>Dan Harper </a> :
    <a href=»http://net.tutsplus.com» title=»Nettuts — Spoonfed Coding Skills»>Nettuts</a>
  </h5>
 
  <div id=»boxtop»></div>
  <div id=»content»>

Смотрите в строке 8, что при включении таблицы стилей мы используем base_url() из помощника URL CodeIgniter для генерации URL-адреса для корня сайта — это поместит таблицу стилей по адресу http://example.com/css/style. css .

Добавьте следующее в /views/footer.php :

1
2
3
4
5
</div><!—/content—>
<div id=»boxbot»></div>
</div><!—/container—>
</body>
</html>

Поскольку форма указывает на функцию Create в контроллере Shouts, давайте создадим это сейчас:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
function create() {
  $data[‘shouts’] = $this->shout->all_shouts();
   
  $this->form_validation->set_rules(‘name’, ‘Name’, ‘required|max_length[255]|htmlspecialchars’);
  $this->form_validation->set_rules(’email’, ‘Email’, ‘valid_email|required|max_length[255]|htmlspecialchars’);
  $this->form_validation->set_rules(‘message’, ‘Shout’, ‘required|htmlspecialchars’);
   
  if ($this->form_validation->run() == FALSE) {
    $this->load->view(‘shouts/index.php’, $data);
  }
  else {
    $this->shout->create();
    $this->session->set_flashdata(‘success’, ‘Thanks for shouting!’);
    redirect(‘shouts/index’);
  }
}

В строке 2 мы извлекаем крики (как мы делали с функцией index), так как они все еще должны быть показаны.
Строки 4-6 — наши правила проверки. Сначала мы проверяем вводимое имя из отправленной формы, а затем — читаемую человеком версию. Третий параметр содержит разделенный по конвейеру (‘|’) список правил проверки.

Например, мы устанавливаем все поля как обязательные, а также пропускаем их через htmlspecialchars перед отправкой. «Имя» и «Электронная почта» имеют максимальную длину, а поле отправленной электронной почты должно напоминать адрес электронной почты.

Если проверка не пройдена, представление индекса загружается снова; в противном случае мы запускаем функцию create() из модели Shout. В строке 13 мы устанавливаем сообщение об успехе во флэш-данные, которые будут отображаться на следующей выполненной странице.

Прежде чем продолжить, мы должны отобразить сообщения об ошибках и успехах (см. Изображения выше) в нашем представлении. Добавьте следующее непосредственно после того, как мы /views/shouts/index.php заголовок в /views/shouts/index.php :

1
2
3
4
5
if ($this->session->flashdata(‘success’)) {
  echo ‘<p class=»success»>’ .
}
 
echo validation_errors(‘<p class=»error»>’, ‘</p>’);

Внутри модели Shout введите следующее:

1
2
3
4
5
6
7
8
function create() {
  $data = array(
    ‘name’ => $this->form_validation->set_value(‘name’),
    ’email’ => $this->form_validation->set_value(’email’),
    ‘message’ => $this->form_validation->set_value(‘message’)
  );
  $this->db->insert(‘shouts’, $data);
}

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

В самом корневом каталоге вашего приложения — в той же папке, что и папка /system/ CodeIgniter, создайте две новые папки: /css/ и /images/ .
В папке CSS добавьте следующее в файл с именем style.css :

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
* {
margin: 0;
padding: 0;
}
 
body {
background: #323f66 top center url(«../images/back.png») no-repeat;
color: #ffffff;
font-family: Helvetica, Arial, Verdana, sans-serif;
}
 
h1 {
font-size: 3.5em;
letter-spacing: -1px;
background: url(«../images/shoutbox.png») no-repeat;
width: 303px;
height: 66px;
margin: 0 auto;
text-indent: -9999em;
color: #33ccff;
}
 
h2 {
font-size: 2em;
letter-spacing: -1px;
background: url(«../images/shout.png») no-repeat;
width: 119px;
height: 44px;
text-indent: -9999em;
color: #33ccff;
clear: both;
margin: 15px 0;
}
 
h5 a:link, h5 a:visited {
color: #ffffff;
text-decoration: none;
}
 
h5 a:hover, h5 a:active, h5 a:focus {
border-bottom: 1px solid #fff;
}
 
p {
font-size: 0.9em;
line-height: 1.3em;
font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
}
 
p.error, .errorExplanation li {
background-color: #603131;
border: 1px solid #5c2d2d;
padding: 10px !important;
margin-bottom: 15px;
}
 
p.success {
background-color: #313d60;
border: 1px solid #2d395c;
padding: 10px;
margin-bottom: 15px;
}
 
#container {
width: 664px;
margin: 20px auto;
text-align: center;
}
 
#boxtop {
margin: 30px auto 0px;
background: url(«../images/top.png») no-repeat;
width: 663px;
height: 23px;
}
 
#boxbot {
margin: 0px auto 30px;
background: url(«../images/bot.png») no-repeat;
width: 664px;
height: 25px;
}
 
#content {
margin: 0 auto;
width: 600px;
text-align: left;
background: url(«../images/bg.png») repeat-y;
padding: 15px 35px;
overflow: hidden;
}
 
#content ul {
margin-left: 0;
margin-bottom: 15px;
}
 
#content ul li {
list-style: none;
clear: both;
padding-top: 30px;
}
 
#content ul li:first-child {
padding-top:0;
}
 
.meta {
width: 85px;
text-align: left;
float: left;
min-height: 110px;
font-weight: bold;
}
 
.meta img {
padding: 5px;
background-color: #313d60;
}
 
.meta p {
font-size: 0.8em;
}
 
.shout {
width: 500px;
float: left;
margin-left: 15px;
min-height: 110px;
padding-top: 5px;
}
 
form {
clear: both;
margin-top: 135px !important;
}
 
.fname, .femail {
width: 222px;
float: left;
}
 
form p {
font-weight: bold;
margin-bottom: 3px;
}
 
form textarea {
width: 365px;
overflow: hidden;
}
 
form input, form textarea {
background-color: #313d60;
border: 1px solid #2d395c;
color: #ffffff;
padding: 5px;
font-family: Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif;
margin-bottom: 10px;
}

И сохраните следующие изображения в папку /images/ : (при сохранении изображения будут иметь правильный размер!)

back.png
bg.png
bot.png
shout.png
shoutbox.png
top.png

Для подтверждения, ваша структура каталогов должна выглядеть как на картинке ниже:

И … готово! Если вы думаете, что мы написали очень мало фактического внутреннего кода в CI, подождите, пока мы не доберемся до Rails, где все взаимодействие с базами данных автоматизировано!

В этом руководстве я предполагаю, что в вашей системе правильно установлены Ruby, Rails и MySQL (или предпочитаемый вами механизм базы данных). Если нет, см. Руководство по установке Rails и страницу загрузки MySQL . Если вы используете Mac OSX Leopard, Ruby и Rails предустановлены.

Также полезно знать, как перемещаться в вашей операционной системе с помощью командной строки. Например, чтобы изменить каталог, используйте cd foldername или cd C:\Users\Dan и т. Д.

Rails предоставляет ряд инструментов командной строки для ускорения разработки вашего приложения. Внутри терминала (или командной строки в Windows) перейдите в папку, в которой вы хотите хранить свои проекты Rails. Лично я храню их в каталоге /rails/ в моей пользовательской области.

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

1
rails -d mysql shoutbox

Здесь Rails установится в /shoutbox/ . Поскольку MySQL — мой предпочтительный движок базы данных, я указываю -d mysql . Если вы предпочитаете использовать MySQLlite (по умолчанию в Rails), вы просто запустите rails shoutbox .
Перейдите в каталог shoutbox:

1
cd shoutbox

Теперь мы сгенерируем контроллер и модель:

1
2
3
ruby script/generate controller Shouts
 
ruby script/generate model Shout

Rails теперь сгенерировал наш контроллер ‘Shouts’ и модель ‘Shout’. Важно знать, что Rails поддерживает строгий стиль именования.
Ваш контроллер должен быть назван во множественном числе того, с чем он будет иметь дело (например, Крики, Пользователи, Списки). Контроллер обычно работает только с одной моделью, которая названа в единственном числе (например, Shout, User, Listing). Следование этому стандарту гарантирует, что Rails сможет использовать все свои функции.

Внутри вашего каталога shoutbox откройте файл /config/database.yml, в котором будут /config/database.yml данные нашей базы данных. Введите свои данные в разделе «Разработка»:

1
2
3
4
5
6
7
8
9
development:
 adapter: mysql
 encoding: utf8
 reconnect: false
 database: shoutbox_development
 pool: 5
 username: root
 password:
 socket: /tmp/mysql.sock

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

Затем откройте файл /db/migrate/***_create_shouts.rb (в большинстве версий Rails к /db/migrate/***_create_shouts.rb файла /db/migrate/***_create_shouts.rb дата и время):

01
02
03
04
05
06
07
08
09
10
11
12
class CreateShouts < ActiveRecord::Migration
  def self.up
    create_table :shouts do |t|
 
      t.timestamps
    end
  end
 
  def self.down
    drop_table :shouts
  end
end

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

Здесь мы добавим поля нашей базы данных:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
class CreateShouts < ActiveRecord::Migration
  def self.up
    create_table :shouts do |t|
      t.string :name
      t.string :email
      t.text :message
      t.timestamps
    end
  end
 
  def self.down
    drop_table :shouts
  end
end

Это может выглядеть страшно, но это очень просто! t.string :name создает поле «имя» в базе данных, которое будет храниться в виде строки (т. е. «varchar»). То же самое касается поля «электронная почта».
Поле ‘message’ добавляется и сохраняется как текст (как в SQL).

Вы заметите, что Rails автоматически включает t.timestamps . Это включает в себя поля create_at и updated_at, которые Rails будет автоматически заполнять при создании или обновлении поля.
Кроме того, Rails автоматически создаст поле id, поэтому нам не нужно это определять самим.

Это эквивалентно следующей команде SQL:

01
02
03
04
05
06
07
08
09
10
CREATE TABLE `shouts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `message` text,
  `ipaddress` varchar(15) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Хотя для создания этих миграций может понадобиться немного привыкнуть, их гораздо проще набирать, чем SQL!

Наконец, выполните следующие две команды в Терминале, чтобы создать и настроить базу данных:

1
2
3
rake db:create
 
rake db:migrate

Первая команда создает базу данных с именем ‘shoutbox_development’. Второй запускает любые внешние миграции баз данных (в данном случае наш файл ***_create_shouts.rb ).

Запустите сервер, а затем перейдите по адресу http: // localhost: 3000 (или любой другой порт, на котором сервер говорит, что он работает — в большинстве случаев это 3000):

1
ruby script/server

Чтобы удалить страницу приветствия по умолчанию, сначала удалите файл в /public/index.html , затем в /config/routes.rb вставьте следующее где-нибудь между первой и последней строками:

1
map.root :controller => «shouts»

Вам нужно будет перезапустить сервер всякий раз, когда вы вносите изменения в контроллер или в маршруты — нажмите Ctrl + C, затем повторно запустите ruby script/server .

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

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

Из папки вашего приложения в Терминале запустите ruby script/console . Это интерактивный интерпретатор Ruby, который также подключен к нашему приложению Rails, поэтому мы можем взаимодействовать с ним!

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

Запустите следующий код ruby ​​внутри интерактивной консоли:

1
2
3
4
shout = Shout.new(
 :name => ‘Dan Harper’,
 :email => ’[email protected]’,
 :message => ‘Hello, World!’)

Здесь мы вызываем new метод Rails для модели «Кричать» — это создаст новую запись в таблице базы данных криков. Мы также передаем хеш, содержащий данные, которые мы хотим ввести.
Это хранится в переменной «кричать».

Примечание. Хеш — это то, что PHP называет ассоциированным массивом — массивом, в котором вы также можете установить свой собственный ключ.
Примерный PHP-эквивалент этого кода:

1
2
3
4
$shout = $this->shout->new(
 ‘name’ => ‘Dan Harper’,
 ’email’ => ’[email protected]’,
 ‘message’ => ‘Hello, World!’);

Наконец, сохраните это в базу данных с помощью:

1
shout.save

Если вы ввели код правильно, ruby ​​должен вернуть ‘true’.
Теперь вы можете получить это из базы данных с помощью:

1
2
3
shout = Shout.find :last
 
shout.name

Первая команда найдет самую последнюю строку в таблице «крики» и сохранит ее в переменной «крик». Мы можем найти конкретный элемент с shout.name который должен возвращать все, что вы ввели в качестве «имени» для записи.

Повторите Shout.new и Shout.save еще несколько раз, чтобы добавить больше записей в базу данных.

Внутри файла /app/controllers/shouts_controller.rb введите следующее между существующим оператором класса:

1
2
3
def index
  @shouts = Shout.all_shouts
end

Мы вызываем метод all_shouts из модели ‘Shout’ и сохраняем результат в переменной экземпляра shouts (как видно из @ ).

В CodeIgniter эквивалентный код был:

01
02
03
04
05
06
07
08
09
10
11
12
class Shouts extends Controller {
 
  function Shouts() {
    parent::Controller();
  }
 
  function index() {
    $data[‘shouts’] = $this->shout->all_shouts();
    $this->load->view(‘shouts/index.php’);
  }
 
}

Некоторые заметные различия:

  1. Rails использует символ «<» вместо «extends» при создании класса;
  2. Для создания функции / метода мы используем def вместо function ;
  3. Rails не требует метода конструктора;
  4. Rails автоматически загружает файл представления для текущего метода. В этом случае файл представления находится по адресу /app/views/shouts/index.html.erb ;
  5. Уже заметно, что код в Rails намного чище. Вам не нужны скобки (скобки) при определении функции / метода, если он не содержит никаких параметров, нам не нужно добавлять точку с запятой в конце каждого оператора, и в поле зрения нет фигурных скобок!

Внутри /app/models/shout.rb введите следующее внутри класса, чтобы определить функцию all_shouts :

1
2
3
def self.all_shouts
  Shout.find(:all, :limit => 10, :order => ‘id DESC’)
end

Здесь мы запускаем Rails ‘ find для модели Shout (т. Е. Таблицы криков). Мы передаем хеш, сообщающий методу ограничить количество результатов до 10 в порядке убывания.
Это эквивалентный код CodeIgniter:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
function all_shouts() {
  $data = array();
  $this->db->order_by(‘id’, ‘DESC’);
  $q = $this->db->get(‘shouts’, 10);
 
  if ($q->num_rows() > 0) {
    foreach ($q->result() as $row) {
      $data[] = $row;
    }
  }
 
  return $data;
  $q->free_result();
}

Да … намного проще!
Также обратите внимание, что в Ruby, если вы специально не return что-либо, автоматически возвращается последний оператор. Например, мы могли бы использовать следующее вместо этого (хотя это не имело бы никакого значения):

1
2
3
def self.all_shouts
  return Shout.find(:all, :limit => 10, :order => ‘id DESC’)
end

В CodeIgniter нам приходилось вручную включать файлы верхнего и нижнего колонтитула в каждом представлении. Rails использует немного другой подход. Внутри /views/layouts/ создайте файл с именем application.html.erb со следующим внутри:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Transitional//EN»
«http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd»>
<html xmlns=»http://www.w3.org/1999/xhtml»>
<head>
<meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″ />
<title>Shoutbox in Ruby on Rails</title>
<%= stylesheet_link_tag ‘style’, :media => ‘screen’ %>
</head>
<body>
<div id=»container»>
 
  <h1>Shoutbox</h1>
  <h5>
    <a href=»http://www.danharper.me» title=»Web Developer»>Dan Harper </a> :
    <a href=»http://net.tutsplus.com» title=»Nettuts — Spoonfed Coding Skills»>Nettuts</a>
  </h5>
 
  <div id=»boxtop»></div>
  <div id=»content»>
 
    <%= yield %>
 
  </div><!—/content—>
<div id=»boxbot»></div>
</div><!—/container—>
</body>
</html>

Это преимущественно обычный HTML-макет, сочетающий в себе как верхний, так и нижний колонтитулы. В строке 7 мы включаем ссылку на таблицу стилей. Rails предоставляет папку /public/ в которую вы включаете изображения, таблицу стилей, файлы javascript и любые статические файлы HTML. В этом случае код выведет ссылку на таблицу стилей по адресу /public/stylesheets/style.css .

Далее в строке 21 находится <%= yield %> . Это вставит файл основного вида для конкретной страницы в этом месте.

Почему .html.erb? Все файлы представлений в Rails сначала имеют расширение для определенного формата, который вы хотите выводить, а затем .erb, чтобы сервер интерпретировал код Ruby внутри него.
Это означает, что у вас также может быть файл .xml.erb, если вы хотите экспортировать в XML для определенных страниц и т. Д.

<%= %> Ruby использует <% и %> чтобы обернуть любой код Ruby для интерпретации, так же как PHP использует <?php и ?> .
На страницах HTML мы используем <%= ... %> (обратите внимание на равно), чтобы «напечатать» код. В PHP мы используем <?php echo ... ?> Или <?= ... ?> Для ‘echo’ кода.

Внутри /public/stylesheets/ создайте файл с именем style.css содержащий тот же CSS, который мы использовали в разделе CodeIgniter.
Также вставьте изображения из раздела CodeIgniter в /public/images/ .

Если вы перезагрузите сервер сейчас и перезагрузите браузер, вы должны увидеть страницу ошибки «Шаблон отсутствует». Это потому, что мы еще не создали фактическое представление для текущей страницы.

Страница ошибки «Шаблон отсутствует» сообщает нам, какой файл он ожидал:
«Отсутствует шаблон shouts/index.html.erb в пути просмотра app/views «
Итак, давайте создадим этот файл сейчас и введем следующее, чтобы проверить его:

1
Hello, World!

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?php
echo ‘<ul>’;
foreach ($shouts as $shout) {
  $gravatar = ‘http://www.gravatar.com/avatar.php?gravatar_id=’ .
  ?>
 
  <li>
    <div class=»meta»>
      <img src=»<?= $gravatar ?>» alt=»Gravatar» />
      <p><?= $shout->name ?></p>
    </div>
    <div class=»shout»>
      <p><?= $shout->message ?></p>
    </div>
  </li>
 
  <?php
}
echo ‘</ul>’;

Эквивалент в Ruby следующий (замените сообщение «Hello, World!» Этим):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<ul>
<% for shout in @shouts
 
  gravatar = ‘http://www.gravatar.com/avatar.php?gravatar_id=’ + Digest::MD5.hexdigest(h(shout.email.downcase)) + ‘&size=70’ %>
 
  <li>
    <div class=»meta»>
      <img src=»<%= gravatar %>» alt=»Gravatar» />
      <p><%= shout.name %></p>
    </div>
    <div class=»shout»>
      <p><%= shout.message %></p>
    </div>
  </li>
 
<% end %>
</ul>

В строке 2 находится обычный цикл ‘foreach’ в Ruby. Вместо foreach ($shouts as $shout) в PHP мы используем for shout in @shouts в Ruby.

Цикл замыкается в end строки 16.

В строке 4 мы создаем URL Gravatar почти так же, как в PHP, с некоторыми исключениями:

  1. В PHP мы используем символ точки (.) Для объединения операторов, Ruby использует символ плюс (+), как в JavaScript;
  2. Рубиновая версия PHP-функции md5()Digest::MD5.hexdigest() ;
  3. Функция h() в Ruby эквивалентна PHP htmlspecialchars() ;
  4. PHP использует -> для доступа к объекту (например, $shout->email ). Ruby использует точку (например, shout.email );
  5. Чтобы адрес электронной почты был в нижнем регистре, мы используем strtolower($shout->email) в PHP. В Ruby все является объектом, поэтому мы просто добавляем .downcase к концу строки или переменной — shout.email.downcase . Вы также можете .upcase , .reverse и т. Д.

Обновите страницу в вашем браузере, и теперь вы должны увидеть сообщения!

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

1
2
3
<% form_for :shout, :url => { :action => ‘create’ } do |f|
  … code here …
<% end %>

Это блок из помощника форм Rails для простого создания форм. form_for :shout связывает форму напрямую с моделью Shout.

:url = { :action = 'create ' } — это хэш, детализирующий, куда форма будет направлена ​​при отправке. В этом случае форма перейдет в / shouts / create / (Контроллер криков, метод Create). Мы могли бы набрать:: :url = { :controller = 'shouts', :action = 'create } , однако отсутствие ключа’ controller ‘в хэше указывает Rails использовать текущий контроллер.

Наконец, do |f| сохраняет все ранее в переменной f . Например, мы могли бы создать текстовое поле, связанное с этим, используя f.text_field

Теперь мы объяснили, что введите полный код формы внизу файла представления индекса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<% form_for :shout, :url => { :action => ‘create’ } do |f|
 
  <h2>Shout!</h2>
 
  <div class=»fname»>
    <label for=»name»><p>Name:</p></label>
    <%= f.text_field :name, :size => 20 %>
  </div>
 
  <div class=»femail»>
    <label for=»email»><p>Email:</p></label>
    <%= f.text_field :email, :size => 20 %>
  </div>
 
  <%= f.text_area :message, :rows => 5, :cols => 40 %>
 
  <p><%= submit_tag ‘Submit’ %></p>
 
<% end %>

И сравните это с версией CodeIgniter PHP:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
echo form_open(‘shouts/create’);
  <h2>Shout!</h2>
 
  <div class=»fname»>
    <label for=»name»><p>Name:</p></label>
    <input type=»text» name=»name» value=»<?= set_value(‘name’) ?>» />
  </div>
 
  <div class=»femail»>
    <label for=»email»><p>Email:</p></label>
    <input type=»text» name=»email» value=»<?= set_value(’email’) ?>» />
  </div>
 
  <textarea name=»message» rows=»5″ cols=»40″><?= set_value(‘message’) ?></textarea>
 
  <p><input type=»submit» value=»Submit» /></p>
  <?php
echo form_close();

Мы больше используем помощник по формам Rails при создании полей ввода, текстовой области и кнопки отправки. С помощью f.text_field :name, :size = 20 мы создаем текстовое поле с именем ‘name’ (соответствующее столбцу в нашей базе данных, в который он должен быть вставлен). Это вывело бы в HTML как:

1
<input type=»text» name=»shout[name]» id=»shout_name» size=»20″ />

В версии приложения CodeIgniter мы установили для каждого поля ввода значение « <?= set_value('email') ?> Поэтому CodeIgniter автоматически заполнит поля, если они не пройдут проверочные тесты.
В Rails это обрабатывается автоматически, так как мы используем помощник по формам Rails для создания входных данных.

Обновите страницу в вашем браузере, и вы должны увидеть форму внизу:

Следующим шагом является вставка любых отправленных данных в базу данных. Форма направлена ​​на shouts / create, поэтому давайте сейчас создадим действие create (внутри контроллера):

01
02
03
04
05
06
07
08
09
10
11
def create
  @shouts = Shout.all_shouts
 
  @shout = Shout.new(params[:shout])
  if @shout.save
    flash[:notice] = ‘Thanks for shouting!’
    redirect_to :action => ‘index’
  else
    render :action => ‘index’
  end
end

В строке 2 мы извлекаем все наши текущие крики из базы данных, так как они все еще должны отображаться.

В строке 4 мы загружаем new функцию Rails для нашей модели Shout. Вы помните, что мы использовали Shout.new при вставке фиктивных данных в базу данных через интерактивную консоль.
Мы передаем new представленные данные с помощью params[] — так Rails обращается к данным POST.
Это загружается в переменную экземпляра @shout .

Когда мы использовали интерактивную консоль, мы использовали shout.save для сохранения данных. Если он был успешным, он возвращает «true», в противном случае возвращается «false». Таким образом, в строке 5 мы проверяем, можно ли сохранить крик в базе данных, если это так, мы загружаем уведомление об успешном завершении в «флэш-данные» сеанса и перенаправляем обратно в индекс.
В противном случае мы загружаем файл представления индекса через функцию render .

Вы можете задаться вопросом, где обрабатывается наша проверка, так как мы сделали это в контроллере в CodeIgniter. В Rails мы размещаем правила внутри Модели.
Когда Rails пытается вставить данные в базу данных (например, с помощью @shout.save ), Модель автоматически проверит данные на соответствие нашим правилам, прежде чем пытаться их сохранить. Таким образом, если проверка не @shout.save , то @shout.save вернет значение «false», представление будет перезагружено и отобразятся сообщения об ошибках.

Внутри модели Shout вставьте следующее, прежде чем мы определим self.all_shouts :

1
2
3
validates_presence_of :message
validates_length_of :name, :within => 1..255
validates_format_of :email, :with => /^[a-z0-9_.-]+@[a-z0-9-]+\.[az.]+$/i

В истинном стиле Ruby правила проверки читаются почти как естественный английский. В строке 1 мы гарантируем, что «сообщение» существует.

Далее мы проверяем длину поля ‘name’ — оно должно быть от 1 до 255 символов. 1..255 определяет диапазон. Например, мы можем определить диапазон от 10 до 15 с 10..15 .

Наконец, мы проверяем отправленное письмо в формате адреса электронной почты с использованием регулярного выражения. По сути, отправленное письмо должно состоять из пяти частей:

  1. Строка, содержащая комбинацию букв, цифр, подчеркивания, полной точки или дефиса;
  2. Символ;
  3. Строка, содержащая комбинацию букв, цифр или дефиса;
  4. Точка;
  5. Строка, содержащая комбинацию букв или дефис.

Теперь нам просто нужно отобразить сообщения об ошибках / успехе в представлении (см. Выше). Добавьте следующее в верхней части файла представления индекса:

1
2
<%= error_messages_for :shout, :header_message => nil, :message => nil %>
<%= ‘<p class=»success»>’ + flash[:notice] + ‘</p>’ if flash[:notice] %>

В первой строке мы отображаем любые сообщения об ошибках для формы. Мы устанавливаем :header_message и :message в nil (Ruby использует ‘nil’, PHP использует ‘null’), чтобы остановить функцию, отображающую нормальные сообщения, которые она отображает (нам просто нужны сообщения об ошибках).

Вторая строка отображает наше успешное сообщение. Обратите внимание на if flash[:notice] note if flash[:notice] в конце строки. Это гарантирует все, прежде чем он попытается отобразить, если существует уведомление вспышки.
Очевидно, мы могли бы также сделать следующее; однако это имело бы тот же эффект:

1
2
3
<% if flash[:notice] %>
  <%= ‘<p class=»success»>’ + flash[:notice] + ‘</p>’ %>
<% end %>

Попробуйте, он должен функционировать точно так же, как версия CodeIgniter, но с гораздо меньшим количеством кода (который также намного легче читать!)

CodeIgniter:
Контроллер: 31 линия
Модель: 33 линии
Вид: 69 строк
Всего: 133 строки

Рубин на рельсах:
Контроллер: 19 линий
Модель: 11 линий
Просмотр: 64 строки
Всего: 94 строки

Хотя это руководство, возможно, сделало процесс разработки приложения на Rails слишком сложным, оглянуться назад на свой код и посмотреть, насколько все просто!

Если это руководство вызвало у вас интерес к Ruby и Ruby on Rails, я настоятельно рекомендую приобрести копию Rails для разработчиков PHP , гибкую веб-разработку с использованием Rails и / или программирование Ruby от программистов Pragmatic.

Теперь иди! Отправляйся исследовать мир Rails!