CRUD и генераторы скаффолдов
Начать данный пост хотелось бы со слов замечательного поэта:
Ночь, улица, фонарь, аптека,
Бессмысленный и тусклый свет.
Живи еще хоть четверть века -
Все будет так. Исхода нет.
Умрешь - начнешь опять сначала
И повторится все, как встарь:
Ночь, ледяная рябь канала,
Аптека, улица, фонарь.
Александр Блок.
10 октября 1912
CRUD — (англ. create read update delete — «Создание чтение обновление удаление») сокращенное именование 4 базовых функций управления данными — создание, чтение, редактирование и удаление.
http://ru.wikipedia.org/wiki/CRUD
Если вы повнимательней присмотритесь к своим приложениям, то наверняка сможете найти и у себя множество функций блоков кода, которые занимаются именно тем, что выполняют указанные действия над некоторой сущностью вашего проекта.
Например:
-Пост из вашего блога - создать, просматривать, редактировать, удалить.
-Альбом фотографий - создать , просматривать (увидеть все фото), редактировать, удалить.
-Фотография из альбома - создать (загрузить), просматривать, редактировать, удалить.
-Страница (в дереве страниц) - создать, просматривать, редактировать, удалить,
поднять вверх по дереву, поднять
вниз по дереву, перенести страницу и все дочерние в другой раздел.
Хм! Вы не поверите, но алгоритм создания, просмотра, редактирования, удаления - у всех объектов один и тот же.
Создание - получить данные для заполнения объекта, создать новую запись в таблице БД.
Просмотр - получить данные об объекте из БД по некоторому id, передать данные для отрисовки в шаблонизтор.
Редактировать - получить данные об объекте из БД по некоторому id, передать данные для отрисовки в шаблонизтор с формой редактирования.
Удалить - удалить объект из БД по id. Перенаправить пользователя на страницу со списком объектов.
Поскольку алгоритм действия для всех объектов одинаков - то не стоит тратить время для создания таких простых и однотипных операций - можно написать генератор кода, который по заданному имени объектов будут создавать сам создавать уже готовый код для управления объектами данного типа.
Кроме того, поскольку отображение списков объектов, форм редактирования, страниц просмотра в простейшем случае тоже очень похоже - то пожалуй ничего не стоит сделать программу, которая по по заданным именам полей и указанным типам данных будет сама создавать шаблоны для отрисовки.
Данная тема - давно отработана в rails - и существует несколько альтернатив по созданию кода для CRUD операций.
Скаффолды - Scaffolds (строительные лес
а, подмостки, то что помогает строить базовый административный интерфейс) -- общее имя генераторам которые занимаются формированием кода для CRUD операций
В среде rails есть свой стандартный генератор скаффолдов.
И так, я вызываю генератор скаффолдов:
#ruby script/generate scaffold BlogPost title:string description:string content:text position:integer
Он по заданным параметрам создает
1. Миграцию:
class CreateBlogPosts < ActiveRecord::Migration
def self.up
create_table :blog_posts do |t|
t.string :title
t.string :description
t.text :content
t.integer :position
t.timestamps
end
end
def self.down
drop_table :blog_posts
end
end
Выполнив миграцию - вы создадите в БД нужную таблицу для хранения данных об объектах данного класса.
Чувствуете?! В простейших случаях (а их большинство), Вы теперь можете забыть о средствах вроде: phpMyAdmin, работы в чистом сеансе sql, написания своих скриптов для изменений в БД.
2. Модель (программное представления об объектах БД в вашем приложении)
class BlogPost < ActiveRecord::Base
# тут пока пусто
# это просто класс унаследованный от ActiveRecord::Base
end
3. Контроллер (бизнес логику приложения)
class BlogPostsController < ApplicationController
# GET /blog_posts
# GET /blog_posts.xml
def index
@blog_posts = BlogPost.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @blog_posts }
end
end
# GET /blog_posts/1
# GET /blog_posts/1.xml
def show
@blog_post = BlogPost.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @blog_post }
end
end
# GET /blog_posts/new
# GET /blog_posts/new.xml
def new
@blog_post = BlogPost.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @blog_post }
end
end
# GET /blog_posts/1/edit
def edit
@blog_post = BlogPost.find(params[:id])
end
# POST /blog_posts
# POST /blog_posts.xml
def create
@blog_post = BlogPost.new(params[:blog_post])
respond_to do |format|
if @blog_post.save
flash[:notice] = 'BlogPost was successfully created.'
format.html { redirect_to(@blog_post) }
format.xml { render :xml => @blog_post, :status => :created, :location => @blog_post }
else
format.html { render :action => "new" }
format.xml { render :xml => @blog_post.errors, :status => :unprocessable_entity }
end
end
end
# PUT /blog_posts/1
# PUT /blog_posts/1.xml
def update
@blog_post = BlogPost.find(params[:id])
respond_to do |format|
if @blog_post.update_attributes(params[:blog_post])
flash[:notice] = 'BlogPost was successfully updated.'
format.html { redirect_to(@blog_post) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @blog_post.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /blog_posts/1
# DELETE /blog_posts/1.xml
def destroy
@blog_post = BlogPost.find(params[:id])
@blog_post.destroy
respond_to do |format|
format.html { redirect_to(blog_posts_url) }
format.xml { head :ok }
end
end
end
4. Шаблоны для отрисовки данных и форм (Вид)
index.html.erb
<h1>Listing blog_posts</h1>
<table>
<tr>
<th>Title</th>
<th>Description</th>
<th>Content</th>
<th>Position</th>
</tr>
<% @blog_posts.each do |blog_post| %>
<tr>
<td><%=h blog_post.title %></td>
<td><%=h blog_post.description %></td>
<td><%=h blog_post.content %></td>
<td><%=h blog_post.position %></td>
<td><%= link_to 'Show', blog_post %></td>
<td><%= link_to 'Edit', edit_blog_post_path(blog_post) %></td>
<td><%= link_to 'Destroy', blog_post, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New blog_post', new_blog_post_path %>
edit.html.erb
<h1>Editing blog_post</h1>
<% form_for(@blog_post) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_field :description %>
</p>
<p>
<%= f.label :content %><br />
<%= f.text_area :content %>
</p>
<p>
<%= f.label :position %><br />
<%= f.text_field :position %>
</p>
<p>
<%= f.submit 'Update' %>
</p>
<% end %>
<%= link_to 'Show', @blog_post %> |
<%= link_to 'Back', blog_posts_path %>
new.html.erb
<h1>New blog_post</h1>
<% form_for(@blog_post) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_field :description %>
</p>
<p>
<%= f.label :content %><br />
<%= f.text_area :content %>
</p>
<p>
<%= f.label :position %><br />
<%= f.text_field :position %>
</p>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', blog_posts_path %>
show.html.erb
<p>
<b>Title:</b>
<%=h @blog_post.title %>
</p>
<p>
<b>Description:</b>
<%=h @blog_post.description %>
</p>
<p>
<b>Content:</b>
<%=h @blog_post.content %>
</p>
<p>
<b>Position:</b>
<%=h @blog_post.position %>
</p>
<%= link_to 'Edit', edit_blog_post_path(@blog_post) %> |
<%= link_to 'Back', blog_posts_path %>
Поскольку я работаю с HAML - то я не поленился и написал свои простейшие скаффолды с формированием HAML шаблонов отображения.
Видео уроки формата Блог на Rails за 15 минут основаны на технике скаффолдов.
Такие же средства, как мне известно есть на большинстве современных платформ, типа django on pyhton.
С уважением к php сообществу, Илья Зыкин, Иваново 2009.