Этот сайт не наркоманов. Это сайт программистов. Здесь курят мануал.

Добро пожаловать на Пыху!

Логин:
Пароль:
 

Нет прописки? Зарегистрируйся!

Новости

Мы в твиттере!
Мы вконтакте!
Мы на яндексе!

Краснодарское время: 10 Февраль, 2012, 11:45:52

Страниц: [1]
Печать
Автор Тема: MVC и Ruby on Rails  (Прочитано 1947 раз)
0 Пользователей и 1 Гость смотрят эту тему.
killich    ↓ 
16 Август, 2009, 01:30:21
НЕ ХУЕТА! ХУЕТА!

Группа: Санитары

Карма: 20
Сообщений: 275
Сила слова: 7.27

Концепция MVC - Модель Вид Контроллер (Я предпочел бы название - Модель Контроллер Вид), это одна из базовых и самых удачных на данный момент концепций разработки ПО для web (и для большинства других программных продуктов).
 
Суть MVC заключается не в расположении файлов внутри проекта, не в их устройстве и не в программной реализации. С идеями MVC меня в 2006 году познакомил мой преподаватель программирования в университете, после чего в течение года я писал свою реализацию MVC на php, не опираясь ни на один программный продукт реализованный на MVC (просто было лень искать), а используя только понятую мною (причем, возможно, не самым правильным образом) идею.
 
Я был потрясен, когда многое из того, к чему я пришел самостоятельно я обнаружил в RAILS, что и послужило поводом срочного перехода на RAILS, поскольку изобретать свой велосипед просто надоело. =)
 
MVC утверждает (в очень приблизительном виде и моей интерпретации), что средства работы с БД (Модель), должны быть полностью отделены от программной логики (Контроллера). Кроме того, программная логика (Контроллер) получив необходимые данные от БД (посредством Модели) должны передать уже подготовленные данные средству отображения (Виду).
 
И так - общая схема такая.
 
1. Контроллер, согласно пришедшим от пользователя параметрам вызывает Модель (функции работы с БД).
 
2. Получив необходимые данные от Модели, Контроллер выполняет подготовку данных для Вида (выполняет формирование переменных и массивов, их преобразования и т.д.) передает готовые данные (массивы и переменные) в Вид.
 
3. Вид - это перемешка HTML кода + вставка переменных и логики отображения (например цикл, пробегающий по массиву и отрисовывающий его элементы в тегах h3). Фактически - Вид - это HTML шаблонизатор, в который поступают уже готовые данные из Контроллера.
 
И в чем же отличие от PHP? В чем красота? Ну.. Если вам попадались только PHP проекты устроенные согласно всем канонам MVC - вы очень счастливый человек. Да! MVC можно реализовать на любом языке, просто ROR устроен так, что программы иначе здесь не создаются.
 
В ROR практически исключены ситуации, когда в HTML коде присутствует обращение к БД через SQL, тут же производится разбор данных и их проверка, и тут же данные отрисовываются.
 
MVC и ROR разработчики заявляют - ПРОГРАММНОЙ КАШЕ - НЕТ! ДАЕШЬ КРАСИВЫЙ И ПРАВЕЛЬНЫЙ MVC КОД!
 

Модель (Model)
 

Модель - это средство работы с таблицами БД. Набор функций и средств создания записей в таблице БД, получения данных из таблицы, обновление данных и удаления записей из таблиц.
 
Модель в понимании RAILS это класс унаследованный от ActiveRecord::Base.
Что это значит? Хм. Попробуем разобраться.
 
Что же нам дает то, что существует некоторый класс унаследованный от ActiveRecord::Base?
 
ActiveRecord - это один из подходов работы с БД.
 
В Rails ActiveRecord подход реализуется в одноименной библиотеке работы с БД -> ActiveRecord.
 
Все в Rails подчинено соглашениям - в этом потрясающем фреймворке трудно найти сотню конфигурационных файлов - большинство настроек существует по-умолчанию, витает в воздухе и за счет своей логичности порою задаешь себе вопрос - а зачем вообще нужны конфигурационные файла в других системах. Я не знаю где это настраивается, но по умолчанию я бы настроил, что бы это работало, так как мне нужно - и ЭТО ДЕЙСТВИТЕЛЬНО РАБОТАЕТ ТАК КАК ТЫ ОЖИДАЕШЬ! без дополнительных настроек и конфигураций.
 
Вот и ActiveRecord задает набор таких соглашений. За счет чего нам легко и просто работать с БД. Рассмотрим пример:
 
Предположим, что у нас существует миграция:
 

Ruby
class CreateRoles < ActiveRecord::Migration
  def self.up
    create_table 'roles' do |t|
      t.string    'name'         # Английское имя роли
      t.string    'title'        # Название Роли
      t.text      'description'  # Текстовое описание Роли
      t.text      'settings'     # Настройки Роли
     
      t.timestamps
    end
  end
 
  def self.down
    drop_table 'roles'
  end
end

 
Миграции расположены в каталоге:
c:\ror_server\rails_apps\MY_SUPER_SITE\db\migrate\
 
Мы запустим выполнение миграции:
c:\ror_server\rails_apps\MY_SUPER_SITE>rake db:migrate
 
В результате в БД появится таблица roles в которой есть поля:
 
Ruby
-roles
  name
  title
  description
  settings
  created_at
  updated_at

Мы создаем файл с описанием класса МОДЕЛИ для работы с данной таблицей:
 
Ruby
class Role < ActiveRecord::Base
  # Здесь может быть много кода
  # Но пока что тут не будет ничего кроме
  # 3х строчек с комментариями
end

Все Модели приложения хранятся в каталоге:
c:\ror_server\rails_apps\MY_SUPER_SITE\app\models\
 
Если знания в области программирования достаточны, то легко понять, что от любого класса можно создать экземпляр (для того они и нужны эти самые классы)
 
Это значит, что в приложении мы сможем выполнить следующую команду:
 

Ruby
role= Role.new

 
Я надеюсь, что определение класса Role, мы еще не забыли?! =)
 
Я напомню - в этом классе нет ничего, кроме 3х строчек комментариев.
 
Однако класс Role унаследован от ActiveRecord::Base, а это значит, что ActiveRecord уже послал SQL запрос в БД и узнал, какие поля находятся в таблице с именем roles и автоматически создал необходимые переменные в классе Role.
 
Почему именно в таблице в именем roles???
 
Это очень просто - это негласное СОГЛАШЕНИЕ ActiveRecord и большинства элементов фреймворка - если класс Role, то логичнее всего предположить, что он связан с таблицей roles! Я бы лично сделал именно так! И создатель ActiveRecord тоже так же подумал! Ура!
 
Следовательно, я могу попробовать сделать следующее:
 

Ruby
role= Role.new
role.name= 'administrator'
role.title= 'Роль администратора'
role.description= 'В этой записи в таблице roles хранятся настройки админа'
role.settings= 'админ может все!'

 
Замечательно! И что дальше! А вот что! Мы выполняем волшебный метод ActiveRecord с названием SAVE
 

Ruby
role= Role.new
role.name= 'administrator'
role.title= 'Роль администратора'
role.description= 'В этой записи в таблице roles хранятся настройки админа'
role.settings= 'админ может все!'
 
role.save

 
В результате выполненных нами действий, мы создали программное отображение новой записи в таблице БД. Мы заполнили соответствующие поля и выполнили метод save. В результате чего в БД появилась новая запись.
Так мы, не используя SQL запросов можем работать с БД. 99% работы с БД в Rials производится через программное отображение записей таблицы БД.
 
При сохранении объекта role (выполнение функции role.save) ActiveRecord самостоятельно заполнил поля created_at и updated_at. Следить за изменением данных полей нам не требуется.
 

Модель (Выборка данных из БД) Метод Find
 

В приложении нам придется не только создавать записи, но в основном получать их, обновлять или передавать в Вид для отображения. Как же получить необходимые данные из БД? Кночно же, как и все в Rails - все очень просто.
 
Вспомним определение класса Roles:
 

Ruby
class Role < ActiveRecord::Base
  # Здесь может быть много кода
  # Но пока что тут не будет ничего кроме
  # 3х строчек с комментариями
end

 
Казалось бы - класс абсолютно пустой, но уже сам факт его существования и то, что он унаследован от ActiveRecord::Base нам вполне достаточно.
 
Всякий класс, унаследованный от ActiveRecord автоматически становится счастливым обладателем метода find, а помощью, которого можно выполнять большинство требуемых выборок из таблицы связанной СОГЛАШЕНИЯМИ с данным классом.
 
Предположим, что в таблице roles уже есть несколько записей:
(Что бы не засорять эфир - оставлены только некоторые поля)
 
Ruby
id |name                       | title                            | created_at            | updated_at
1  | administrator           | Администратор портала              | 2009-07-22 16:45:48    | 2009-07-22 16:45:48
2  | registrated_user        | Зарегистрированный пользователь    | 2009-07-22 16:45:48  | 2009-07-22 16:45:48
3  | guaranted_user_role       | Заверенный пользователь          | 2009-07-22 16:45:48  | 2009-07-22 16:45:48
4  | site_administrator_role | Администратор сайта              | 2009-07-22 16:45:49   | 2009-07-22 16:45:49

Так в приложении мы можем выполнить следующие манипуляции:
 

 
Ruby
# Найти все записи в таблице roles
roles= Role.find(:all)

Ruby
# Найти первую запись в таблице roles
roles1= Role.find(:first)

Ruby
# Найти все записи в таблице roles поле created_at в которых равно '2009-07-22 16:45:49'
roles2= Role.find_all_by_created_at('2009-07-22 16:45:49')

Ruby
# Найти все записи в таблице roles где created_at= '2009-07-22 16:45:49' И поле title= 'Администратор портала'
roles3= Role.find_all_by_created_at_and_title('2009-07-22 16:45:49', 'Администратор портала')

Ruby
# Найти все записи в таблице roles где created_at= '2009-07-22 16:45:49' ИЛИ поле title= 'Администратор портала'
roles4= Role.find_all_by_created_at_or_title('2009-07-22 16:45:49', 'Администратор портала')

 
После того как мы нашли некоторый массив записей или одну запись, мы можем выполнить над каждой записью некоторые действия и сохранить результат в БД.
 
Так например выше в переменную roles1 был отправлен результат поиска первой записи в таблице. roles1= Role.find(:first) Теперь можно изменить переменную roles1 и выполнив сохранение методом save - мы изменим запись в таблице БД.
 

 
Ruby
# Найти первую запись в таблице roles
# Изменить поле title
# Сохранить изменения в БД
 
roles1= Role.find(:first)
roles1.title= 'Изменил текст в этом поле'
roles1.save

 

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

Контроллер (Controller)
 

Контроллер фактически это файл со списком обработчиков действий для некоторого раздела сайта.
Так например контроллер Pages будет отвечать в проекте за все производимые над страницами сайта.
Контроллер Pages будет включать в себя обработчики действий (функции обеспечивающие работу пользователя на сайте).
 
Как правило базовый контроллер состоит из набора функций:
 
-index -  список всех объектов данного класса (как правило с логикой пагинации [перелистывание списка объектов по страницам] )
-show -   показ всех данных для одного объекта
-new -    отработка страницы для создания нового объекта
-create - алгоритм создания нового объекта
-edit -   отработка страницы для редактирования объекта
-update - алгоритм обновления объекта
-destroy- убить объект и перейти на какую нибудь страницу =) гыгыгыг!
 
Контроллер - контроллер, controller
Функция Контроллера - обработчик, action
 
После выполнения алгоритма внутри обработчика (action) данные передаются в файл отображения (Вид), который носит точно такое же имя как и обработчик. Так если был выполнен обработчик index, то все данные, которые получены в результате его выполнения поступают в файл отображения index.html.erb
ERB - это стандартный шаблонизатор Rails - именно тут и генерируется HTML код.
 
После выполнения некоторых действий, например destroy, как правило, не происходит отрисовки файла destroy.html.erb (такого файла вообще не существует), а происходит переадресация пользователя к другому действию контроллера - REDIRECT. [redirect_to(admins_users_url) - фактически переадресация на index]
 
Пример Контроллера построенного с помощью Скаффолда для администрирования объектов класса User.
Такой код обеспечивает весь набор действий CRUD для класса User, т.е. полное БАЗОВОЕ управление пользователями на сайте.
 
__Смотрим пример и находим места, где действия КОНТРОЛЛЕРА обращаются к БД, посредством класса МОДЕЛИ User__
Полученные данные сохраняются в переменных обозначенных через символ @ - благодаря чему носят глобальный характер и существуют до момента отрисовки в ВИДЕ.
Ruby

class Admins::UsersController < ApplicationController 
  # GET /users
  def index
    @users = User.paginate(:all,
                           :order=>"created_at ASC", #ASC, DESC
                           :page => params[:page],
                           :per_page=>6
                           )
                           
    respond_to do |format|
      format.html
    end
  end
 
  # GET /users/1
  def show
    @user = User.find(params[:id])
 
    respond_to do |format|
      format.html
    end
  end
 
  # GET /users/new
  def new
    @user = User.new
 
    respond_to do |format|
      format.html
    end
  end
 
  # GET /users/1/edit
  def edit
    @user = User.find(params[:id])
  end
 
  # POST /users
  def create
    @user = User.new(params[:user])
 
    respond_to do |format|
      if @user.save
        flash[:notice] = 'user успешно создано.'
        format.html { redirect_to(admins_user_path(@user)) }
      else
        format.html { render :action => "new" }
      end
    end
  end
 
  # PUT /users/1
  def update
    @user = User.find(params[:id])
 
    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = 'user успешно обновлено.'
        format.html { redirect_to(edit_admins_user_path(@user)) }
      else
        format.html { render :action => "edit" }
      end
    end
  end
 
  # DELETE /users/1
  def destroy
    @user = User.find(params[:id])
    @user.destroy
 
    respond_to do |format|
      format.html { redirect_to(admins_users_url) }
    end
  end 
end

 
ВИД (View)
 

Вид - это файлы отвечающие за отрисовку даннх в виде HTML.
Для каждого класса существует своя папка со своими VIEW файлами.
В файлы Вида приходят данные из Контроллера, внутри переменных обозначенных через символ @
 
Так например вид может получить от Контроллера переменную @users или @pages_tree
 
Стандартным шаблонизатором Rails является ERB - он очень похож на PHP видом записи.
HTML теги перемешаны с выводом данных из переменных контроллера:
 

Ruby
<div class="site_map">
    <div class="title">
  <img class="symbol" src="/images/basic/site_map.jpg" alt="" />Карта сайта</div>
    <div class="lm55">
 
    <%= show_map(@sections) %>
    <%= parse_site_map(@sections) %>
 
    </div>
</div>
 

Здесь:
 

Ruby
<%= show_map(@sections) %>
<%= parse_site_map(@sections) %>

 
Это вывод на экран результата 2х функций, которые в качестве параметра принимают переменные поступившие из Контроллера.
« Последнее редактирование: 16 Август, 2009, 01:30:21 от adw0rd » Записан
phpdude    ↓ 
15 Август, 2009, 08:28:23 , спустя
НЕ ХУЕТА! ХУЕТА!

я - ЭМО
Группа: в ухо

Карма: 339
Сообщений: 19713
Сила слова: 1.72

я бы Килич ахуенен, и я говорю это. ТЫ АХУЕНЕН!
 
но руби не люблю, поэтому сори даже читать не стал (
Спустя 7 секунд добавил
НО добавил в закладки ;)
Записан

забанен. могу забанить других, пишите в личку
BEER. Helping ugly people have sex since 1862.
killich    ↓ 
15 Август, 2009, 08:34:27 , спустя 6 минут 4 секунды
НЕ ХУЕТА! ХУЕТА!

Группа: Санитары

Карма: 20
Сообщений: 275
Сила слова: 7.27

Вот начну с сентября плановые уроки писать - и через полгода парабатю твой моск =)
Записан
rider-sx    ↓ 
15 Август, 2009, 08:39:27 , спустя 5 минут
НЕ ХУЕТА! ХУЕТА!

drmmmmmm
Группа: Адекваты

Карма: 32
Сообщений: 2718
Сила слова: 1.18

killich, соблазнил на руби...
а трой на жаву...
Записан

Страниц: [1]
Печать
 

Перейти в: