вторник, 2 декабря 2008 г.

Lorem Ipsum Dolor....

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

Дело в том, что для проверки шрифтов, отступов и т.д., то-есть правильности верстки, принято заполнять страницу большыми фрагментами текста. Это нужно для того чтобы посмотреть как будут вести себя дом-элементы содержащие текст в реальной работе. Использовать что-то типа: "...Тест Тест Тест Тест Тест Тест...." не есть правильно, так как нужно испоьзовать сбалансированый текст, с правильным распределением пробелов, знаков пунктуации, а также длины слов. Также замечено, что при таких проверках важно чтобы смысл текста не отвлекал тестера от работы. Идеальным текстом является Lorem Ipsum.

Lorem Ipsum - это текст-"рыба", часто используемый в печати и вэб-дизайне. Lorem Ipsum является стандартной "рыбой" для текстов на латинице с начала XVI века. В то время некий безымянный печатник создал большую коллекцию размеров и форм шрифтов, используя Lorem Ipsum для распечатки образцов. Lorem Ipsum не только успешно пережил без заметных изменений пять веков, но и перешагнул в электронный дизайн. Его популяризации в новое время послужили публикация листов Letraset с образцами Lorem Ipsum в 60-х годах и, в более недавнее время, программы электронной вёрстки типа Aldus PageMaker, в шаблонах которых используется Lorem Ipsum.

Привожу фрагмент текста из 5 абзацов, который можно использовать в работе:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sed lectus feugiat tortor tincidunt iaculis. Integer malesuada metus laoreet lectus. Donec dictum lobortis libero. Aenean nibh orci, ullamcorper eu, convallis ut, egestas quis, eros. Quisque pellentesque orci eu arcu. Proin urna nisi, accumsan sit amet, condimentum vel, ultricies ac, tellus. Integer fermentum, metus a feugiat vestibulum, urna eros lacinia urna, pulvinar blandit libero sem in neque. Etiam rhoncus. Sed urna. Aliquam consequat, nibh sit amet fringilla dapibus, urna tellus elementum quam, quis tristique quam velit et diam. Nam eget tellus vel tortor varius consequat. Aliquam auctor posuere mi. Pellentesque sit amet ipsum. Nam libero massa, venenatis vel, dapibus eget, lacinia a, erat.

Donec rhoncus sodales tellus. Vestibulum iaculis vehicula justo. Maecenas non dui in nunc egestas gravida. Cras mattis. Integer turpis mauris, pharetra id, feugiat a, elementum et, neque. Etiam purus. Mauris tincidunt, ipsum in sollicitudin consectetur, est nulla porttitor erat, sed blandit lorem erat eget dui. Curabitur ante lectus, mollis sit amet, auctor et, faucibus non, tellus. In commodo. Morbi nibh. Aenean eget sapien eu dolor porttitor auctor. Nullam elementum urna eget tellus. Mauris porta rutrum elit. Morbi eu tellus. In odio. Suspendisse potenti. Nam convallis lacus sit amet libero. Phasellus sem. Etiam augue mi, eleifend in, dapibus sed, ullamcorper vitae, orci.

Donec auctor, lacus et porta varius, lectus ligula ullamcorper augue, in faucibus libero turpis sed dolor. Nam vulputate tortor. Aliquam tempus ante ut tortor. Sed venenatis pretium purus. Curabitur rhoncus magna eget leo. Nunc blandit leo a dui. Etiam ut lectus sit amet turpis dictum luctus. Nunc sed neque non magna placerat placerat. Nam accumsan consequat nunc. Nulla viverra malesuada dui. Donec convallis ante vitae nulla. Duis placerat blandit nunc.

Suspendisse nunc velit, tincidunt eget, accumsan quis, placerat et, arcu. Aliquam erat volutpat. Aenean eu nulla. Donec dignissim, purus nec porta blandit, justo nunc blandit lectus, eu rutrum eros justo vel tortor. Nullam tortor nisl, cursus et, pellentesque ac, ornare ut, orci. Nunc leo. Suspendisse potenti. Pellentesque tristique, magna et porttitor vestibulum, ipsum dui egestas dui, eget accumsan erat ipsum id ante. Morbi ante purus, mollis et, tincidunt id, condimentum posuere, ante. Nulla ullamcorper bibendum metus. Integer ut diam. Donec ullamcorper orci. Sed porttitor, odio non porta faucibus, mi turpis aliquet nisl, vitae euismod dolor felis non eros. Quisque sit amet est sit amet dui ullamcorper lacinia. Aliquam tempus, magna sit amet lacinia lacinia, diam risus malesuada pede, et aliquam felis dui at nulla. Donec diam mi, sollicitudin nec, egestas eget, posuere in, nibh. Proin sit amet dui eget tellus blandit imperdiet. Nullam libero erat, ornare vel, lacinia quis, venenatis sit amet, massa. Sed leo enim, mattis sed, placerat id, venenatis eu, diam. Sed est.

Aliquam blandit. Cras sem. Aenean dictum mauris sit amet pede. Nam eu lectus. Mauris a nisl nec felis interdum pharetra. Maecenas non neque sed neque malesuada sagittis. Suspendisse potenti. Suspendisse condimentum pulvinar nisl. Nunc mi elit, facilisis sed, tempor ac, tincidunt ac, justo. Aliquam dui. Donec neque. Cras neque tortor, sagittis id, consequat sit amet, dapibus quis, magna. Pellentesque id metus ac diam accumsan ullamcorper. Nulla facilisi. Phasellus sit amet neque. Vivamus ac sapien. Sed faucibus urna vel sem. Ut ipsum.




пятница, 14 ноября 2008 г.

Что лучше Ruby или PHP? Или PHP Vs Ruby on Rails

Именно этот вопрос я недавно увидел на каком-то форуме :). Хочу немного помочь в нем разобраться. Впринцыпе хороший сайт, грамотный программист сделает и там и там...
Но..В ПХП есть куча фреймворков, написанных разными людьми с разным уровнем, что выбирать или может написать свой - дело только программиста. В Руби есть замечательный фреймворк, в народе именуемый - Рельсы (Rails), который настолько облегчает разработку, настолько мощный, что скорость разработки увеличивается колосально. Его использует огромное количество програмеров, он отлично оттестирован.
Главные изюминки Ruby on Rails, это:
  1. Сам язык руби, ну уж очень удобный
  2. ActiveRecord - прослойка для работы с любыми БД
  3. MVC архитектура и жесткая привязка кода по папках - искать нужный код просто прелесть
  4. Сильно развитое тестирование (юнит тесты, функциональные, интеграциооные тесты, мок-обьекты, RSpec,...)
Напоследок скажу, человек хоть немного поработав на Ruby on Rails никогда в жизни не задаст вопрос - "А чем это же лучше чем ПХП".

Так что пробуйте товарищи программисты, пробуйте и вы ОЧЕНЬ много для себе откроете нового.

Как итог, сам задам вам вопрос: "Что удобнее, ехать из Киева в Москву велосипедом, или поездом??? Причем неважно на каком уровне вы владеете велосипедом" :)


вторник, 11 ноября 2008 г.

Работающий пример проксирующего скрипта

Реальный работающий прокси-скрипт, для примера из прошлой статьи

include $_SERVER["DOCUMENT_ROOT"]."/common/define.php";
$file=($_GET[file]);
$file = ROOT."/shared".$file;
if(isset($file)){
  $fl = fopen("log_proxy_new.txt","a");
  fwrite($fl,$file."\n");
  $type = substr($file,strlen($file)-3,3);
  if($type=="css"){
      header('Content-type: text/css');
   }else if($type==".js"){
      header('Content-type: application/javascript');
   }
   readfile($file);
}
fclose($fl);
exit;
?>

пятница, 7 ноября 2008 г.

Вынести FCKEditor выше DOCUMENT_ROOT

Для того чтобы вынести FCKEditor выше рута, пришлось немного попотеть, потому хочу облегчить задачу тем кто захочет сделать подобное. Идея вынести редактор возникла по простой причине, допустим, нас есть CMS, на которой настроена туча сайтов. Возникла мысль все общее для всех сайтов вынести наружу, и оформить в отдельном хранилище в форме ядра.

Польза вынесения редактора: вышла новая версия редактора, а старая нас не совсем устраивает (например вылезает баг), а у нас уже есть десяток сайтов на одной основе. В таком случае придется настраивать редактор 10 раз в каждом сайте - согласитесь, трудоемкая задача.

При настройке редактора(FCKEditor), нужно обязательно задать $this->BasePath в файле fckeditor_php5.php. Это путь относоительно которого должен работать редактор, он ОБЯЗАТЕЛЬНО должен быть относительно DOCUMENT_ROOT.

Как же обойти проблему??Самое оптимальное решение было найдено, привожу его вам:

В корне проекта создадим условие фильтра через modrewrite в.httaccess + проксирующий скрипт, который будет обрабатывать все пути доступа к FCKEditor и перенаправлять их куда надо. Причем конфигурационный путь будет вида: $this->BasePath = "http://".$_SERVER[SERVER_NAME].'/tools/fckeditor/' ;
Тоесть, мы не нарушаем идеологию настройки путей редактора.

Пример (работающий) проксирующего скрипта:

--------proxy.php:

";
if(isset($file)){
$file = ROOT."/tools/fckeditor/".$file;
$type = substr($file,strlen($file)-3,3);

if( $type=="php"){
include $file;
}else{
...

}

}

?>

Для того чтобы прокси-скрипт работал, необходимо чтобы все url которые идут к редактору, приходили на прокси посредством Get метода. Для этого в корне сайта положим в файлик httacces следующию дерективу для ModRewrite, который будет вырезать путь после tools/fckeditor/ и передавать в прокси-скрипт.

-----.httacces:

RewriteRule ^tools/fckeditor/(.*)$ /proxy.php?file=$1 [L]


В самом редакторе достаточно поставить "правильный" путь к нему, относительно рута.

---------fckeditor_php5.php

public function CreateFCKeditor($instanceName, $width, $height)
{
$this->InstanceName = $instanceName ;
$this->BasePath = "http://".$_SERVER[SERVER_NAME].'/tools/fckeditor/' ; <-- тут $this->Width = $width ;
$this->Height = $height ;
return $this->CreateHtml() ;
}

Особенности работы $_SERVER[HTTP_REFERER] в IE7

Столкнулся недавно с проблемкой, которая заняла пару часов мое разработки, так как отлавливалась долго. Если вы имеете сценарии на php где используете глобальную переменную среды $_SERVER[HTTP_REFERER] , то вы поимеете проблемы.

Проверено лично: данная переменная отрабатывает корректно в Мозиле, Опере и возвращает неадекватное значение в ИЕ7. Избегайте ее использование так как часто результатом будет пустая строка.

Для людей не стыкавшихся с проблемой - $_SERVER[HTTP_REFERER] - возвращает адрес страницы с которой мы пришли

понедельник, 27 октября 2008 г.

Задать статус группе радио кнопок в зависимости от перекючателя

Возникла задача сделать доступными/недоступными группу радио-кнопок в зависимости от состояния чекбокса. Мысль использовать jquery пришла сразу, красота код неоспорима (хотя можно было бы просто Джава Сриптом пройтись по элементам формы):

У нас есть checkbox с id="main_default", тогда код будет следующий:

function Select(){
   $(":radio").attr('disabled', $("#main_defalt").attr('checked'));
}

среда, 22 октября 2008 г.

Особенности работы с mysql_fetch_array в PHP

При создании метода в класе доступа к БД, часто необходимо выбрать только первую запись, при этом метод вернет хеш. Но если запрос типа - "SELECT count(*) FROM users", то тут надо вернуть просто переменную.

Решение может быть следующие:

 function select_first($sql){
          $sql.=" LIMIT 1"  ;
          $sth = $this->execute($sql);
          $num = ($sth?mysql_num_rows($sth):0);
          if ($num == 1){
             $row = mysql_fetch_array($sth);
             if(sizeof($row)==2){
                 return $row[0];
             }else{
                return $row;
             }             
          }else{
             return false; 
          }   
        }         

Ключевым будет блок:

 if(sizeof($row)==2){
                 return $row[0];
             }else{
                return $row;
             }             

Здесь мы используем свойство  mysql_fetch_array, зная что возвратится хеш+просто массив. Например если бы мы вызвали метод с таким запросом: 

$res=select_first("SELECT name FROM users WHERE id=1");

то если допустим такой юзер есть и его имя Sergey, то:

$row['name'] = "Sergey" 
$row[0] ="Sergey"

SizeOf($row) = 2 в случае возврата 1 поля. Потому мы всегда при необходимости возвратим хеш или просто переменную.

Это решение не претендует на полноту, так как класы по работе с БД сейчас довольно продвинутые (для ПХП), просто мне пришлось работать с проектом, где работа с БД реализована довольно примитивно. Но может это кому-то понадобится :)


понедельник, 13 октября 2008 г.

Бета-тестирование РНР 5.3

Компания Zend Technologies объявила о выпуске новой бета-версии популярного языка серверных сценариев для написания веб-приложений PHP 5.3 в октябре этого года. В новой версии реализована сборка мусора в памяти, поддержка пространств имен и упаковка PHP-приложений в архивы формата PHAR. Кроме того, серьезно оптимизировано быстродействие технологий PHP на платформе Windows за счет применения современных компиляторов Microsoft, а также современных компонентов других производителей для поддержки XML, операций с графикой и доступа к БД. 


Поддержка пространства имен в PHP 5.3 позволяет компоновать PHP-приложения из кода, полученного из разных источников. Этот механизм помогает сделать PHP-приложения по настоящему модульными, а также применять одновременно несколько технологических платформ, таких, как Zend PHP и PEAR (PHP Extension and Application Repository).

Новый механизм сборки мусора в памяти помогает платформе PHP 5.3 использовать память с максимальной эффективностью. Благодаря этому механизму подолгу работающие PHP-сценарии избавлены от утечек памяти. Упаковка PHP-приложений в архивы формата PHAR (PHP Archive) серьезно облегчит распространение и развертывание приложений. Концепция PHAR полностью аналогичная принципам, заложенным в давно известный формат файлов JAR (Java Application Archive), используемый для распространения Java-приложений.

Также в комплект поставки PHP 5.3 будут включены различные дополнительные компоненты, в том числе клиентская библиотека для интеграции PHP с СУБД MySQL. По заверениям разработчиков, приложения PHP 5.2 должны сохранить работоспособность в среде PHP 5.3. Также расширена поддержка интернационализации приложений – библиотека ICU (International Components for Unicode) поможет создавать полностью многоязычные приложения.

Хотя ранее версию PHP 5.3 планировалось выпустить до конца 2008 года, сейчас сроки выпуска перенесены на первый квартал 2009 г. Вместе с финальной версией PHP 5.3 будет доступна открытая платформа WSF/PHP (Web Services Framework) для полной реализации сервисно-ориентированной архитектуры SOA (Service-Oriented Architecture) в среде PHP. Компания WSO2, которая занимается разработкой и поддержкой WSF/PHP, обещает реализовать полноценные возможности для создания приложений электронной коммерции.

четверг, 25 сентября 2008 г.

Детально о миграциях. Создание таблиц. Добавление полей.

Как уже было сказано в статье Миграции. Что такое миграции? после создания миграции, в ней присутствует всего два метода - self.up i self.down. Первый вызывается при выполнении текущей миграции в рамках проведения всех миграций (rake db:migrate), второй срабатывает когда делается откат текущей миграции.

Соответственно метод self.down нейтрализирует все то что было сделано методом self.up. Если мы в self.up добавляем новое поле то в self.down мы его должны удалить, если создаем таблицу - то при откате должны ее удалить, если переимнновываем или меняем тип поля, то при откате все должно вернутся на круги своя.

Тепер детально рассмотрим какие действия мы можем делать с БД в текущих методах. Сначала начнем с более простых действий, а закончим более сложными.

Условимся, что работать ми будем с таблицей пользователей, соответственно модель - User. Я буду попарно давать действия и противодействия (для отката).

Добавление нового поля

def self.up
add_column :users, :name, :string
end

Сначала указывается таблица, далее указывается имя поля, потом указывается его тип. Весь список используемых типов можно посмотреть в моей статье: Типы данных в миграциях для разных СУБД

Удаление нового поля

def self.down
remove_column :users, :name
end

Сначала указываем таблицу, потом имя поля которое нужно удалить

Переименование колонок

def self.up
rename_column :users, :name, :user_name
end

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

Обратное переименование колонок

def self.down
rename_column :users, :user_name, :name
end

для отката достаточно вызвать то же метод, только поменять поля местами

Изменение типа поля

def self.up
change_column :users, :age, :integer
end

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

Обратное изменение имя поля

def self.down
change_column :users, :age, :string
end

Для обратного изменения достаточно указать старый тип. Но иногда бывает так, что нада заблокировать возможность отката, например если у нас логика приложения будет жестко привязана к тому что тип поля целый. Тогда в Рельсах используется специальная конструкция которая запрещает откат даной миграции:

def self.down
raise ActiveRcord::IrreversibleMigration
end

Следующим большим разделом будут - Таблицы

Создание таблицы

def self.up
create_table :users, * do |table|
table.column :name, :string, **
table.column :age, :integer
end
end

* - здесь могут указыватся дополнительные опции для создания таблицы:

:force=>true/false - удалать таблицу если уже существует таблица с таким именем
:temporary=>true/false - промежуточная таблица(существует до дисконекта с базой)
:option=>"same opions", например: "auto_increment = 25" - дополнительные SQL опции
:primary_key=>:field_name - если нада задать имя поля отличное от дефолтного ID
:id=>false - если нужно создать таблицу без первичного ключа

** - здесь и в конце каждого объявления поля могут быть дополнительные опции:

:null => true/false - признак того, может ли поле быть null
:limit => field size - максимальный размер поля
:default => default value - значение поля по-умолчанию
В table.column указывается имя поля, тип поля

Удаление таблицы

def self.down
drop_table :users
end
Тут я думаю все понятно :)

Создание/удаление индексов

add_index :users, :name - Для создания индекса указываем таблицу и имя поля

remove_index :user, :name - Для удаление индекса указываем таблицу и имя поля

Типы даных в миграциях для разных СУБД

Кликните на картинку для более детального просмотра

пятница, 19 сентября 2008 г.

FireFox 3.1 доступна Бета-версия

Как и анонсировалось, ФФ выпустил бета-версию нового усовершенствованного браузера под порядковым номером 3.1. Теперь все поклонники ФФ смогут скачать броузер для тестирования - по этой ссылке. Правда пока интерфейс только на английском, но для истинных поклонников это думаю не помеха.

Разработчики Mozilla произвели серию новых оптимизаций JavaScript движка Firefox, разрабатываемого под кодовым именем SpiderMonkey. Внесенные изменения позволили увеличить скорость выполнения некоторых скрптов в 20-40 раз. Новые "tracing" оптимизации, с реализацией нового JIT-компилятора (Just-In-Time), интегрированы в дерево исходных текстов firefox.

Суть "tracing" оптимизации в сохранении плана выполнения скрипта и в последующем использование бинарного кода при выполнении подобных блоков. При этом происходит преобразование циклов и сложных методов в вид линейного потока инструкций.

Основные нововведения:
  • Drag and Drop между IE и Firefox
  • Поддержка технологии web worker threads
  • Новый селектор для создания Aero-style “glass” в XUL Initial Glass support
  • Поддержка CSS 2.1 свойств: ::before, ::after и white-space:pre-line
  • Поддержка CSS 3 свойств: -moz-border-image, word-wrap: break-word, text-shadow, box-shadow и column-rule
  • Улучшенная производительность(обещают в 22 раза)
Благодаря включенной в «Firefox 3.1» поддержке открытого видеокодека «Ogg Theora» для просмотра контента в соответствующем формате пользователям больше не придется загружать специальный плагин. Другим важным изменением в новой версии браузера является поддержка тега video для интеграции видеоматериалов в веб-страницы.

Добавлю еще один момент с которым столкнулся после установки - также как и в ФФ3, когда я открываю страничку www.gmail.com, то страничка с почтой уменьшена в несколко раз и читать что-либо там невозможно... В Google Chrom все выглядит нормально... Обидно что есть такой недочет, просто использую восновном только ФФ в повседневности.

вторник, 16 сентября 2008 г.

Сортировка в find. Зачем нужны conditions

Для того чтобы найти что-то в БД используется метод Find(из фреймворка ActiveRecord), который имеет следующий вид:

result=
User.find(:all/:first/:last,
:conditions=>"some conditions",
:order=>"some order",
:limit=>"count records in result")


:all/:first/:last - альтернативы поиска, разделены косой чертой чисто схематически, на самом деле для любого запроса испольовать разрешено только один из параметров. Соответственно они указывают что вернуть в запросе - все записи/первую/последнюю запись.

:conditions=>"some conditions" - это условия выборки, например:
:conditions=>"id = 1 and name='some name'"
или
:conditions=>["name= ? and lastname = ? ", name, lastname] - параметры передаются как Хеш.

:order=>"some order" - условие сортировки, например:
:order=>"name, age DESC" - сортируем сначала по имени(по алфавиту, параметр ASC можно опускать, так как это сортировка по-умолчанию), потом сортируем по возрасту, по
убыванию(указать надо явно).

:limit=>"count records in result" - количество возвращаемых записей, например:
:limit=>"10"

Дополнительные параметры добавлю в статью позже, если она будет пользоватся интиресом у читателей (:joins,:select,:offset,:from,:group,:lock,:readonly)

пятница, 12 сентября 2008 г.

Маленький глюк Google Chrome

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

Еще один глюк, точнее неудобство: Когда в Мозиле кликнуть кнопочку "Назад" зажав при этом Ctrl, то предыдущая страница открывается в новой вкладке, что очень удобно и я часто этим пользуюсь. В Google Chrome такой возможности не предвидели...

...да и без любимых плагинов Файрфоксных как-то одиноко....

понедельник, 8 сентября 2008 г.

Миграции. Что такое миграция?

Как уже было описано в предыдущих статьях, рельсы работают с Базой данных через ActiveRecord(обьектная прослойка между Бд і web-приложением), настройка производится в одном единственном файле конфигурации. Возникает логичный вопрос - мы создали базу, настроили конфиги, так как же нам создать структуру БД??

Ответ - миграции. Что же такое миграция и зачем они вообще нужны?

Миграция - это файл который содержит описание создания в БД таблиц и полей. Чтобы создать миграцию воспользуйтесь или консолью или меню вашей IDE. В консоли надо набрать - ruby script/generate migration add_a_new_table. "Add a new table" - название миграции, которое должно описывать действие с БД.

Содержимое файла(Как пример приведем код создания таблицы юзеров):


class CreateUsers < ActiveRecord
def self.up
      create_table :users do |table|
         table.column :username, :string, :null => false, :limit => 60

         table.column :password, :string, :null => false
     end
end
def self.down
     drop_table :users
end
end

Детальнее типы данных рассмотрим в следующих статьях.

Таким образом отдельные миграции содержат отдельную логику создания новых структур. Код после
def self.down нужен для того чтобы миграцию можно было "откатить назад". Все миграции складываются в отдельную папку и их имя файла начинается с цыфры которая показывает ее место в списке. Миграции исполняются строго по очереди. Из за того что предусмотрен откат - мы можем безболезненно вернутся в любое последнее стабильное состояние БД до изминения.

Благодаря тому что миграции хранятся в отдельных, легкочитаемых файлах - достаточно только загрузить их из SVN и проммигрировать - и каждый разработчик получит точную копию основной БД на свою машину. Нет необходимости делать SQL дампы, а потом руками переносить все в нашу локальную базу. Так же легко и закомитить миграции в репозиторий где проведя миграции (на сервере проводяться в автоматичном режиме) мы внесем изминения в нашу рабочую БД.

четверг, 4 сентября 2008 г.

Google Chrome - обзор нового браузера

Гугль анонсировал выход в свет нового браузера, в котором впервые реализован механизм многопоточности, вернее многопроцессорности - на каждую вкладку свой процес, тоесть если где-то у вас зависнет ЯваСкрипт - то зависнет только 1 владка, а не весь браузер.

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

Детальную информацию можно посмотреть тут http://unno.ru/chrome/

Закачать браузер можно здесь: закачка

понедельник, 28 июля 2008 г.

Простая выборка записей через метод Find. Кратко о Conditions.

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


































# name last name age create_date updated_at
1 John Doe 31 29.07.2008 29.07.2008
2 Sergey Saenko 23 29.07.2008 29.07.2008
3 Ivan Petrenko 25 29.07.2008 29.07.2008


Как же работает с SQL используя ActiveRecord?

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

User.find(1) - результатом такого запроса будет первая запись нашей таблицы, которая соответствует пользователю John Doe, результатом выполнения запроса будет обьект класа User.
Таким образом, если метод find() принимает в качестве параметра число, то он будет искать запись, ІD которой будет соответствовать параметру.
User.find(:all) - вернет коллекцию єкземпляров класса User. Согласно переданому параметру - выберет все записи из таблицы.
User.find(:first), и по аналогии User.find(:last) - эти два запроса соответственно вернут первого и последнего зарегистрированного пользователя в системе.


При генерации любой модели, независимо от полей таблицы заданных в миграции - в автоматическом режиме создаются 2 дополнительных поля:
create_date и updated_at которые имеют тип дата/время. Оба поле заполняется автоматически при создании записи(дата создания и дата обновления сначала совпадают), но второе поле автоматически изменяется при любой модификации записи.


Так к чему же я это все писал - при любой выборке коллекции записей, данные будут отсортированы как-раз по полю create_date (если порядок сортировки не задан в явном виде). Таким образом я точно знаю что User.find(:first) вернет первый созданный обьект, а User.find(:last) соответствует последнему созданному экземпляру User.


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


Для того чтобы задать параметры выборки используется метод :conditions, например:
User.find(:all, :conditions=>"age=23") - выберет второго пользователя.
Чтобы передавать в :conditions параметры, можно использовать следующие способы:
name = "Sergey"

1. User.find(:all,:conditions=>["name=:name",{:name=>name}])

2. User.find(:all,:conditions=>["name= ?",name])

3. User.find(:all,:conditions=>"name=#{name}")

Рельса в любом из 3 случаев предварительно формирует для БД запрос, а потом его отсылает. Тоесть неверно говорить что что параметры на сервере в 1 и 2 передаются отдельно, а ядро запроса кешируется. В любом случае на сервер идет готовый запрос, проверял лично. По скорости работы выигрывает на сотые доли секунды 3 вариант, но его целиесобразно использовать только если мы не вставляем в параметры пользовательские данные. Для того чтобы предотвратить сюл-иньекции используйте вариант 1 или 2.

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


User.find(:all,:conditions=>["start_date= ? and end_date = ?",current,current])


а в 1 варианте можно сделать так:


User.find(:all,:conditions=>["start_date= :current_date and end_date = :current_date",{:current_date=>current}])


таким образом удается избавится от избыточности параметров


Сonditions- очень похожи на С-функцию sprintf, так что сложности с пониманием быть не должно. А само тело условия формируется аналогично постороения условия запроса через WHERE.

Ruby on Rails. Настройка database.yml

Эта статья является дополнением к моей предыдущей публикации "Как связана модель и таблица в БД?". Для того чтобы успешно работать с БД, ActiveRecord должен получить ее описание. Дальше он сам подберет нужный для работы драйвер. Программист не должен заботится о том с какой базой даных он работает, единственное что он должен сделать - правильно настроить конфигурационный файл подключения к базе и создать саму базу в соответствующем редакторе (например SQL Manager for MySQL).

Откроем папку с проектом и найдем там файл \config\database.yml. Первоначально он имеет вид (я опускаю комментарии. Комментарием считается строка которая начинается с символа "#"):


development:
adapter: mysql
encoding: utf8
database: blogger
username: root
password: 123123
host: localhost

test:
adapter: mysql
encoding: utf8
database: TestApplication_test
username: root
password:
host: localhost

production:
adapter: mysql
encoding: utf8
database: TestApplication_production
username: root
password:
host: localhost

Здесь описаны подключения к трем БД:
  • тестовой(на которой прогоняют тесты)
  • БД разработчика(которая подключается к локально установленному проекту разработчика)
  • БД production(которая включается в релиз готового проекта)
Рассмотрим детально подключение к произвольной БД, так как параметры везде одинаковые:
  1. adapter: mysql - указывается база данных с которой предстоит работать
  2. encoding: utf8 - выбирается кодировка хранимых данных (следите чтобы она совпадала с кодировкой самого проекта)
  3. database: TestApplication_production - имя уже созданной базы данных
  4. username: root - логин админа БД
  5. password: - пароль админа БД (если он не пустой)
  6. host: localhost - хост БД, localhost указывет на то что работать предстоит на локальной машине
Теперь вам предстоит создать тестовую(test) и девелоперскую(
development) БД и прописать соответствующие параметры в database.yml. Базу данных для продакшина(production) можно закомментировать, так как она понадобится только после завершения проекта или выхода первого релиза.

К выбору имени БД тоже есть некоторые соглашения. Если вы планируете назвать вашу БД к примеру "my_database", то к имени тестовой БД принято добавлять суфикс "_test", а к девелоперской - "_development". В результате получим my_database_test и my_database_development соответственно.




вторник, 22 июля 2008 г.

Как связана модель и таблица в БД?

Ну, давайте начнем. Модель - это класс, который предоставляет свои методы как интерфейс для работы с БД.

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

Нам не нужно создавать вручную ни таблицу, ни класс - рельса это сделает за нас. Достаточно для этого в консоли запустить генератор:
>ruby script\generate model User
в консоли генерируется список созданных файлов и папок:
> exists app/models/ - папка где хранятся все модели
> exists test/unit/ - папка для юнит-тестов
> exists test/fixtures/ - папка для фикстур
> create app/models/user.rb - файл модели
> create test/unit/user_test.rb - файл юнит-теста модели
> create test/fixtures/users.yml - файл где хрянтся фикстуры для модели
> create db/migrate - папка где хранятся миграции
> create db/migrate/001_create_users.rb - миграция для создания таблицы users

генератор создает нужные файли с шаблонным текстом для модели, функцональный тест, фикстуры. Нас пока будет интересовать только файл /app/model/user.rb - в котором и хранится наша модель. Он по-умолчанию содержит только обьявления класса(модели),
который наследуется от ActiveRecord - фреймворка для работы с БД

Генератор также создает в БД таблицу с именем users.

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

Для доступа к полю таблицы - используеться одноименный метод модели, например в таблице user есть поле name, то мы можем к нему обратиться как User.name

У вас возникает естественный вопрос: "Как модель знает какие поля есть у таблицы?"
Для того чтобы понять как ставиться в соответствие метод модели и поле базы - необходимо разобраться с миграциями, так как разгадка находиться в файле db/migrate/001_create_users.rb который создал наш генератор.

Подробно про о миграциях поговорим в следующей статье.


Немного терминологии:

Юнит-тест - это класс(тесты подробно рассмотрим позже) который привязывается к конкретной модели (имеет доступ ко всем ее методам), генерируется отдельно для каждой модели, манипулирует ее методами (может быть еще даже несуществующими), имитируя ее поведение заданое в спецификации. Основым инструментом для тестирования является утверждение(assert).

Утверждения могут быть разных типов, но общим для всех являеться сравнение уже известного параметра (согласно спецификации проекта) и параметра который возвращает модель в результате выполнения какого-либо метода.

Пример:утверждаем что количество юзеров в БД равняется 1:

def test_should_be_one_user_in_database
assert 1, User.count
end


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

Таким образом: еще не реализовав модель, мы можем задать ее поведение (которое хочет заказчик). В тех местах где тест будет "падать" мы будем знать какая конкретно, и где, возникает ошибка. Если над проектом работает команда - то написание тестов просто необходимо, они тестируют все важные узлы системы, и программист сразу сможет увидеть что его код что-то нарушил в системе - и сразу все исправит.


Фикстуры: это файлы которые содержат записи для конкретных таблиц (в формате yml) . Реально, для разработки нужно 2 базы данных - для разработки и тестовая.

В БД разработки храняться реальные данные разрабатываемого проекта, которые программист тестирует у себя в браузере и вводит через формы.

В тестовой БД
хранятся данные на которых проганяются тесты, и эти данные как-раз и подгружаются каждый раз в БД из фикстур.

Существует две БД для того, чтобы тестовые данные были у всех разработчиков одинаковые и независили от того какие данные в проекта у каждого разработчика

Ruby on Rails. Модель в контексте MVC архитектуры построения веб-приложений

Детальное описание применения MVC архитектуры в Рельсах я решил все-таки начать с модели. На то есть ряд причин:
  • литература, предложенная мной для быстрого старта в Релсах, уже позволяет читателю немного представить в голове основной алгоритм построения приложения
  • Контроллер использует для работы модель, а значит описание начнем именно с нее:
О чем здесь пойдет речь:
  1. Как связана модель и таблица в БД
  2. Краткий старт в ActiveRecord
  3. Запросы к БД, задание параметров, работа с БД через интерфейс модели
  4. Связывание моделей
  5. Методы модели, методы экземпляров модели
  6. Особенности работы метода with_scope, или как мержить параметры запроса?
Приведенный выше список является своего рода названиями разделов, каждый из элементов которого будет разбит и описан в отдельных подпунктах


четверг, 17 июля 2008 г.

Кратко о MVC

Подробно MVC можно посмотреть в интернете, информации полно. Моя задача не описать все еше раз своими словами, а показать как это все работает в Релсах.

Для новичков я вкратце опишу что же это такое (немного детальнее посмотрите тут). Главная задача шаблона проектирования - отделить код от представления данных, тоесть как в поговорке "мухи отдельно, котлеты отдельно".

MVC (Модель-Представление-Контроллер) шаблон проектирования cостоит из 3 основных компонентов:
  • Модель - объектная прослойка между хранилищем информации(в частном случае база данных), которая предоставляет интерфейс для работы с сохраненной информацией (поиск, выборки, апдейты, удаления), а также методы котрые занимаются всевозможной обработкой для конкретной модели. Для Ruby on Rails в основе любой модели лежит супер мощный фреймворк - ActiveRecord. Который предоставляет все возможныйе базовые методы для работы с данными.
    Каждая таблица в БД имеет свою модель, где описаны связи между разными моделями (связи осуществляются на уровне моделей, а не таблиц!), а также методы работы с данными для конкретной модели(например User)
  • Контроллер - это ваш посредник между броузером(представлением данных) и моделью(БД), который занимается перехватом всех событий которые возникают в процессе работы и дальнейшей их обработкой. Используя роутер(файл содержащий информацию о том как обрабатывать события и куда направлять данные) контроллер "знает" какому экшну какого контроллера передать реакцию на событие (например сабмит формы) . Контроллер можно представить себе в виде продавца-консультанта, который выслушав ваши пожелания проведет вас в нужный отдел магазина.
  • Представления данных (View) - это последний компонент МVС корый занимается отображением данных. В рельсах используется для этого RHTML - помесь HTML и Ruby - RubyHTML. Где возможно использования руби вместе с обычным штмл. Основная задача представления - отобразить данные которые сформировал контроллер в результате на запрос юзера. Здесь позволено только фильтровать данные пришедшее с контроллера, обработка запрещается(вынесена в контроллер)
Таким образом работу типового рельсового приложения можна описать используя такую схему:
Запрос пользователя(в броузере) -> Обработка события и вызов нужного экшна в контроллере(с передачей пользовательских параметров запроса) -> Обработка в контроллере используя для работы с БД нужные Модели -> формирование ответа и передача в Представление -> отбражение запроса в нужном формате и выдача юзеру через броузер


Логические выражения в Руби

На своем горьком опыте я убедился, что спецификацию языка программирования надо читать очень и очень внимательно, сегодня столкнулся с проблемой, которая забрала у меня целый час времени.
Если вы есть новичек в Руби, то запомните одну истину - для Руби and i &&, or i || имеют разные приоритеты, ВСЕГДА юзайте только && i ||.
Рассмотри маленький примерчик котрый легко воспроизвести в ИРБ:
>> a = 2
>> puts (a==2) and false
=> true !!!!

>> puts (a==2)&& false
=> false

вторник, 8 июля 2008 г.

Ruby on Rails and MVC

Я начинаю цикл статей, которые максимально доступно помогут разобраться в архитектуре ModelViewController (MVC) применимо к Ruby on Rails. Я не утверждаю что эти статьи есть эталон, но постараюсь покрайней мере дать вам мое виденье данного вопроса.

среда, 25 июня 2008 г.

Пишем парсер на Ruby on Rails

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

Часто таким образом забиваю тестовые БД, для того чтобы "поганять" систему на большой базе. Набирать и придумывать такую тестовую информацию - процес не из простых, и точно не из интересных.

Написать парсер на Ruby on Rails не составляет особого труда, так как существуют мощные библиотеки для этого, а также регулярные выражения в Руби - выше всяких похвал.

Для написания парсеров используется библиотека HPricot(здесь находится сайт с документацией и примерами), которая позволяет используя XPath систему поиска легко вытянуть нужную информацию.

Если кому нужно поправить знания XPath, то это легко можно сделать используя уроки XPath.

Если возникают проблемы с переводом английской документации - пишите в комментарии, постараюсь помочь.

Для того чтобы в Руби научится писать и использовать регулярные выражения, существует очень удобный и полезный сайт, где можно отдельно от кода тестировать рег.выражения. Советую его посетить и добавить себе в закладки, помогает в разработке, даже очень - Rubular

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

Продолжение следует....


вторник, 24 июня 2008 г.

Быстрый старт с Ruby on Rails

Я не буду писать то что уже написано - в этой вводной статье дам основные ресурсы, проверенные мной, для быстрого старта в Ruby on Rails, чтобы потом не возвращаться к самым азам.

Здесь выложу те ресурсы - которые надо обязательно посетить всем новичкам в Ruby on Rails.

Список ресурсов:
  1. http://ru.wikibooks.org/wiki/Ruby - учебник где кратко выложены основы самого Ruby
  2. http://www.realcoding.net/article/view/4383 - установка Рельс
  3. http://www.rsdn.ru/article/inet/rails.xml - первое веб-приложение на Ruby on Rails
  4. http://kolia.pp.ru/programming/060521_morev_rails/index.html - кратко описн процес написания веб-приложений на Рельсах(Ruby on Rails)
  5. http://www.gotapi.com/rubyrails - МЕГА полезный ресурс для разработчика, хелпер - который поможет вам найти информацию в любом вопросе касающимся Ruby on Rails
продолжение следует...

четверг, 12 июня 2008 г.

Мое первое впечатление от Ruby on Rails

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

Чтобы научится хорошо программировать, недостаточно только писать код и читать книги, нужно писать статьи о своих познаниях и достижениях. При написании статьи, приходится глубже рассматривать проблему, чтобы обьяснить суть вопроса читателю.

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