<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;D08ASXw6eyp7ImA9WxNUF0Q.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483</id><updated>2009-11-09T21:44:08.213+02:00</updated><title>Записки про Ruby</title><subtitle type="html">5.times { print "We *love* Ruby -- it's outrageous!" }</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://ruby-ua.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>90</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/blogspot/ruby-ua" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;DU4MRXY8eSp7ImA9WxNUF0o.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-3103519743780209399</id><published>2009-11-09T13:23:00.001+02:00</published><updated>2009-11-09T16:46:24.871+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-09T16:46:24.871+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="datamapper" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><title>Привіт, DataMapper!</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SvfpZb_wybI/AAAAAAAAEx4/V3B46l0dGjs/s1600-h/dm.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SvfpZb_wybI/AAAAAAAAEx4/V3B46l0dGjs/s320/dm.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;b&gt;DataMapper&lt;/b&gt; - це &lt;i&gt;ORM&lt;/i&gt; бібліотека (англ. &lt;i&gt;Object-relational mapping&lt;/i&gt;, &lt;i&gt;Обє'ктно-реляційна проекція&lt;/i&gt; - технологія, яка зв'язую бази даних з концепцією об'єктно-орієнтовного програмування, створюючи "віртуальну об'єктну базу даних"). &lt;i&gt;DataMapper&lt;/i&gt; написана на Ruby, і широко використовується у таких фреймворках як &lt;i&gt;Merb&lt;/i&gt; та &lt;i&gt;Sinatra&lt;/i&gt;. Вона була розроблена, щоб усунути недоліки бібліотеки &lt;i&gt;ActiveRecord&lt;/i&gt;, яка використовується в &lt;i&gt;Ruby on Rails&lt;/i&gt; по замовчуванню. &lt;i&gt;DataMapper&lt;/i&gt; слідує стандартам ORM-моделі: таблиці відображаються у вигляді класів, записи - у вигляді об'єктів, а стовпці - у вигляді властивостей цих об'єктів. Методи класу використовуються для здійснення операцій на рівні таблиці, а методи екземпляра здійснюють операції над окремими рядками.&lt;br /&gt;
Якщо в базі даних є таблиця з назвою &lt;i&gt;posts&lt;/i&gt; (записи), то наш застосунок матиме клас &lt;i&gt;Post&lt;/i&gt;. Рядки цієї таблиці відповідають об'єктам класу - конкретний запис представляється як об'єкт класу &lt;i&gt;Post&lt;/i&gt;. У межах цього об'єкту для отримання доступу до окремих стовпців і встановлення їм значення, використовуються властивості.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Інсталяція DataMapper&lt;/h2&gt;&lt;i&gt;DataMapper&lt;/i&gt; доступний через менеджер пакетів &lt;i&gt;Ruby Gem&lt;/i&gt;:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;gem install dm-core
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Якщо ви плануєте використовувати &lt;i&gt;DataMapper&lt;/i&gt; з базою даних, встановіть адаптер бази даних з проекту &lt;i&gt;DataObjects&lt;/i&gt;. В залежності від ваших уподобань, це може бути &lt;i&gt;do_mysql&lt;/i&gt;, &lt;i&gt;do_postgres&lt;/i&gt; або &lt;i&gt;do_sqlite3&lt;/i&gt;.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;gem install do_sqlite3
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
Давайте уявимо, що ми створюємо деякі моделі для застосунку блогу. Ми отримаємо їх просто і красиво. Перше рішення, яке потрібно ухвалити - які моделі нам потрібні. Очевидно нам потрібна модель для записів (&lt;i&gt;Post&lt;/i&gt;) і коментарів (&lt;i&gt;Comment&lt;/i&gt;). Також нам можуть знадобитися категорії (&lt;i&gt;Category&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
Для роботи з &lt;i&gt;DataMapper&lt;/i&gt; необхідно додати наступні рядки до нашого застосунку:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;require 'rubygems'
require 'dm-core'
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Перед тим, як зайнятися визначенням моделей, потрібно з'єднатися з базою даних:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# An in-memory SQLite3 connection:
DataMapper.setup(:default, 'sqlite3::memory:')
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# A file SQLite3 connection:
DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/the_database_name.sqlite3")
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# A MySQL connection:
DataMapper.setup(:default, 'mysql://localhost/the_database_name')
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# A Postgres connection:
DataMapper.setup(:default, 'postgres://localhost/the_database_name')
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
В нашому застосунку буде використовуватися база даних &lt;i&gt;SQLite3&lt;/i&gt; (яку потрібно встановити, якщо ви збираєтесь відтворювати приведений тут код). Якщо ви користуєтесь іншим сервером баз даних (наприклад, &lt;i&gt;MySQL&lt;/i&gt; чи &lt;i&gt;PostgreSQL&lt;/i&gt;), вам потрібно заздалегідь подбати про створення бази даних і надання повноважень користувачу.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Визначення моделей&lt;/h2&gt;Таблиця для моделі &lt;i&gt;Post&lt;/i&gt; повинна існувати в чистому вигляді, тому включаємо &lt;i&gt;DataMapper::Resource&lt;/i&gt;. Це вказує на те, що клас &lt;i&gt;Post&lt;/i&gt; є ресурсом &lt;i&gt;DataMapper&lt;/i&gt;(тобто описує записи в БД). У базі буде створена таблиця &lt;i&gt;posts&lt;/i&gt; і ми отримаємо методи для роботи з нею. Угода з іменуванням моделей - використовувати однину, а не множину. Але це лише угода, ви можете робити як бажаєте. Це означає, що в базі буде створена таблиця &lt;i&gt;posts&lt;/i&gt; і ми отримаємо методи для роботи з нею.&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Post
  include DataMapper::Resource

  property :id,         Serial
  property :title,      String
  property :body,       Text
  property :created_at, DateTime
  property :published,  Boolean, :default =&amp;gt; false

  default_scope(:default).update(:order =&amp;gt; [created_at.desc])
end

class Comment
  include DataMapper::Resource

  property :id,         Serial
  property :posted_by,  String
  property :email,      String
  property :url,        String
  property :body,       Text
end

class Category
  include DataMapper::Resource

  property :id,         Serial
  property :name,       String
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Всередині класу моделі викликається метод &lt;i&gt;property&lt;/i&gt; для кожної властивості. Він має два необхідних аргументи - ім'я і тип, а все інше не є обов'язковим.&lt;br /&gt;
Тип &lt;i&gt;Serial&lt;/i&gt; вказує на те, що властивість буде первинним ключем, тобто &lt;i&gt;AUTOINCREMENT&lt;/i&gt;(автоматично отримувати значення).&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;property :id,  Serial
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Властивість &lt;i&gt;created_at&lt;/i&gt; буде автоматично заповнюватися часом створення запису &lt;i&gt;TIMESTAMP&lt;/i&gt;(для цього необхідно підключити &lt;i&gt;'dm-timestamps'&lt;/i&gt;).&lt;br /&gt;
&lt;i&gt;DM-Timestamps&lt;/i&gt; забезпечує автоматичне оновлення властивостей &lt;i&gt;created_at&lt;/i&gt; або &lt;i&gt;created_on&lt;/i&gt; і &lt;i&gt;updated_at&lt;/i&gt; або &lt;i&gt;updated_on&lt;/i&gt;.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;property :created_at, DateTime
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Аргумент &lt;i&gt;:default&lt;/i&gt;, встановлює значення по замовчуванню для властивості.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;property :published,  Boolean, :default =&amp;gt; false
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
І нарешті&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;default_scope(:default).update(:order =&amp;gt; [created_at.desc])
&lt;/code&gt;&lt;/pre&gt;говорить нам про те, що записи по замовчуванню треба діставати впорядкованими за спаданням часу створення.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Доступні типи&lt;/h3&gt;&lt;i&gt;DM-Core&lt;/i&gt; підтримує наступні типи даних:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Boolean&lt;/li&gt;
&lt;li&gt;String&lt;/li&gt;
&lt;li&gt;Text&lt;/li&gt;
&lt;li&gt;Float&lt;/li&gt;
&lt;li&gt;Integer&lt;/li&gt;
&lt;li&gt;BigDecimal&lt;/li&gt;
&lt;li&gt;DateTime, Date, Time&lt;/li&gt;
&lt;li&gt;Object&lt;/li&gt;
&lt;li&gt;Discriminator&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Якщо включити &lt;i&gt;DM-Types&lt;/i&gt;, стають доступні наступні типи даних:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Csv&lt;/li&gt;
&lt;li&gt;Enum&lt;/li&gt;
&lt;li&gt;EpochTime&lt;/li&gt;
&lt;li&gt;FilePath&lt;/li&gt;
&lt;li&gt;Flag&lt;/li&gt;
&lt;li&gt;IPAddress&lt;/li&gt;
&lt;li&gt;URI&lt;/li&gt;
&lt;li&gt;Yaml&lt;/li&gt;
&lt;li&gt;Json&lt;/li&gt;
&lt;li&gt;BCryptHash&lt;/li&gt;
&lt;li&gt;Regex&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Асоціації&lt;/h2&gt;&lt;i&gt;Асоціації&lt;/i&gt; - це спосіб оголошення відносин між моделями. Вони надають ряд методів, які дозволяють створювати відносини та отримувати пов'язані моделі. У &lt;i&gt;DataMapper&lt;/i&gt; є декілька видів асоціацій.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Один до багатьох(One-To-Many)&lt;/h3&gt;Запис(&lt;i&gt;Post&lt;/i&gt;) потенціально може мати безліч коментарів(&lt;i&gt;Comment&lt;/i&gt;). Така прив'язка до запису обумовлюється тим, що кожен коментар містить посилання на ідентифікатор запису, якому він належить. Тому ми повинні налаштувати &lt;i&gt;one-to-many&lt;/i&gt; асоціацію між ними.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SvfwSRhdeCI/AAAAAAAAEyA/KRE5KK_1UG0/s1600-h/one-to-many.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SvfwSRhdeCI/AAAAAAAAEyA/KRE5KK_1UG0/s320/one-to-many.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Post
  has n, :comments
end

class Comment
  belongs_to :post
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Має і належить до багатьох(Has and belongs to many або One-To-Many-Through)&lt;/h3&gt;Запис може належати багатьом категоріям, і кожна категорія може містити безліч записів. Це і є прикладом зв'язку "&lt;i&gt;багато до багатьох&lt;/i&gt;", який також носить дивовижну назву "&lt;i&gt;має і належить до багатьох&lt;/i&gt;". Схоже на те, що кожна із взаємодіючих сторін містить колекцію елементів іншої сторони. Всередині БД зв'язки "&lt;i&gt;багато до багатьох&lt;/i&gt;" здійснюються з використанням проміжної об'єднавчої таблиці. У ній містяться пари зовнішніх ключів, які зв'язують дві задані таблиці.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_lXvcYH2YnAY/Svfw_xME_vI/AAAAAAAAEyI/9RYMRxPFxGI/s1600-h/many-to-many.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/Svfw_xME_vI/AAAAAAAAEyI/9RYMRxPFxGI/s400/many-to-many.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Categorization
  include DataMapper::Resource

  property :id,         Serial
  property :created_at, DateTime

  belongs_to :category
  belongs_to :post
end

class Post
  has n, :categorizations
  has n, :categories, :through =&amp;gt; :categorizations
end

class Category
  has n, :categorizations
  has n, :posts,      :through =&amp;gt; :categorizations
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Перевірка даних&lt;/h2&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;gem install dm-validations
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;i&gt;DataMapper&lt;/i&gt; дозволяє перевіряти дані до того, як вони будуть збережені до бази даних за допомогою так званих &lt;i&gt;валідаторів&lt;/i&gt;. Щоб зробити перевірку доступною для нашого затосунку, просто додамо рядок:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;require 'dm-validations'
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
У &lt;i&gt;DataMapper&lt;/i&gt; є два способи для перевірки властивостей у класі - ручна і автоматична.&lt;br /&gt;
&lt;br /&gt;
&lt;h3&gt;Ручна перевірка&lt;/h3&gt;Подібно до інших Ruby ORM, ми можемо викликати метод перевірки безпосередньо передавши йому ім'я властивості(або масив імен) для перевірки:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;validates_length :title
validates_length [:title, :body]
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
На даний момент доступні наступні перевірки:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;validates_present&lt;/li&gt;
&lt;li&gt;validates_absent&lt;/li&gt;
&lt;li&gt;validates_is_accepted&lt;/li&gt;
&lt;li&gt;validates_is_confirmed&lt;/li&gt;
&lt;li&gt;validates_format&lt;/li&gt;
&lt;li&gt;validates_length&lt;/li&gt;
&lt;li&gt;validates_with_method&lt;/li&gt;
&lt;li&gt;validates_with_block&lt;/li&gt;
&lt;li&gt;validates_is_number&lt;/li&gt;
&lt;li&gt;validates_is_unique&lt;/li&gt;
&lt;li&gt;validates_within&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;h3&gt;Автоматична перевірка&lt;/h3&gt;Перевірку можна створити разом із оголошенням властивості у класі моделі:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# неявно створює validates_present
:nullable =&amp;gt; false
:length =&amp;gt; (1..n)
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# неявно створює validates_length
:length =&amp;gt; 20
:length =&amp;gt; (1..20) # не може бути нульовим
:lenth =&amp;gt; (0..20)  # може бути нульовим
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;# неявно створює validates_format
:format =&amp;gt; :email_address
:format =&amp;gt; /\w+_\w+/
:format =&amp;gt; lambda {|str| str}
:format =&amp;gt; Proc.new {|str| str}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Тепер давайте створимо клас як з ручною перевіркою, так і з автоматичною:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;require 'dm-validations'

class Post
  include DataMapper::Resource

  property :title, String
  validates_length :name, :max =&amp;gt; 30

  property :body, Text, :length =&amp;gt; (1..5000)
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;h3&gt;Робота з помилками перевірки&lt;/h3&gt;Якщо &lt;i&gt;валідатор&lt;/i&gt; знаходить помилку в моделі, він генерує об'єкт &lt;i&gt;Validate::ValidationErrors&lt;/i&gt;, який доступний моделі через виклик методу &lt;i&gt;#errors&lt;/i&gt; :&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;my_post = Post.new(:title =&amp;gt; "Is It Alright?")
if my_post.save
  # my_post є дійсним і буде збережений
else
  my_post.errors.each do |e|
    puts e
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Повідомлення про помилки, які надаються &lt;i&gt;DataMapper&lt;/i&gt; як правило чіткі і точно пояснюють, що пішло не так. Але у вас є можливість змінити їх, шляхом передання опції &lt;i&gt;:message&lt;/i&gt; :&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;validates_is_unique :body, :scope =&amp;gt; :post_id,
  :message =&amp;gt; "There's already a comment of that body in this post"
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Цей приклад демонструє використання опції &lt;i&gt;:scope&lt;/i&gt; для перевірки унікальності властивості в обмеженій області. Об'єкт не буде дійсним, якщо інший об'єкт з таким самим &lt;i&gt;post_id&lt;/i&gt; матиме ідентичне &lt;i&gt;body&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Щось подібне також можна зробити і для автоматичної перевірки через встановлення &lt;i&gt;:messages&lt;/i&gt; у параметрах властивості:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;property :email, String, :nullable =&amp;gt; false, :unique =&amp;gt; true, :format =&amp;gt; :email_address,
                         :messages =&amp;gt; {
                           :presence =&amp;gt; "We need your email address.",
                           :is_unique =&amp;gt; "We already have that email."
                           :format =&amp;gt; "Doesn't look like an email address."
                        }
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Робота з даними&lt;/h2&gt;&lt;br /&gt;
&lt;i&gt;CRUD&lt;/i&gt; - (англ. create read update delete) 4 базові функції управління даними "створення, зчитування, зміна і видалення".&lt;br /&gt;
Стосовно СУБД:&lt;br /&gt;
&lt;pre&gt;Створити - INSERT 
Вибірка   - SELECT
Оновити  - UPDATE
Знищити  - DELETE
&lt;/pre&gt;&lt;br /&gt;
Для прикладу створимо новий екземпляр моделі &lt;i&gt;Post&lt;/i&gt;, оновимо його властивості і збережемо. Якщо збереження пройде успішно функція поверне &lt;i&gt;true&lt;/i&gt;, або &lt;i&gt;false&lt;/i&gt;, якщо щось пішло не так.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;post = Post.new
post.attributes = {:title =&amp;gt; "Hello world!", :body =&amp;gt; "DataMapper is awesome!"}
post.save
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Є декілька способів встановлення властивостей моделі:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;post = Post.new(:title =&amp;gt; 'Pass in a hash to the new method'
post.title = 'Set individual property')
post.attributes = {:title =&amp;gt; "Hello world!", :body =&amp;gt; "DataMapper is flexible!"}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Також можна оновити властивості моделі і зберегти за допомогою одного методу:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;post.update_attributes = {:title =&amp;gt; "Hello world!", :body =&amp;gt; "DataMapper is simple!"}
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Щоб знищити запис, ви просто викликаєте на ньому метод &lt;i&gt;#destroy!&lt;/i&gt;. Він поверне &lt;i&gt;true&lt;/i&gt; або &lt;i&gt;false&lt;/i&gt;, в залежності від того чи запис був видалений. Ось приклад знаходження існуючого запису, та його знищення:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;post = Post.get(3)
post.destroy! #=&amp;gt; true
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Методи пошуку для об'єктів &lt;i&gt;DataMapper&lt;/i&gt; визначені в &lt;i&gt;DataMapper::Repository&lt;/i&gt;. Вони включають &lt;i&gt;get()&lt;/i&gt;, &lt;i&gt;all()&lt;/i&gt;, &lt;i&gt;first()&lt;/i&gt;.&lt;br /&gt;
DataMapper має методи, які дозволяють отримати:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;один запис по ключу;&lt;/li&gt;
&lt;li&gt;перший запис, що збігається з набором умов;&lt;/li&gt;
&lt;li&gt;множину записів, які відповідають умовам.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;post = Post.get(1)                          # отримати запис із первинним ключем 1
post = Post.get!(1)                         # аналогічно get(), але у випадку невдачі поверне ObjectNotFoundError
post = Post.first(:title =&amp;gt; 'Hello world!') # перший запис із заголовком 'Hello world!'
posts = Post.all                            # всі записи
posts = Post.all(:published =&amp;gt; true)        # всі опубліковані записи
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Методи &lt;i&gt;all()&lt;/i&gt; і &lt;i&gt;first()&lt;/i&gt; можуть бути з'єднані в ланцюжок для подальшої побудови запиту до бази даних:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;all_posts = Post.all
published_posts = all_posts.all(:published =&amp;gt; true)
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Як прямий наслідок цього:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Post
  def self.published
    all(:published =&amp;gt; true)
  end
end

published_posts = Post.published
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Замість визначення умов, використовуючи &lt;i&gt;SQL&lt;/i&gt;, можна вказувати умови, використовуючи хеш значень.&lt;br /&gt;
Наведені нище приклади є досить простими, ви буде здивовані, як ви можете визначити умови рівності не вдаючись до &lt;i&gt;SQL&lt;/i&gt;.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;posts = Post.all(:created_at.gt =&amp;gt; 2, :created_at.lt =&amp;gt; 10)
# SQL: 'created_at &amp;gt; 2 AND created_at &amp;lt; 10'
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Доступні символи операцій для умов:&lt;br /&gt;
&lt;pre&gt;gt    # більше
lt    # менше
gte   # більше або рівне
lte   # менше або рівне
not   # не рівне
eql   # рівне
like  # схоже
in    # міститься - використовується автоматично, якщо в якості аргументу переданий масив
&lt;/pre&gt;&lt;br /&gt;
Щоб визначити порядок, в якому повинні бути відсортовані результати, використовується:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;posts = Post.all(:all =&amp;gt; [:created_at.desc]
# SQL: select * from posts ORDER BY created_at DESC)
&lt;/code&gt;&lt;/pre&gt;Сортувати можна за зростанням(&lt;i&gt;asc&lt;/i&gt;) і за спаданням(&lt;i&gt;desc&lt;/i&gt;).&lt;br /&gt;
&lt;br /&gt;
Крім того DataMapper підтримує й інший синтаксис для умов:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;posts = Post.all(:conditions =&amp;gt; {:id =&amp;gt; 1})
posts = Post.all(:conditions =&amp;gt; ["id = ?", 1])
posts = Post.all(:conditions =&amp;gt; {:id =&amp;gt; 1}, :title.like =&amp;gt; '%foo%')
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Іноді потрібно зробити запит до БД вручну:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;posts = repository(:default).adapter.query('SELECT title, body FROM posts WHERE published = 1')
&lt;/code&gt;&lt;/pre&gt;Зауважте, така форма запиту поверне об'єкт &lt;i&gt;Struct&lt;/i&gt;, а не &lt;i&gt;Post&lt;/i&gt;.&lt;br /&gt;
&lt;br /&gt;
Ну і на сам кінець варто згадати конструкцію &lt;i&gt;before&lt;/i&gt;, яка може стати у нагоді тоді, коли потрібно виконати якусь дію з даними до того як вони будуть збережені у базу. Для прикладу:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;class Post
  include DataMapper:Resource

  before :save, :format_body

  def format_body
    # ... деякий код
  end
end

class Comment
  include DataMapper:Resource

  before :save do
    # ... деякий код
  end
end
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Спочатку я планував вкластися в одну статтю, але практика показала, що навіть двох мало. Тому чекайте продовження, в якому ми спробуємо написати свій затишний блог на &lt;i&gt;Sinatra&lt;/i&gt; по мотивах бестселера "&lt;i&gt;Creating a weblog in 15 minutes with Rails&lt;/i&gt;".&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Що почитати на дозвіллі?&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://datamapper.org/docs/"&gt;DataMapper Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Користуючись нагодою, вітаю співвітчизників з Днем української писемності та мови.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://uaday.org/" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="UA DAY" src="http://uaday.org/ban-468.png" title="День української мови" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-3103519743780209399?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/3103519743780209399/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=3103519743780209399" title="1 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3103519743780209399?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3103519743780209399?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/rFHmxnZKpwk/datamapper.html" title="Привіт, DataMapper!" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_lXvcYH2YnAY/SvfpZb_wybI/AAAAAAAAEx4/V3B46l0dGjs/s72-c/dm.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/11/datamapper.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIBSXs8fSp7ImA9WxNVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-3877661358374886891</id><published>2009-10-28T12:51:00.007+02:00</published><updated>2009-10-30T12:12:38.575+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T12:12:38.575+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="tutorial" /><category scheme="http://www.blogger.com/atom/ns#" term="sinatra" /><title>Привіт, Sinatra!</title><content type="html">&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_lXvcYH2YnAY/Sughmv6woZI/AAAAAAAAExY/ZAKA4dEfBUA/s1600-h/Sinatralogo.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/Sughmv6woZI/AAAAAAAAExY/ZAKA4dEfBUA/s320/Sinatralogo.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Sinatra&lt;/b&gt; — об'єктно-орієнтований програмний каркас(&lt;i&gt;framework&lt;/i&gt;) для створення веб-застосунків, написана на мові програмування &lt;i&gt;Ruby&lt;/i&gt;. На офійному сайті написано, що Sinatra це навіть не фреймворк, а &lt;i&gt;DSL&lt;/i&gt; для створення веб-додатків. Залежить від інтерфейсу веб-сервера &lt;i&gt;Rack&lt;/i&gt;. Вона є альтернативою іншим Ruby фреймворкам, таким як &lt;i&gt;Ruby on Rails&lt;/i&gt;, &lt;i&gt;Merb&lt;/i&gt;, &lt;i&gt;Nitro&lt;/i&gt; та &lt;i&gt;Camping&lt;/i&gt;.&lt;br /&gt;Sinatra є відкритим програмним забезпеченням і розповсюджується під ліцензією &lt;i&gt;MIT&lt;/i&gt;.&lt;br /&gt;Розроблена та створена &lt;i&gt;Blake Mizerany&lt;/i&gt;, Sinatra є крихітною(близько 1500 рядків коду, що майже 1/100-а розміру Rails) та надзвичайно гнучкою. Вона не слідує типовій архітектурі &lt;i&gt;Модель-Вид-Контролер&lt;/i&gt;(&lt;i&gt;Model-View-Controller&lt;/i&gt;, &lt;i&gt;MVC&lt;/i&gt;), яка використовується в інших фреймвоках, таких як Ruby On Rails. Натомість, Sinatra зосереджена на "швидкому створенню веб-додатків на Ruby із мінімальними зусиллями". Sinatra використовує всі можливості Ruby і є його оригінальним розширенням.&lt;br /&gt;&lt;br /&gt;Sinatra дає незвичайне відчуття присутності. Це як музика. Ви диригент оркестру. І перша скрипка звучить так, як ви їх наказали, хоча ви не обов'язково повинні знати, як на ній грати. Але в той же час у вас є можливість посмикати струни, побити в барабани, засурмити фанфари. Sinatra крихітна, гнучка і модульна. Ви вільні у виборі, що використовувати у якості бібліотеки моделі, двигуна шаблонів, двигуна &lt;i&gt;JavaScript&lt;/i&gt;. Незважаючи на свій юний вік Sinatra є потужним і багатообіцяючим інструментом, про що свідчить підтримка з боку таких таких маститих проектів, як &lt;i&gt;Engine Yard&lt;/i&gt;, &lt;i&gt;Heroku&lt;/i&gt;, &lt;i&gt;GitHub&lt;/i&gt; і &lt;i&gt;Songbird&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Інсталяція Sinatra&lt;/span&gt;&lt;br /&gt;Розпочнемо знайомство із встановлення Sinatra.&lt;br /&gt;У вас уже повинен бути встановлений Ruby. Для тих хто вже користується новою гілкою 1.9 можу вас втішити - починаючи з версії 0.9.2, Sinatra повністю сумісна з Ruby 1.9 і Rack 1.0. Найпростіший шлях - встановити Sinatra через Rubygems:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ gem install sinatra&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Привіт, Sinatra&lt;/span&gt;&lt;br /&gt;Тепер давайте створимо наш перший веб-додаток.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# myapp.rb&lt;br /&gt;require 'rubygems'&lt;br /&gt;require 'sinatra'&lt;br /&gt;&lt;br /&gt;get '/' do&lt;br /&gt; "Привіт, Sinatra!"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Звичайно це не дуже корисна програма, це традиційний "Hello World!". Незважаючи на свою простоту, цей приклад корисний тим, що дозволяє виконати всі дії, необхідні для написання і запуску будь-якого Sinatra додатку.&lt;br /&gt;Інша річ, яку ви могли помітити, вам не потрібно запускати нічого подібного Rails генераторам, для створення додатку. Для запуску програми код Ruby потрібно зберегти в файлі під якоюсь назвою (в нашому випадку це myapp.rb). Потім програму потрібно запустити. В залежності від операційної системи, це робиться по різному. Наприклад, під управлінням &lt;i&gt;Linux&lt;/i&gt;, потрібно набрати на терміналі:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ ruby myapp.rb&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У результаті запуститься веб-сервер &lt;i&gt;WEBrick&lt;/i&gt;, який можна переглянути з вашого улюбленого навігатора тенет за адресою &lt;a href="http://localhost:4567/"&gt;http://localhost:4567&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Маршрути&lt;/span&gt;&lt;br /&gt;В Sinatra-додатках вхідні запити спочатку відсилаються маршрутизатору, який і вирішує, куди запит повинен бути відісланий і як, власне, цей запит повинен бути оброблений. У Sinatra, маршрут пов'язаний із HTTP-методом, і записується у парі з відповідним зразком URL.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;GET&lt;/li&gt;&lt;br /&gt;&lt;li&gt;POST&lt;/li&gt;&lt;br /&gt;&lt;li&gt;PUT&lt;/li&gt;&lt;br /&gt;&lt;li&gt;DELETE&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Кожен маршрут пов'язаний з блоком:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/' do&lt;br /&gt; # показати щось&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;post '/' do&lt;br /&gt; # створити щось&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;put '/' do&lt;br /&gt; # оновити щось&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;delete '/' do&lt;br /&gt; # знищити шось&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Маршрути збігаються у тому порядку, в якому вони визначені. Тобто, викликається перший маршрут, який відповідає запиту. З цієї причини ви повинні розміщувати найбільш специфічні обробники зверху, а найбільш нечіткі - знизу.&lt;br /&gt;&lt;br /&gt;Маршрут може включати в себе імена параметрів, які доступні через параметри хешу:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/hello/:name' do&lt;br /&gt; # збігається з "/hello/foo" і "/hello/bar"&lt;br /&gt; # params[:name] буде 'foo' або 'bar'&lt;br /&gt; "Hello #{params[:name]}!"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Також маршрут може включати підстановлювальний знак (wildcard), який доступний через масив &lt;i&gt;params[:splat]&lt;/i&gt; :&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/say/*/to/*'&lt;br /&gt; # збігається з "/say/hello/to/world"&lt;br /&gt; params[:splat] # =&amp;gt; ["hello", "world"]&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/download/*.*' do&lt;br /&gt; # збігається з "/download/path/to/file.xml"&lt;br /&gt; params[:splat] # =&amp;gt; ["path/to/file", "xml"]&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Маршрут, відповідний з регулярними виразами:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get %r{/hello/id([\d]+)} do&lt;br /&gt; # збігається з "/hello/id1234"&lt;br /&gt; # params[:captures] =&amp;gt; ["1234"]&lt;br /&gt; "Hello, #{params[:captures].first}!"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Або те саме з параметром блоку:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get %r{/hello/id([\d]+)} do |c|&lt;br /&gt; "Hello, #{c}!"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;User Agent.&lt;br /&gt;Наступний маршрут відповідає будь-якому броузеру:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/agent', :agent =&amp;gt; /(.+)/ do&lt;br /&gt; "You are using #{params[:agent].first}"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тільки Opera:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/agent', :agent =&amp;gt; /Opera\/(\d+\.\d+).*?/ do&lt;br /&gt; "You are using Opera version #{params[:agent].first}"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Інші методи викликаються так само як "&lt;i&gt;get&lt;/i&gt;" маршрути. Ви просто використовуєте функції "&lt;i&gt;post&lt;/i&gt;", "&lt;i&gt;put&lt;/i&gt;" чи "&lt;i&gt;delete&lt;/i&gt;" для визначення маршруту. Щоб отримати доступ до параметрів &lt;i&gt;POST&lt;/i&gt;, використовується &lt;i&gt;params[:xxx]&lt;/i&gt;, де &lt;i&gt;xxx&lt;/i&gt; - це ім'я елементу форми, яке було надіслано.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;post '/foo' do&lt;br /&gt; "You just asked for foo, with post param bar equal to #{params[:bar]}"&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Статичні файли&lt;/span&gt;&lt;br /&gt;Статичні файли віддаються з директорії &lt;i&gt;./public&lt;/i&gt;. Ви можете визначити інше місце, встановивши опцію &lt;i&gt;:public&lt;/i&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;set :public, File.dirname(__FILE__) + '/static'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Зверніть увагу, що ім'я публічного каталогу не включається в шлях URL. Файл &lt;i&gt;./public/css/style.css&lt;/i&gt; буде доступний як &lt;i&gt;http://localhost/css/style.css&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Шаблони&lt;/span&gt;&lt;br /&gt;Шаблони безпосередньо розміщуються у директорії &lt;i&gt;./views&lt;/i&gt;. Щоб використовувати іншу директорію, необхідно встановити опцію &lt;i&gt;:views&lt;/i&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;set :views, File.dirname(__FILE__) + '/templates'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Важливо пам'ятати, що вам завжди доведеться посилатися на шаблон використовуючи об'єкт типу &lt;i&gt;Symbol&lt;/i&gt;, навіть якщо він знаходяться у підкаталозі (в такому випадку використовувати &lt;i&gt;:'subdir/template'&lt;/i&gt;). Методи будуть виконувати будь-які рядки, передані їм безпосередньо.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Шаблони HAML&lt;/b&gt;&lt;br /&gt;&lt;i&gt;Haml&lt;/i&gt; (&lt;i&gt;XHTML Abstraction Markup Language&lt;/i&gt;) — мова розмітки для спрощеного генерування &lt;i&gt;XHTML&lt;/i&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/' do&lt;br /&gt; haml :index&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Обробляє &lt;i&gt;./view/index.haml&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Параметри HAML можуть бути встановлені глобально через конфігурацію Sinatra, або перевизначені індивідуально.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;set :haml, {:format =&amp;gt; :html5 } # формат Haml по замовчуванню :xhtml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/' do&lt;br /&gt; haml :index, :haml_options =&amp;gt; {:format =&amp;gt; :html4 } # перевизначення&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Шаблони Erb&lt;/b&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'erb'&lt;br /&gt;&lt;br /&gt;get '/' do&lt;br /&gt; erb :index&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Обробляє &lt;i&gt;./view/index.erb&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Шаблони Builder&lt;/b&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'builder'&lt;br /&gt;&lt;br /&gt;get '/' do&lt;br /&gt; content_type 'application/xml', :charset =&amp;gt; 'utf-8'&lt;br /&gt; builder :index&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Обробляє &lt;i&gt;./view/index.builder&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Шаблони Sass&lt;/b&gt;&lt;br /&gt;&lt;i&gt;Sass&lt;/i&gt; (&lt;i&gt;Syntactically Awesome Stylesheets&lt;/i&gt;) - еквівалент &lt;i&gt;HAML&lt;/i&gt; для &lt;i&gt;CSS&lt;/i&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'sass'&lt;br /&gt;&lt;br /&gt;get '/stylesheet.css' do&lt;br /&gt; content_type 'text/css', :charset =&amp;gt; 'utf-8'&lt;br /&gt; sass :stylesheet&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Обробляє &lt;em&gt;./view/stylesheet.sass&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Параметри Sass можуть бути встановлені глобально через конфігурацію Sinatra, або перевизначені індивідуально.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;set :sass, {:style =&amp;gt; :compact } # стиль Sass по замовчуванню :nested&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/stylesheet.css' do&lt;br /&gt; content_type 'text/css', :charset =&amp;gt; 'utf-8'&lt;br /&gt; sass :stylesheet, :sass_options =&amp;gt; {:style =&amp;gt; :expanded } # перевизначення&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Вбудовані шаблони&lt;/b&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/' do&lt;br /&gt; haml '%div.title Hello World'&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Обробляє вказаний рядок.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Доступ до змінних у шаблоні&lt;/b&gt;&lt;br /&gt;Шаблони оцінюються в тому контексті, як і обробники маршруту. Змінні, встановленні в обробнику маршруту безпосередньо доступні шаблону.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/:id' do&lt;br /&gt; @foo = Foo.find(params[:id])&lt;br /&gt; haml '%h1= @foo.name'&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Або вказати явний хеш(&lt;i&gt;Hash&lt;/i&gt;) локальних змінних:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;get '/:id' do&lt;br /&gt; foo = Foo.find(params[:id])&lt;br /&gt; haml '%h1= foo.name', :locals =&amp;gt; { :foo =&amp;gt; foo }&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Зазвичай це використовується для обробки шаблонів, як &lt;i&gt;фрагментів&lt;/i&gt;(&lt;i&gt;partials&lt;/i&gt;) з інших шаблонів.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In-file шаблони&lt;/b&gt;&lt;br /&gt;Шаблони можуть бути визначеними у кінці вихідного файлу:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'rubygems'&lt;br /&gt;require 'sinatra'&lt;br /&gt;&lt;br /&gt;get '/' do&lt;br /&gt; haml :index&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;__END__&lt;br /&gt;&lt;br /&gt;@@ layout&lt;br /&gt;%html&lt;br /&gt; = yield&lt;br /&gt;&lt;br /&gt;@@ index&lt;br /&gt;%div.title Hello world!!!!!&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Іменовані шаблони&lt;/b&gt;&lt;br /&gt;Шаблони також можуть бути визначені з використання шаблону верхнього рівня:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;template :layout do&lt;br /&gt; "%html\n  =yield\n"&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;template :index do&lt;br /&gt; '%div.title Hello World!'&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;get '/' do&lt;br /&gt; haml :index&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Якщо шаблон під назвою "&lt;i&gt;layout&lt;/i&gt;" існує, він буде використовуватися щоразу при обробці шаблону. Ви можете відключити &lt;i&gt;макети&lt;/i&gt;(&lt;i&gt;layouts&lt;/i&gt;), передавши&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;:layout =&amp;gt; false&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:large;"&gt;Що почитати на дозвіллі?&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.sinatrarb.com/documentation.html"&gt;Sinatra Documentation&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://haml-lang.com/docs/yardoc/HAML_REFERENCE.md.html"&gt;The Haml reference&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-3877661358374886891?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/3877661358374886891/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=3877661358374886891" title="1 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3877661358374886891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3877661358374886891?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/Sgk4q30K9Sw/sinatra.html" title="Привіт, Sinatra!" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_lXvcYH2YnAY/Sughmv6woZI/AAAAAAAAExY/ZAKA4dEfBUA/s72-c/Sinatralogo.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/10/sinatra.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkYCRHYyfip7ImA9WxNVEk0.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-2881509744381625755</id><published>2009-10-22T12:36:00.000+03:00</published><updated>2009-10-22T12:36:05.896+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-22T12:36:05.896+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="internet" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><title>Try Ruby! Now With 1.9</title><content type="html">Веб-версія &lt;b&gt;IRB&lt;/b&gt;(&lt;b&gt;i&lt;/b&gt;nteractive &lt;b&gt;r&lt;/b&gt;uby &lt;b&gt;p&lt;/b&gt;rompt) та 15 хвилинний навчальний посібник для людей, які хочуть познайомитися з Ruby. Тепер версія 1.9.&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SuAmCieV9II/AAAAAAAAEw4/ryOMPI3-FCc/s1600-h/tryruby19.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SuAmCieV9II/AAAAAAAAEw4/ryOMPI3-FCc/s400/tryruby19.png" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div align="center"&gt;&lt;a href="http://tryruby.sophrinix.com/"&gt;http://tryruby.sophrinix.com/&lt;/a&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-2881509744381625755?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/2881509744381625755/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=2881509744381625755" title="1 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2881509744381625755?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2881509744381625755?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/1-4e-v7xalk/try-ruby-now-with-19.html" title="Try Ruby! Now With 1.9" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_lXvcYH2YnAY/SuAmCieV9II/AAAAAAAAEw4/ryOMPI3-FCc/s72-c/tryruby19.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/10/try-ruby-now-with-19.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYNRnc5fyp7ImA9WxNVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-2722161732517862561</id><published>2009-10-14T14:45:00.007+03:00</published><updated>2009-10-30T11:49:57.927+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T11:49:57.927+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="mechanize" /><category scheme="http://www.blogger.com/atom/ns#" term="vkontakte" /><title>vk.com. Частина 7</title><content type="html">У цьому дописі мова знову піде про &lt;a href="http://ruby-ua.blogspot.com/search/label/vkontakte"&gt;ВКонтакте&lt;/a&gt; і &lt;a href="http://mechanize.rubyforge.org"&gt;WWW::Mechanize&lt;/a&gt;. Хоч він і йде під номером &lt;span style="font-style:italic;"&gt;сім&lt;/span&gt;, він не є продовженням попередніх частинами, хоча для повного розуміння про далі буде йти мова, бажано ознайомитися з ними. З них ви можете дізнатися, як робити наступні речі ВКонтакте:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Отримання новин профілю (кількості нових повідомлень, фотографій, відео, друзів, груп).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Отримання списку друзів&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Отримання приватних повідомлень&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Написання приватних повідомлень&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Я вже &lt;a href="http://ruby-ua.blogspot.com/2009/09/keyword-loginvkcomactlogin.html"&gt;писав&lt;/a&gt; про те, що домен &lt;span style="font-weight:bold;"&gt;VK.COM&lt;/span&gt; перейшов під контроль соціальної мережі ВКонтакте. Майже з тих самих пір авторизація користувачів на сайті &lt;a href="http://vkontakte.ru"&gt;vkontakte.ru&lt;/a&gt; відбувається через редірект &lt;a href="http://login.vk.com"&gt;login.vk.com&lt;/a&gt;. Це викликає незручність при авторизації за допомогою &lt;a href="http://mechanize.rubyforge.org"&gt;WWW::Mechanize&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'mechanize'&lt;br /&gt;require 'json'&lt;br /&gt;&lt;br /&gt;class Vkontakte&lt;br /&gt;  def initialize&lt;br /&gt;    @ua = WWW::Mechanize.new{&amp;#124;agent&amp;#124;&lt;br /&gt;      agent.user_agent_alias = 'Linux Mozilla'&lt;br /&gt;      agent.follow_meta_refresh = true&lt;br /&gt;    }&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # Authorisation by submitting email and password (Login)&lt;br /&gt;  #                                                       &lt;br /&gt;  def login_force(uid, email, pass)                       &lt;br /&gt;    url = &amp;quot;http://login.vk.com/?act=login&amp;quot;                &lt;br /&gt;    page = @ua.post(url, {'email' =&amp;gt; email, 'pass' =&amp;gt; pass, 'expire' =&amp;gt; '1', 'vk' =&amp;gt; 1})&lt;br /&gt;    s = page.body.match(/'s' value='(.+?)'/)[1]                                         &lt;br /&gt;    @ua.post('http://vkontakte.ru/login.php?op=slogin&amp;amp;redirect=1', {'s' =&amp;gt; s})          &lt;br /&gt;    user_page = @ua.get('http://vkontakte.ru/profile.php')                              &lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;if __FILE__ == $0&lt;br /&gt;  id = &amp;quot;xxxxxxxx&amp;quot;&lt;br /&gt;  email = &amp;quot;user@example.com&amp;quot;&lt;br /&gt;  pass = &amp;quot;your_password&amp;quot;&lt;br /&gt;&lt;br /&gt;  vkontakte_agent = Vkontakte.new&lt;br /&gt;  vkontakte_agent.login_force(id, email, pass)&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Далі можна продовжувати роботу з ВКонтакте як звичайно.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Давайте напишемо скрипт, який буде авторизуватись і працювати з &lt;a href="http://vk.com"&gt;vk.com&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'mechanize'&lt;br /&gt;require 'json'     &lt;br /&gt;&lt;br /&gt;class Vkontakte&lt;br /&gt;  def initialize&lt;br /&gt;    @ua = WWW::Mechanize.new{&amp;#124;agent&amp;#124;&lt;br /&gt;      agent.user_agent_alias = 'Linux Mozilla'&lt;br /&gt;      agent.follow_meta_refresh = true&lt;br /&gt;    }&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  # Authorisation by submitting email and password (Login)&lt;br /&gt;  #                                                       &lt;br /&gt;  def login_force(uid, email, pass)                       &lt;br /&gt;    url = &amp;quot;http://vk.com&amp;quot;&lt;br /&gt;    login_page = @ua.get(url)&lt;br /&gt;    login_form = login_page.form_with(:name =&amp;gt; 'login')&lt;br /&gt;    login_form.email = email&lt;br /&gt;    login_form.pass = pass&lt;br /&gt;    user_page = login_form.submit # &amp;#1059; &amp;#1088;&amp;#1072;&amp;#1079;&amp;#1110; &amp;#1091;&amp;#1089;&amp;#1087;&amp;#1110;&amp;#1096;&amp;#1085;&amp;#1086;&amp;#1111; &amp;#1072;&amp;#1074;&amp;#1090;&amp;#1086;&amp;#1088;&amp;#1080;&amp;#1079;&amp;#1072;&amp;#1094;&amp;#1110;&amp;#1111; &amp;#1074;&amp;#1110;&amp;#1076;&amp;#1073;&amp;#1091;&amp;#1074;&amp;#1072;&amp;#1108;&amp;#1090;&amp;#1100;&amp;#1089;&amp;#1103; &amp;#1087;&amp;#1077;&amp;#1088;&amp;#1077;&amp;#1093;&amp;#1110;&amp;#1076; &amp;#1085;&amp;#1072; http://login.vk.com.&lt;br /&gt;    if user_page.uri.to_s == 'http://login.vk.com/?act=login'&lt;br /&gt;      user_page =user_page.forms.first.submit&lt;br /&gt;      return true&lt;br /&gt;    else&lt;br /&gt;      return false&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;if __FILE__ == $0&lt;br /&gt;  id = &amp;quot;xxxxxxxx&amp;quot;&lt;br /&gt;  email = &amp;quot;user@example.com&amp;quot;&lt;br /&gt;  pass = &amp;quot;your_password&amp;quot;&lt;br /&gt;&lt;br /&gt;  vkontakte_agent = Vkontakte.new&lt;br /&gt;  vkontakte_agent.login_force(id, email, pass)&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Як ви бачите, авторизація на сайті &lt;a href="http://vk.com"&gt;vk.com&lt;/a&gt; відбувається більш прозоро і зрозуміло.&lt;br /&gt;Якщо порівняти сайти &lt;a href="http://vkontakte.ru"&gt;vkontakte.ru&lt;/a&gt; і &lt;a href="http://vk.com"&gt;vk.com&lt;/a&gt;, можна помітити, що крім відмінностей у назві домену вони практично ідентичні.&lt;br /&gt;Для прикладу продемонструю метод для зміни статусу ВКонтакте:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class Vkontakte&lt;br /&gt;  # Set status message for current user&lt;br /&gt;  #&lt;br /&gt;  def set_status(message)&lt;br /&gt;    url = 'http://vk.com/profile.php'&lt;br /&gt;    page = @ua.get(url)&lt;br /&gt;    hash = page.body.match(/id='activityhash' value='(.+?)'/)[1]&lt;br /&gt;    query = {&amp;quot;activityhash&amp;quot; =&amp;gt; hash, &amp;quot;setactivity&amp;quot; =&amp;gt; message}&lt;br /&gt;    sleep(1) # http://vk.com/blank.php - &amp;#1042;&amp;#1080; &amp;#1085;&amp;#1072;&amp;#1084;&amp;#1072;&amp;#1075;&amp;#1072;&amp;#1083;&amp;#1080;&amp;#1089;&amp;#1100; &amp;#1079;&amp;#1072;&amp;#1074;&amp;#1072;&amp;#1085;&amp;#1090;&amp;#1072;&amp;#1078;&amp;#1080;&amp;#1090;&amp;#1080; &amp;#1073;i&amp;#1083;&amp;#1100;&amp;#1096;&amp;#1077; &amp;#1086;&amp;#1076;&amp;#1085;i&amp;#1108;&amp;#1111; &amp;#1086;&amp;#1076;&amp;#1085;&amp;#1086;&amp;#1090;&amp;#1080;&amp;#1087;&amp;#1085;&amp;#1086;&amp;#1111; &amp;#1089;&amp;#1090;&amp;#1086;&amp;#1088;i&amp;#1085;&amp;#1082;&amp;#1080; &amp;#1079;&amp;#1072; &amp;#1089;&amp;#1077;&amp;#1082;&amp;#1091;&amp;#1085;&amp;#1076;&amp;#1091;. &amp;#1055;&amp;#1086;&amp;#1074;&amp;#1077;&amp;#1088;&amp;#1085;i&amp;#1090;&amp;#1100;&amp;#1089;&amp;#1103; &amp;#1085;&amp;#1072;&amp;#1079;&amp;#1072;&amp;#1076; i &amp;#1089;&amp;#1087;&amp;#1088;&amp;#1086;&amp;#1073;&amp;#1091;&amp;#1081;&amp;#1090;&amp;#1077; &amp;#1097;&amp;#1077; &amp;#1088;&amp;#1072;&amp;#1079;.&lt;br /&gt;    page = @ua.post(url, query)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ддя того щою цей метод працював з сайтом &lt;a href="http://vkontakte.ru"&gt;vkontakte.ru&lt;/a&gt; достатньо у змінній &lt;span style="font-style:italic;"&gt;url&lt;/span&gt; змінити &lt;span style="font-style:italic;"&gt;vk.com&lt;/span&gt; на &lt;span style="font-style:italic;"&gt;vkontakte.ru&lt;/span&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-2722161732517862561?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/2722161732517862561/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=2722161732517862561" title="2 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2722161732517862561?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2722161732517862561?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/k6Jn8G1N_xQ/vkcom-7.html" title="vk.com. Частина 7" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/10/vkcom-7.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQHQX07cCp7ImA9WxNXEUo.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-4314232541454925070</id><published>2009-09-29T00:15:00.005+03:00</published><updated>2009-09-29T00:45:30.308+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-29T00:45:30.308+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="nokogiri" /><category scheme="http://www.blogger.com/atom/ns#" term="internet" /><title>Proxy list fetcher using Ruby &amp; Nokogiri</title><content type="html">А чому б нам не зробити накручувалку, яка голосує за &lt;span style="font-style:italic;"&gt;що-небудь&lt;/span&gt; ? "Чорні"(брудні) технології залишимо нашим політиком. А самі займемося чимось корисним.&lt;br /&gt;&lt;br /&gt;Цей скрипт складає список проксі-серверів з сайту &lt;a href="http://www.proxy4free.com"&gt;proxy4free.com&lt;/a&gt;, і записує його до файлу &lt;span style="font-style:italic;"&gt;proxy_list.txt&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;&lt;br /&gt;require 'nokogiri'&lt;br /&gt;require 'open-uri'&lt;br /&gt;&lt;br /&gt;file = File.new('proxy_list.txt', 'w')&lt;br /&gt;url = 'http://www.proxy4free.com/page1.html'&lt;br /&gt;# Get a Nokogiri::HTML:Document for the page&lt;br /&gt;doc = Nokogiri::HTML(open(url))&lt;br /&gt;&lt;br /&gt;# Search for nodes by css&lt;br /&gt;doc.css('table tr.text').each do &amp;#124;tr&amp;#124;&lt;br /&gt;  ip = (tr/&amp;quot;td:nth(1)&amp;quot;).first.inner_html&lt;br /&gt;  if ip.match(/^(\d{1,3}\.){3}\d{1,3}$/)&lt;br /&gt;    port = (tr/&amp;quot;td:nth(2)&amp;quot;).first.inner_html&lt;br /&gt;    file.puts &amp;quot;#{ip}:#{port}&amp;quot;&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;file.close&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Керівництва до дії:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Do something&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Do something else&lt;/li&gt; &lt;br /&gt;&lt;li&gt;Do something once more&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&amp;lt;Do something so much you need&amp;gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;?????&lt;/li&gt; &lt;br /&gt;&lt;li&gt;PROFIT!&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-4314232541454925070?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/4314232541454925070/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=4314232541454925070" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/4314232541454925070?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/4314232541454925070?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/8VympzJA1dk/proxy-list-fetcher-using-ruby-nokogiri.html" title="Proxy list fetcher using Ruby &amp; Nokogiri" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/proxy-list-fetcher-using-ruby-nokogiri.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UESH0zcSp7ImA9WxNQFkw.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-6525590129693643218</id><published>2009-09-22T14:05:00.005+03:00</published><updated>2009-09-22T14:33:29.389+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-22T14:33:29.389+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="windows" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><title>RubyInstaller for Windows</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/Srix3IQmNsI/AAAAAAAAEv4/SNbNW_P9mgA/s1600-h/wruby1.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 291px; height: 73px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/Srix3IQmNsI/AAAAAAAAEv4/SNbNW_P9mgA/s400/wruby1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5384248915189446338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://rubyinstaller.org/"&gt;RubyInstaller&lt;/a&gt; (раніше відомий як &lt;span style="font-style:italic;"&gt;One-Click Installer&lt;/span&gt;) - це автономний Windows-інсталятор, який включає в себе саму мову &lt;span style="font-style:italic;"&gt;Ruby&lt;/span&gt;, середовище виконання, важливу документацію (містить документацію Ruby Core і стандартних бібліотеках, а також книжку "The Book of Ruby" написану Huw Collingbourne), та багато іншого.&lt;br /&gt;Для інсталяції Ruby в один клік необхідно спочатку завантажити версію, яку ви хочете (на даний момент доступні 1.8.6 та 1.9.1) і запустити .exe файл.&lt;br /&gt;Після цього в меню "Пуск" з'явиться відповідний пункт:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sri18Uf-P2I/AAAAAAAAEwQ/ViDWbfsMAjo/s1600-h/wruby.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 80px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sri18Uf-P2I/AAAAAAAAEwQ/ViDWbfsMAjo/s400/wruby.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5384253402421018466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Хочу замітити цей проект знаходиться на першому місці по кількості скачувань з сайту &lt;a href="http://rubyforge.org/"&gt;RubyForge&lt;/a&gt;. На даний момент це - 3,572,852 раз.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-6525590129693643218?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/6525590129693643218/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=6525590129693643218" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6525590129693643218?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6525590129693643218?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/rOOpmFCXUNo/rubyinstaller-for-windows.html" title="RubyInstaller for Windows" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_lXvcYH2YnAY/Srix3IQmNsI/AAAAAAAAEv4/SNbNW_P9mgA/s72-c/wruby1.JPG" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/rubyinstaller-for-windows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUAR3g-fip7ImA9WxNVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-8175961708621973514</id><published>2009-09-21T10:00:00.001+03:00</published><updated>2009-10-30T11:50:46.656+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T11:50:46.656+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="wx" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>wxRuby → Сайзери (3 частина)</title><content type="html">У &lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-2.html"&gt;попередній частині&lt;/a&gt; ми розглянули &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;. Продовжимо знайомитися з сайзерами &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wx::StaticBoxSizer&lt;/span&gt;&lt;br /&gt;Клас &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; є похідним від &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; і відрізняється від нього тільки тим, що цей сайзер поміщає свої дочірні елементи в рамку з надписом, яка являє собою екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;.&lt;br /&gt;Використання &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; практично нічим не відрізняється від використання класу &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; за виключенням того, що конструктор цього класу вимагає ще один параметр - екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;, який і буде обводити дочірні елементи сайзера.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::StaticBoxSizer.new(Wx::StaticBox box,  Integer orient)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::StaticBoxSizer.new(Integer orient,  Wx::Window parent,&lt;br /&gt;                      String label = '')&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Перший приклад конструктора використовує вже існуючий екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;. Він бере пов'язаний &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt; та орієнтацію(параметр &lt;span style="font-style:italic;"&gt;orient&lt;/span&gt;), яка може бути горизонтальною або вертикальною. Другий конструктор створює новий &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt; із вказаними надписом і батьківським вікном.&lt;br /&gt;&lt;br /&gt;Розглянемо простий приклад &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; разом з двома кнопками.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   static_box = Wx::StaticBox.new(self, :label =&amp;gt; "StaticBox")&lt;br /&gt;   sizer  = Wx::StaticBoxSizer.new(static_box, Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;   button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;   button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;   sizer.add_item(button1)&lt;br /&gt;   sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;   set_sizer(sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі ми спочатку створили екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;, а потім сайзер &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt;, в конструктор якого і передали щойно створений &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;, а також дві кнопки.&lt;br /&gt;&lt;br /&gt;В результаті такого розміщення елементів ми отримали вікно, яке виглядає наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrC_joisQI/AAAAAAAAEro/ekYlBn2nwyQ/s1600-h/sizer01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrC_joisQI/AAAAAAAAEro/ekYlBn2nwyQ/s400/sizer01.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380327102000312578" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Зверніть увагу, що &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt; займає все вікно, так як він є основним сайзером для вікна. Якщо в перший &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; вставити дочірні такі ж сайзери, то вони будуть обводити тільки елементи керування. Давайте додамо ще пару кнопок:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   static_box0 = Wx::StaticBox.new(self, :label =&amp;gt; "StaticBox 0")&lt;br /&gt;   vert_sizer  = Wx::StaticBoxSizer.new(static_box0, Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;   static_box1 = Wx::StaticBox.new(self, :label =&amp;gt; "StaticBox 1")&lt;br /&gt;   static_box2 = Wx::StaticBox.new(self, :label =&amp;gt; "StaticBox 2")&lt;br /&gt;&lt;br /&gt;   sizer_1 = Wx::StaticBoxSizer.new(static_box1, Wx::HORIZONTAL)&lt;br /&gt;   sizer_2 = Wx::StaticBoxSizer.new(static_box2, Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;   vert_sizer.add(sizer_1)&lt;br /&gt;   vert_sizer.add_item(sizer_2, :flag =&amp;gt; Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)&lt;br /&gt;  &lt;br /&gt;   button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;   button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;   button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;   button4 = Wx::Button.new(self, :label =&amp;gt; 'Button 4')&lt;br /&gt;&lt;br /&gt;   sizer_1.add_item(button1)&lt;br /&gt;   sizer_1.add_item(button2)&lt;br /&gt;  &lt;br /&gt;   sizer_2.add_item(button3)&lt;br /&gt;   sizer_2.add_item(button4)&lt;br /&gt;&lt;br /&gt;   set_sizer(vert_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тут ми створили три екземпляри класу &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; і передали кожному по своєму екземпляру класу &lt;span style="font-style:italic;"&gt;Wx::StaticBox&lt;/span&gt;. В перший вертикальний сайзер ми додали ще два горизонтальні сайзери(&lt;span style="font-style:italic;"&gt;sizer_1&lt;/span&gt; та &lt;span style="font-style:italic;"&gt;sizer_2&lt;/span&gt;). Перший буде прив'язаний по замовчуванню до лівого краю, а другий ми перенесли в правий нижній кут, вказавши прапорці &lt;span style="font-style:italic;"&gt;Wx::ALIGN_RIGHT&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;Wx::ALIGN_BOTTOM&lt;/span&gt;. Насправді прапорець &lt;span style="font-style:italic;"&gt;Wx::ALIGN_BOTTOM&lt;/span&gt; не буде відігравати тут ніякої ролі, оскільки друга "полиця" &lt;span style="font-style:italic;"&gt;vert_sizer&lt;/span&gt; по висоті буде обмежена саме цим другим сайзером &lt;span style="font-style:italic;"&gt;sizer_2&lt;/span&gt;. Але цей прапорець дасть нам зрозуміти істинні розміри головного сайзера &lt;span style="font-style:italic;"&gt;vert_sizer&lt;/span&gt;, тому що розмір його рамки може ввести в оману.&lt;br /&gt;В результаті виконання цього прикладу ми побачимо:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrDyASpAKI/AAAAAAAAErw/RnDH8eTlCNM/s1600-h/sizer10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrDyASpAKI/AAAAAAAAErw/RnDH8eTlCNM/s400/sizer10.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380327968686538914" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Для більшої наочності приведу знімок вікна з ОС Windows:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrD9ADdi2I/AAAAAAAAEr4/YQoiaS9QfDA/s1600-h/sizer11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 200px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrD9ADdi2I/AAAAAAAAEr4/YQoiaS9QfDA/s400/sizer11.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380328157601434466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І щоб було більш зрозуміло, те ж вікно з намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrEJLTTAMI/AAAAAAAAEsA/moBc-y3VDfM/s1600-h/sizer12.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrEJLTTAMI/AAAAAAAAEsA/moBc-y3VDfM/s400/sizer12.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380328366779072706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як бачите, вкладені сайзери зайняли не всю доступну область, на відміну від головного сайзера &lt;span style="font-style:italic;"&gt;vert_sizer&lt;/span&gt;.&lt;br /&gt;На цьому огляд &lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt; закінчимо і перейдемо до огляду інших сайзерів.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wx::GridSizer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt; розміщує елементи керування (або дочірні сайзери) в комірках віртуальної таблиці. Віртуальної, тому що насправді ніякої таблиці не створюється. Розміри всіх комірок у цій таблиці однакові як по ширині, так і по висоті. При цьому розміри комірок залежать від того чи використовується прапорець &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt; для розтягнення сайзера до максимально можливих розмірів. У випадку якщо &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt; не використовується, ширина кожної комірки рівна ширині найбільш широкого елементу керування, а висота, відповідно, рівна висоті найбільш високого. Якщо при додаванні сайзера був встановлений прапорець &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt; (або сайзер є головним для вікна), то вся займана сайзером площа ділиться порівну на кількість рядків і стовпців, необхідних для розміщення елементів.&lt;br /&gt;Для початку розглянемо конструктор &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;GridSizer.new(Integer rows,  Integer cols,  Integer vgap,&lt;br /&gt;             Integer hgap)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;GridSizer.new(Integer cols,  Integer vgap = 0,&lt;br /&gt;             Integer hgap = 0)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Він приймає 4 параметри. &lt;span style="font-style:italic;"&gt;rows&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;cols&lt;/span&gt; визначає кількість рядків і стовпців у сайзері. Якщо який-небудь з цих параметрів рівний нулю, то він буде розрахований виходячи із загальної кількості дочірніх елементів у сайзері, роблячи сайзер динамічно зростаючим. &lt;span style="font-style:italic;"&gt;vgap&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;hgap&lt;/span&gt; - величина зазору між рядками і стовпцями у пікселях, відповідно.&lt;br /&gt;&lt;br /&gt;Розглянемо приклади. Нехай спочатку &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt; буде основним для вікна. Розмістимо 6 кнопок у два рядки і три стовпці:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)&lt;br /&gt;   6.times do |i|&lt;br /&gt;     button = Wx::Button.new(self, :label =&amp;gt; "Button #{i}")&lt;br /&gt;     grid_sizer.add(button)&lt;br /&gt;   end&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrFZAs32UI/AAAAAAAAEsI/YZOsDFn2We0/s1600-h/sizer20.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrFZAs32UI/AAAAAAAAEsI/YZOsDFn2We0/s400/sizer20.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380329738323089730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Так як основний сайзер намагається зайняти якомога більшу область вікна, то у нашому випадку &lt;span style="font-style:italic;"&gt;grid_sizer&lt;/span&gt; займе все вікно, а висота рядків буде рівна висоті клієнтської області вікна, поділеної на кількість рядків. Аналогічно з шириною комірок, вона буде рівна ширині клієнтської області вікна, поділеної на кількість стовпців, необхідних для розміщення дочірніх елементів.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrFn820LcI/AAAAAAAAEsQ/Y25PqOn_cd4/s1600-h/sizer21.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrFn820LcI/AAAAAAAAEsQ/Y25PqOn_cd4/s400/sizer21.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380329994989088194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі ми явно задали кількість рядків і стовпців за допомогою конструктора &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;, але ми би добилися того ж результату, якщо б вказали тільки кількість стовпців, які ми хочемо отримати. У цьому випадку сайзер сам розрахує необхідну кількість рядків. Пізніше ми розглянемо і такий приклад.&lt;br /&gt;А щоб переконатися в тому, що комірки сайзера дійсно займають той розмір, який ми тільки що бачили на малюнку, розтягнемо кожну кнопку на всю комірку за допомогою прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)&lt;br /&gt;   6.times do |i|&lt;br /&gt;     button = Wx::Button.new(self, :label =&amp;gt; "Button #{i}")&lt;br /&gt;     grid_sizer.add_item(button, :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   end&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;І побачимо очікуваний результат:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrGLm_-3UI/AAAAAAAAEsY/duns8Hghm24/s1600-h/sizer22.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrGLm_-3UI/AAAAAAAAEsY/duns8Hghm24/s400/sizer22.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380330607597247810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Наступні експерименти з цим сайзером ми будемо проводити, коли комірки сайзера залежать від розміру елементів керування, які вона містить. Тому підготуємо наступний приклад, у якому &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt; не буде розтягуватися на все вікно, а буде знаходитися всередині сайзера &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(6) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   button_list.each do |button|&lt;br /&gt;     grid_sizer.add_item(button)&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   box_sizer.add(grid_sizer)&lt;br /&gt;   set_sizer(box_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі для зручності кнопки створюються заздалегідь і поміщаються у масив, щоб в майбутньому ми могли незалежно одна від одної змінювати їх властивості. Основним тут є &lt;span style="font-style:italic;"&gt;box_sizer&lt;/span&gt;, а &lt;span style="font-style:italic;"&gt;grid_sizer&lt;/span&gt; "приклеєний" до верхнього лівого кута. Якщо ми запустимо цей скрипт, то побачимо таке розташування кнопок:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrGs2ljZVI/AAAAAAAAEsg/ZM0qRMbQBL0/s1600-h/sizer30.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrGs2ljZVI/AAAAAAAAEsg/ZM0qRMbQBL0/s400/sizer30.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380331178717046098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як і варто було очікувати, розміри комірок однакові і співпадають із розмірами кнопок.&lt;br /&gt;&lt;br /&gt;А тепер змінимо мінімально можливий розмір однієї кнопки і подивимося як зміняться розміри комірок таблиці:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(6) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;   button_list[0].set_min_size([100, 35])&lt;br /&gt;&lt;br /&gt;   button_list.each do |button|&lt;br /&gt;     grid_sizer.add_item(button)&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   box_sizer.add(grid_sizer)&lt;br /&gt;   set_sizer(box_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrHQvtpP2I/AAAAAAAAEso/fOq8pHwxSLM/s1600-h/sizer31.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrHQvtpP2I/AAAAAAAAEso/fOq8pHwxSLM/s400/sizer31.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380331795347226466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Всі розміри комірок знову рівні, але на цей раз співпадають з розміром найбільшої кнопки &lt;span style="font-style:italic;"&gt;"Button 0"&lt;/span&gt;. Таблицю комірок сайзера у цьому випадку можна намалювати наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrHa-PbQ9I/AAAAAAAAEsw/KGoO0Q0wGWc/s1600-h/sizer32.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrHa-PbQ9I/AAAAAAAAEsw/KGoO0Q0wGWc/s400/sizer32.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380331971045704658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;В наступному прикладі розтягнемо всі кнопки за допомогою прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;, щоб переконатися, що розміри комірок саме такі, як ми їх представляли:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 3, rows = 2)&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(6) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;   button_list[0].set_min_size([100, 35])&lt;br /&gt;&lt;br /&gt;   button_list.each do |button|&lt;br /&gt;     grid_sizer.add_item(button, :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   box_sizer.add(grid_sizer)&lt;br /&gt;   set_sizer(box_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrH9YuGH0I/AAAAAAAAEs4/o3IbMD4ofa8/s1600-h/sizer33.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrH9YuGH0I/AAAAAAAAEs4/o3IbMD4ofa8/s400/sizer33.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380332562269216578" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тепер розглянемо параметри &lt;span style="font-style:italic;"&gt;vgap&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;hgap&lt;/span&gt;, які задають відстань між елементами керування. Найпростіше ці параметри уявити у вигляді товщини стінок, які розділяють елементи, але при цьому зовнішні стінки сайзера-таблиці залишаються нульової товщини.&lt;br /&gt;&lt;br /&gt;У наступному прикладі ми додамо 10 пікселів відстані між рядками і 20 пікселів між стовпцями:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(rows = 2, cols = 3, vgap = 10, hgap = 20)&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(6) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   button_list.each do |button|&lt;br /&gt;     grid_sizer.add_item(button)&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   box_sizer.add(grid_sizer)&lt;br /&gt;   set_sizer(box_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В результаті отримаємо:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrId8VJo-I/AAAAAAAAEtA/lmPDC4S7s_8/s1600-h/sizer34.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrId8VJo-I/AAAAAAAAEtA/lmPDC4S7s_8/s400/sizer34.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380333121584079842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Схожого ефекту можна було б досягнути, використовуючи прапорці, які додають рамку(&lt;span style="font-style:italic;"&gt;border&lt;/span&gt;) навкруги елементу: &lt;span style="font-style:italic;"&gt;Wx::TOP&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;Wx::BOTTOM&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;Wx::LEFT&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;Wx::RIGHT&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;Wx::ALL&lt;/span&gt;, але в даному випадку використовувати параметри &lt;span style="font-style:italic;"&gt;vgap&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;hgap&lt;/span&gt; зручніше, інакше довелось би для кожної кнопки індивідуально вказувати з якої сторони повинна бути рамка. Крім того, рамка змінила б розміри комірок.&lt;br /&gt;&lt;br /&gt;У попередніх приклад ми явно задавали кількість рядків і стовпців таблиці, але ж, знаючи кількість елементів і кількість бажаних стовпців, &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt; може сам розраховувати кількість необхідних рядків. Давайте розглянемо як він це буде робити:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   box_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   grid_sizer = Wx::GridSizer.new(cols = 2)&lt;br /&gt;&lt;br /&gt;   count = 1&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   button_list.each do |button|&lt;br /&gt;     grid_sizer.add_item(button)&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;   box_sizer.add(grid_sizer)&lt;br /&gt;   set_sizer(box_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі ми будемо змінювати кількість кнопок від 1 до 5, і за допомогою зміни значення змінної count.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;count = 1&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrJW5Gj9xI/AAAAAAAAEtI/jNDf4M0KRrA/s1600-h/sizer41.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrJW5Gj9xI/AAAAAAAAEtI/jNDf4M0KRrA/s400/sizer41.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380334099970127634" /&gt;&lt;/a&gt;&lt;br /&gt;Нічого цікавого, одна кнопка вона і є одна кнопка.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;count = 2&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrJkXOptQI/AAAAAAAAEtQ/2AKGdXpoXfE/s1600-h/sizer42.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrJkXOptQI/AAAAAAAAEtQ/2AKGdXpoXfE/s400/sizer42.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380334331395421442" /&gt;&lt;/a&gt;&lt;br /&gt;Тепер вже сайзер може зайняти два стовпці, що він і робить. У нас виходить один рядок.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;count = 3&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrJ0pz7f3I/AAAAAAAAEtY/kTcJdxZVq2M/s1600-h/sizer43.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrJ0pz7f3I/AAAAAAAAEtY/kTcJdxZVq2M/s400/sizer43.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380334611261521778" /&gt;&lt;/a&gt;&lt;br /&gt;У нас з'являється другий рядок, але зверніть увагу на те, що спочатку заповнюється перший стовпчик, а потім другий.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;count = 4&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrKC7zoTMI/AAAAAAAAEtg/I4FlHXagHFU/s1600-h/sizer44.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrKC7zoTMI/AAAAAAAAEtg/I4FlHXagHFU/s400/sizer44.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380334856610270402" /&gt;&lt;/a&gt;&lt;br /&gt;Ну і на кінець ми заповнили два стовпчика, і в нас з'явилося два рядки.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;сount = 5&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrKSFeKzbI/AAAAAAAAEto/JV-Q7rc3LQg/s1600-h/sizer45.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrKSFeKzbI/AAAAAAAAEto/JV-Q7rc3LQg/s400/sizer45.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380335116902649266" /&gt;&lt;/a&gt;&lt;br /&gt;Можна і далі збільшувати значення змінної &lt;span style="font-style:italic;"&gt;count&lt;/span&gt; - кількість рядків буде збільшуватися, але завжди в першу чергу буде повністю заповнюватися спочатку перший стовпчик, а потім другий.&lt;br /&gt;&lt;br /&gt;Мабуть, це всі основні особливості класу &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;, давайте перейдемо до розгляду наступного сайзера.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wx::FlexGridSizer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::FlexGridSizer&lt;/span&gt; по поведінці схожий на &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;, він також розміщує елементи керування в комірках таблиці, але, на відміну від &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt; у &lt;span style="font-style:italic;"&gt;Wx::FlexGridSizer&lt;/span&gt; рядки і стовпці можуть розтягуватися, щоб займати весь вільний простір по вертикалі чи горизонталі.&lt;br /&gt;&lt;br /&gt;Конструктор класу &lt;span style="font-style:italic;"&gt;Wx::FlexGridSizer&lt;/span&gt; нічим не відрізняється від конструктора &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::FlexGridSizer.new(Integer rows,  Integer cols,  Integer vgap,&lt;br /&gt;                     Integer hgap)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::FlexGridSizer.new(Integer cols,  Integer vgap = 0,&lt;br /&gt;                     Integer hgap = 0)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Для того щоб скористатися особливостями цього сайзера і встановити, які рядки і стовпці повинні розтягуватись передбачено, відповідно, два методи:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::FlexGridSizer#add_growable_row(Integer idx,  Integer proportion = $0$)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::FlexGridSizer#add_growable_col(Integer idx,  Integer proportion = $0$)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ці методи приймають 2 параметри:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;idx&lt;/span&gt; - номер рядка або стовпчика, починаючи з 0-ого, який повинен розтягуватись&lt;br /&gt;&lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt; - пропорції, які визначають як потрібно розподілити вільне місце між розтяжними рядками і стовпцями. Цей параметр грає ту ж роль, що і однойменний параметр методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Розглянемо цю поведінку на прикладах.&lt;br /&gt;Для початку створимо &lt;span style="font-style:italic;"&gt;Wx::FlexGridSizer&lt;/span&gt;, який не має розтяжних рядків і стовпців. У цьому випадку всі комірки мають мінімально можливий розмір, навіть не дивлячись на те, що сайзер встановлений як основний для вікна.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 2)&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1])&lt;br /&gt;   grid_sizer.add_item(button_list[2])&lt;br /&gt;   grid_sizer.add_item(button_list[3])&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrMLfvdq4I/AAAAAAAAEtw/2lkx-SJF4m4/s1600-h/sizer50.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrMLfvdq4I/AAAAAAAAEtw/2lkx-SJF4m4/s400/sizer50.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380337202718681986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;А тепер змінимо приклад так, щоб другий стовпчик був "тягучим".&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 2)&lt;br /&gt;   grid_sizer.add_growable_col(1)&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[2])&lt;br /&gt;   grid_sizer.add_item(button_list[3], :flag =&amp;gt; Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrMeVoEhvI/AAAAAAAAEt4/l6XzHPKXtIE/s1600-h/sizer51.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 206px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrMeVoEhvI/AAAAAAAAEt4/l6XzHPKXtIE/s400/sizer51.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380337526420834034" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі ми за допомогою виклику методу &lt;span style="font-style:italic;"&gt;grid_sizer.add_growable_col(1)&lt;/span&gt; вказуємо, що другий стовпчик (перший рахується нульовим) повинен розтягнутися так, щоб зайняти вільне місце. Щоб переконатися у цьому, ми другу кнопку(&lt;span style="font-style:italic;"&gt;button_list[1]&lt;/span&gt;) розтягуємо на всю комірку за допомогою прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;, а останню кнопку вирівнюємо по правому краю (&lt;span style="font-style:italic;"&gt;Wx::ALIGN_RIGHT&lt;/span&gt;) і нижньому краю (&lt;span style="font-style:italic;"&gt;Wx::ALIGN_BOTTOM&lt;/span&gt;). У даному випадку вирівнювання по нижньому краю нічого не дасть, так як розтягується тільки другий стовпчик, а не рядок, але завдяки цьому ми ще раз переконалися, що вертикальний розмір рядка не змінився.&lt;br /&gt;&lt;br /&gt;Тепер розглянемо розтягування рядків.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 2)&lt;br /&gt;   grid_sizer.add_growable_row(1)&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1])&lt;br /&gt;   grid_sizer.add_item(button_list[2], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[3], :flag =&amp;gt; Wx::ALIGN_RIGHT|Wx::ALIGN_BOTTOM)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі за допомогою виклику метода &lt;span style="font-style:italic;"&gt;grid_sizer.add_growable_row(1)&lt;/span&gt; ми вказуємо, що другий рядок повинен розтягуватись. На цей раз розтягуватись на всю комірку буде кнопка &lt;span style="font-style:italic;"&gt;button_list[2]&lt;/span&gt;, а прапорці для &lt;span style="font-style:italic;"&gt;button_list[3]&lt;/span&gt; залишаться ті самі. І у результаті отримаємо:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrNTtCd0aI/AAAAAAAAEuA/mHP07TIVXLU/s1600-h/sizer52.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 360px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqrNTtCd0aI/AAAAAAAAEuA/mHP07TIVXLU/s400/sizer52.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380338443238625698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Крім того для одного сайзера можна вказати, декілька розтяжних рядків і(або) стовпців. У наступному прикладі ми створимо 6 кнопок, розміщених у два рядки і три стовпці, і вкажемо, що останні два стовпці повинні розтягуватися. Для кнопок, які повинні потрапити у ці два стовпці ми встановимо прапорець &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;, щоб розтягнути їх на всю комірку.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 3)&lt;br /&gt;   grid_sizer.add_growable_col(1)&lt;br /&gt;   grid_sizer.add_growable_col(2)&lt;br /&gt;&lt;br /&gt;   count = 6&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[2], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[3])&lt;br /&gt;   grid_sizer.add_item(button_list[4], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[5], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrNzYQcw_I/AAAAAAAAEuI/HTGAEuKprhc/s1600-h/sizer53.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 206px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrNzYQcw_I/AAAAAAAAEuI/HTGAEuKprhc/s400/sizer53.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380338987415946226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;В даному випадку розтяжні стовпці поділити порівну доступне їм вільне місце. Щоб змінити співвідношення вільного місця між стовпчиками змінимо значення параметрів &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;. В наступному прикладі співвідношення останніх двох стовпців буде рівне 1:3.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 3)&lt;br /&gt;   grid_sizer.add_growable_col(1, proportion = 1)&lt;br /&gt;   grid_sizer.add_growable_col(2, proportion = 3)&lt;br /&gt;&lt;br /&gt;   count = 6&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[2], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[3])&lt;br /&gt;   grid_sizer.add_item(button_list[4], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;   grid_sizer.add_item(button_list[5], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrOMG2ZrfI/AAAAAAAAEuQ/paOEGvMxjfw/s1600-h/sizer54.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 148px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrOMG2ZrfI/AAAAAAAAEuQ/paOEGvMxjfw/s400/sizer54.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380339412240018930" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І останній для цього розділу приклад показує, що на деякі комірки може припадати пересічення розтяжних рядків і стовпців.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::FlexGridSizer.new(cols = 2)&lt;br /&gt;   grid_sizer.add_growable_col(1)&lt;br /&gt;   grid_sizer.add_growable_row(1)&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add_item(button_list[0])&lt;br /&gt;   grid_sizer.add_item(button_list[1])&lt;br /&gt;   grid_sizer.add_item(button_list[2], :flag =&amp;gt; Wx::ALIGN_BOTTOM)&lt;br /&gt;   grid_sizer.add_item(button_list[3], :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В результаті бачимо, остання кнопка, яка опинилася на пересічені розтяжних стовпчика і рядка значно додала у розмірах: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrOkFF1hpI/AAAAAAAAEuY/xZuSSDtDC54/s1600-h/sizer55.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrOkFF1hpI/AAAAAAAAEuY/xZuSSDtDC54/s400/sizer55.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380339824084747922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wx::GridBagSizer&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::GridBagSizer&lt;/span&gt;, як і два попередніх сайзера розставляє елементи керування в комірках таблиці. Відмінність полягає у тому, що, на відміну від попередніх сайзерів, цей сайзер не розраховує кількість стовпчиків виходячи з кількості рядків, а при додаванні елементу програміст повинен явно вказати у яку комірку він хоче помістити елемент. Крім того один елемент керування може займати відразу декілька комірок. Всі комірки при цьому мають однаковий розмір, а сам сайзер не розтягується на все вікно, його комірки завжди мають мінімально можливий розмір.&lt;br /&gt;Конструктор &lt;span style="font-style:italic;"&gt;Wx::GridBagSizer&lt;/span&gt; має наступний вигляд:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::GridBagSizer.new(Integer vgap = 0,  Integer hgap = 0)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У ньому ми не можемо задати кількість рядків і стовпців, ми можемо вказати тільки зазори між рядками і стовпцями сайзера.Метод &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt; цього сайзера теж змінився:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::SizerItem add(Wx::Window window,  GBPosition pos,&lt;br /&gt;             Wx::GBSpan span = DefaultSpan,&lt;br /&gt;             Integer flag = 0,&lt;br /&gt;             Integer border = 0,&lt;br /&gt;             Object userData = nil)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::SizerItem add(Wx::Sizer sizer,  Wx::GBPosition pos,&lt;br /&gt;             Wx::GBSpan span = DefaultSpan,&lt;br /&gt;             Integer flag = 0,&lt;br /&gt;             Integer border = 0,&lt;br /&gt;             Object userData = nil)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::SizerItem add(Integer width,  Integer height,&lt;br /&gt;             Wx::GBPosition pos,&lt;br /&gt;             Wx::GBSpan span = DefaultSpan,&lt;br /&gt;             Integer flag = 0,&lt;br /&gt;             Integer border = 0,&lt;br /&gt;             Object userData = nil)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::SizerItem add(GBSizerItem item)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В ньому додалося два параметри:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;pos&lt;/span&gt; визначає в яку комірку повинен додаватися елемент. Цей параметр повинен бути екземпляром класу Wx::GBPosition.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::GBPosition.new(Integer row,  Integer col)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;span&lt;/span&gt; визначає скільки комірок по горизонталі і вертикалі повинен займати елемент, що додається. Цей параметр повинен бути екземпляром класу &lt;span style="font-style:italic;"&gt;Wx::GBSpan&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;GBSpan.new(Integer rowspan,  Integer colspan)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;(1, 1)&lt;/span&gt; - значення по замовчуванню, яке означає, що елемент буде займати одну комірку у будь-якому напрямку.&lt;br /&gt;&lt;br /&gt;Зауважте, що ми ніде не вказуємо ні загальної кількості рядків, ні загальної кількості стовпчиків. Вони обчислюються виходячи із розташування доданих елементів.&lt;br /&gt;В якості прикладу для початку отримаємо таке розміщення кнопок у вікні:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrQP-gZ88I/AAAAAAAAEug/Jj9rAkXrfxw/s1600-h/sizer60.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrQP-gZ88I/AAAAAAAAEug/Jj9rAkXrfxw/s400/sizer60.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380341677743010754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ми могли б отримати таке розміщення використовуючи сайзер &lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;, якщо б деякі комірки заповнили порожніми місцями (додали б екземпляри класу &lt;span style="font-style:italic;"&gt;Wx::Size&lt;/span&gt;), але в &lt;span style="font-style:italic;"&gt;Wx::GridBagSizer&lt;/span&gt; це реалізувати простіше:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::GridBagSizer.new()&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add(button_list[0], pos = Wx::GBPosition.new(0, 1))&lt;br /&gt;   grid_sizer.add(button_list[1], pos = Wx::GBPosition.new(1, 0))&lt;br /&gt;   grid_sizer.add(button_list[2], pos = Wx::GBPosition.new(1, 2))&lt;br /&gt;   grid_sizer.add(button_list[3], pos = Wx::GBPosition.new(2, 1))&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;При додаванні кнопки в сайзер ми просто вказуємо куди саме її необхідно помістити. На наступному малюнку показане те саме вікно з намальованою таблицею сайзера:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrQu2QDLQI/AAAAAAAAEuo/P070n4yyVlU/s1600-h/sizer61.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrQu2QDLQI/AAAAAAAAEuo/P070n4yyVlU/s400/sizer61.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380342208102870274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тепер скористаємося особливостями цього сайзера і зробимо так, щоб кнопки зайняли би не одну, а дві комірки віртуальної таблиці:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrQ6JGlUCI/AAAAAAAAEuw/Mf7LDfDw6Zo/s1600-h/sizer62.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqrQ6JGlUCI/AAAAAAAAEuw/Mf7LDfDw6Zo/s400/sizer62.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380342402141999138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Для цього під час додавання нульової і другої кнопки вкажемо скільки комірок вони повинні займати в обох напрямках за допомогою параметра &lt;span style="font-style:italic;"&gt;span&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;   grid_sizer = Wx::GridBagSizer.new()&lt;br /&gt;&lt;br /&gt;   count = 4&lt;br /&gt;&lt;br /&gt;   button_list = Array.new(count) {|i| Wx::Button.new(self, :label =&amp;gt; "Button #{i}")}&lt;br /&gt;&lt;br /&gt;   grid_sizer.add(button_list[0], pos = Wx::GBPosition.new(0, 1),&lt;br /&gt;                  span = Wx::GBSpan.new(1, 2),&lt;br /&gt;                  flag = Wx::EXPAND)&lt;br /&gt;   grid_sizer.add(button_list[1], pos = Wx::GBPosition.new(1, 0),&lt;br /&gt;                  span = Wx::GBSpan.new(1, 1),&lt;br /&gt;                  flag = Wx::EXPAND)&lt;br /&gt;   grid_sizer.add(button_list[2], pos = Wx::GBPosition.new(1, 2),&lt;br /&gt;                  span = Wx::GBSpan.new(2, 1),&lt;br /&gt;                  flag = Wx::EXPAND)&lt;br /&gt;   grid_sizer.add(button_list[3], pos = Wx::GBPosition.new(2, 1),&lt;br /&gt;                  span = Wx::GBSpan.new(1, 1),&lt;br /&gt;                  flag = Wx::EXPAND)&lt;br /&gt;&lt;br /&gt;   set_sizer(grid_sizer)&lt;br /&gt; end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Як бачите все доволі просто. У цьому прикладі ми розтягнули всі кнопки (навіть ті, на які цей прапорець не подіє), щоб показати, що кнопки дійсно можуть зайняти не тільки свою, а й сусіді комірки. У цьому прикладі для наочності використовуються параметри &lt;span style="font-style:italic;"&gt;span&lt;/span&gt;, навіть для тих, що для них залишене значення по замовчуванню.&lt;br /&gt;&lt;br /&gt;Для наочності на наступному малюнку те ж саме вікно, але з намальованим сайзером:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrRXgnMqKI/AAAAAAAAEu4/qJt7hbwT_DA/s1600-h/sizer63.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqrRXgnMqKI/AAAAAAAAEu4/qJt7hbwT_DA/s400/sizer63.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380342906669017250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ось ми і розглянули всі існуючі в &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt; сайзери, а заодно і навчилися ними користуватися.&lt;br /&gt;&lt;br /&gt;Основою для написання цієї і попередніх частин(&lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-1.html"&gt;1&lt;/a&gt;, &lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-2.html"&gt;2&lt;/a&gt;) стала стаття &lt;a href="http://jenyay.net/Programming/WxSizer"&gt;Сайзеры в wxWidgets / wxPython&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;На все добре і успіхів.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-8175961708621973514?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/8175961708621973514/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=8175961708621973514" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8175961708621973514?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8175961708621973514?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/TfVU8c3VtuA/wxruby-3.html" title="wxRuby → Сайзери (3 частина)" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqrC_joisQI/AAAAAAAAEro/ekYlBn2nwyQ/s72-c/sizer01.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/wxruby-3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUcBSX45eSp7ImA9WxNRF0Q.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-6847126589986420456</id><published>2009-09-13T00:00:00.002+03:00</published><updated>2009-09-13T01:04:18.021+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-13T01:04:18.021+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="life" /><title>З Днем програміста!</title><content type="html">&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;irb(main):001:0&amp;gt; require 'date'&lt;br /&gt;=&amp;gt; true&lt;br /&gt;irb(main):002:0&amp;gt; (Date.new(2009) + 255).to_s&lt;br /&gt;=&amp;gt; &amp;quot;2009-09-13&amp;quot;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqwY6oHfcTI/AAAAAAAAEvQ/RjlkSxV-7h8/s1600-h/header.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 400px; height: 195px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqwY6oHfcTI/AAAAAAAAEvQ/RjlkSxV-7h8/s400/header.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5380703050281218354" /&gt;&lt;/a&gt;&lt;br /&gt;День програмі́ста — офіційне професійне свято програмістів, яке відзначають у 256-й день року (255-й з нуля). У високосний рік це 12 вересня, а у невисокосний — 13 вересня.&lt;br /&gt;Таку нетрадиційну дату було вибрано через те, що число 256 відповідає кількості чисел, яку можна виразити за допомогою вісімкового байта, це — від 0 до 255 (двійкова система: 11111111), які можна представити за допомогою одного байта, який складається з 8 бітів, котрі в свою чергу можуть мати значення 0 або 1, тобто — 2&lt;sup&gt;8&lt;/sup&gt; випадків. Також 256 у шістнадцятковій системі числення це 100 (0x100). А також це максимальна степінь числа 2, яка менша 356 (днів у році).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Вітаю всіх, хто має відношення!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-6847126589986420456?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/6847126589986420456/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=6847126589986420456" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6847126589986420456?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6847126589986420456?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/G5yvRahFJZ8/blog-post.html" title="З Днем програміста!" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqwY6oHfcTI/AAAAAAAAEvQ/RjlkSxV-7h8/s72-c/header.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkIFSHYzeip7ImA9WxNWFU4.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-7331369061866270263</id><published>2009-09-12T02:17:00.004+03:00</published><updated>2009-10-14T17:28:39.882+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-14T17:28:39.882+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="vkontakte" /><title>Keyword:  login.vk.com/?act=login</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sqran_JKKRI/AAAAAAAAEvI/XVfkvR8TcTg/s1600-h/wtf.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 112px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sqran_JKKRI/AAAAAAAAEvI/XVfkvR8TcTg/s400/wtf.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5380353085347080466" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Судячи з активності, або народ переживає, або щось не так...&lt;br /&gt;Доменне ім’я &lt;a href="http://vk.com"&gt;vk.com&lt;/a&gt; віднедавна &lt;a href="http://www.vedomosti.ru/newspaper/article/2009/09/07/213236"&gt;належить&lt;/a&gt; мережі "В контакте". &lt;span style="font-style:italic;"&gt;VK на пути к мировому господству.&lt;/span&gt; А &lt;span style="font-style:italic;"&gt;API&lt;/span&gt; нормальне не можуть надати, так то.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-7331369061866270263?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/7331369061866270263/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=7331369061866270263" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7331369061866270263?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7331369061866270263?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/RJmUJMEYxx0/keyword-loginvkcomactlogin.html" title="Keyword:  login.vk.com/?act=login" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sqran_JKKRI/AAAAAAAAEvI/XVfkvR8TcTg/s72-c/wtf.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/keyword-loginvkcomactlogin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQERn8yfSp7ImA9WxNVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-7344378208754340647</id><published>2009-09-07T19:43:00.044+03:00</published><updated>2009-10-30T11:51:47.195+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T11:51:47.195+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="wx" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>wxRuby → Сайзери (2 частина)</title><content type="html">У &lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-1.html"&gt;попередній статті&lt;/a&gt; ми познайомилися з позиціонуванням віджетів. А тепер перейдемо до найцікавішого, до огляду сайзерів, які є у бібліотеці wxRuby. І на прикладах побачимо, як впливають на розміщення елементів прапорці з методу &lt;span style="font-style:italic;"&gt;Wx::Sizer#add()&lt;/span&gt;.&lt;br /&gt;У якості прикладу розглянемо код, на основі якого ми будемо експериментувати з сайзерами надалі.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;&lt;br /&gt;require 'wx'&lt;br /&gt;&lt;br /&gt;class MainWindow &amp;lt; Wx::Frame&lt;br /&gt;  def initialize&lt;br /&gt;    super(nil, :id =&amp;gt; -1, :title =&amp;gt; '&amp;#1056;&amp;#1086;&amp;#1079;&amp;#1084;&amp;#1110;&amp;#1088; &amp;#1084;&amp;#1072;&amp;#1108; &amp;#1079;&amp;#1085;&amp;#1072;&amp;#1095;&amp;#1077;&amp;#1085;&amp;#1085;&amp;#1103;')&lt;br /&gt;    self.size = [300, 200]&lt;br /&gt;    self.do_sizer&lt;br /&gt;    show&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class SimpleApp &amp;lt; Wx::App&lt;br /&gt;  def on_init&lt;br /&gt;    MainWindow.new&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;app = SimpleApp.new&lt;br /&gt;app.main_loop()&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі оголошується клас вікна &lt;span style="font-style:italic;"&gt;MainWindow&lt;/span&gt;, у конструкторі якого викликається метод &lt;span style="font-style:italic;"&gt;do_sizer()&lt;/span&gt;. Всередині цього методу у майбутніх прикладах відбуватиметься все найцікавіше, в тому сенсі, що у ньому ми і будемо розміщувати елементи керування. Інший код змінюватись не буде, тому в усіх наступних прикладах буде наводитись тільки цей метод.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;У даному прикладі цей метод містить створення порожнього сайзера &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; (без заповнення його елементами керування), і цей сайзер додається у вікно. Запустивши цей приклад, ви побачите порожнє вікно розміром 300x200 пікселів:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU5C89InJI/AAAAAAAAEnI/6Bt5mji7DYE/s1600-h/sizer0.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU5C89InJI/AAAAAAAAEnI/6Bt5mji7DYE/s400/sizer0.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378768052848991378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Wx::BoxSizer&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; є найпростішим сайзером, який дозволяє розміщувати елементи вздовж однієї лінії - по вертикалі або по горизонталі. Конструктор класу &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; приймає один параметр, який вказує як потрібно розміщувати елементи: по вертикалі чи по горизонталі. Відповідно параметр &lt;span style="font-style:italic;"&gt;orient&lt;/span&gt; може приймати два значення: &lt;span style="font-style:italic;"&gt;Wx::HORIZONTAL&lt;/span&gt; або &lt;span style="font-style:italic;"&gt;Wx::VERTICAL&lt;/span&gt;. Підкласи &lt;span style="font-style:italic;"&gt;Wx::HBoxSizer&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;Wx::VBoxSizer&lt;/span&gt; є посиланнями для створення горизонтального і вертикального &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;, відповідно. Наступні рядки еквівалентні:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::HBoxSizer.new&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Якщо &lt;span style="font-style:italic;"&gt;orient = Wx::HORIZONTAL&lt;/span&gt;, то сайзер можна уявити у вигляді книжної полиці, розділеної по горизонталі на комірки, всередині яких розміщені елементи керування. При чому розмір кожної комірки рівний ширині елемента, який міститься всередині з урахуванням рамки(&lt;span style="font-style:italic;"&gt;border&lt;/span&gt;). Якщо при цьому сайзер використовується як основний для вікна(встановлений за допомогою методу &lt;span style="font-style:italic;"&gt;set_sizer()&lt;/span&gt;), то по вертикалі "полиця" буде займати все батьківське вікно. Якщо сайзер буде знаходитись всередині іншого сайзера (і не буде розтягуватись за допомогою прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;), то в цьому випадку його розмір по вертикалі буде обмежений елементом з найбільшою висотою.&lt;br /&gt;&lt;br /&gt;Якщо &lt;span style="font-style:italic;"&gt;orient = Wx::VERTICAL&lt;/span&gt;, то сайзер можна уявити у вигляді книжкової шафки, розділеної на горизонтальні полиці. Тепер вже висота кожної "полиці" рівна розміру, розміщеного у ній елемента (разом із рамкою). Якщо сайзер використовується як основний для вікна, то по горизонталі "шафка" займатиме всю ширину вікна. Інакше її ширина дорівнюватиме ширині найширшого елемента керування.&lt;br /&gt;Розглянемо приклади:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add(button1)&lt;br /&gt;    sizer.add(button2)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі ми створюємо вертикальний &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; і додаємо у нього дві кнопки(&lt;span style="font-style:italic;"&gt;button1&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;button2&lt;/span&gt;). Для всіх параметрів використовуємо значення до замовчуванню. Результат розміщення кнопок:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU67QNOG1I/AAAAAAAAEnQ/n_XbTc67QFs/s1600-h/sizer10.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU67QNOG1I/AAAAAAAAEnQ/n_XbTc67QFs/s400/sizer10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378770119601036114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як ми і очікували, кнопки розмістилися по вертикалі одна під одною. Для кращого розуміння роботи сайзера на наступному малюнку червоним прямокутником намальовані комірки сайзера. Підкреслю, що "фізично", ніяких поличок і комірок у вигляді будь-яких панелей не існує, але така абстракція допоможе легше зрозуміти роботу сайзерів.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU7PEqGx9I/AAAAAAAAEnY/sLV_D9TuF-k/s1600-h/sizer11.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU7PEqGx9I/AAAAAAAAEnY/sLV_D9TuF-k/s400/sizer11.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378770460098349010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як бачите, полиці сайзера зайняли все вікно по горизонталі, і справа є ще вільне місце, яке утворилося завдяки тому, що сайзер є основним для вікна і він намагається зайняти по можливості якомога більше місця. Щоб переконатися у цьому, вирівняємо першу кнопку по правому краю. Для цього будемо використовувати прапорець &lt;span style="font-style:italic;"&gt;Wx::ALIGN_RIGHT&lt;/span&gt; при додаванні &lt;span style="font-style:italic;"&gt;button1&lt;/span&gt;.&lt;br /&gt;Зараз ми познайомимося з методом &lt;span style="font-style:italic;"&gt;Wx::Sizer#add_item()&lt;/span&gt;, який є практично ідентичним до &lt;span style="font-style:italic;"&gt;Wx::Sizer#add()&lt;/span&gt;, але, на відміну від свого брата, додаткові параметри можуть бути визначеними за допомогою ключових слів у будь-якому порядку, наприклад:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sizer.add_item(an_item, :index =&amp;gt; 1, :proportion =&amp;gt; 1, :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :flag =&amp;gt; Wx::ALIGN_RIGHT)&lt;br /&gt;    sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В результаті виконання скрипта ми побачимо наступне вікно:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqU8KTETCPI/AAAAAAAAEng/2P8vQfog5qQ/s1600-h/sizer20.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqU8KTETCPI/AAAAAAAAEng/2P8vQfog5qQ/s400/sizer20.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378771477578582258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Або те саме з намальованим сайзером:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU8PdBSmtI/AAAAAAAAEno/R2EYrxyFrs4/s1600-h/sizer21.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU8PdBSmtI/AAAAAAAAEno/R2EYrxyFrs4/s400/sizer21.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378771566149671634" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тепер подивимось, як поводить себе горизонтальний сайзер. Запустимо скрипт з наступним методом, що встановлює розташування елементів керування:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1)&lt;br /&gt;    sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У результаті отримаємо таке розміщення кнопок:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU8-3DkIEI/AAAAAAAAEnw/-asG8E3eBF0/s1600-h/sizer30.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU8-3DkIEI/AAAAAAAAEnw/-asG8E3eBF0/s400/sizer30.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378772380592382018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І те саме з намальованим сайзером:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU9IFi1k-I/AAAAAAAAEn4/JxTCsEk2ab8/s1600-h/sizer31.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU9IFi1k-I/AAAAAAAAEn4/JxTCsEk2ab8/s400/sizer31.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378772539100468194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Щоб знову ж таки переконатися, що сайзер займає по вертикалі весь розмір вікна, вирівняємо першу кнопку по нижньому краю за допомогою прапорця &lt;span style="font-style:italic;"&gt;Wx::ALIGN_BOTTOM&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1)&lt;br /&gt;    sizer.add_item(button2, :flag =&amp;gt; Wx::ALIGN_BOTTOM)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта (відразу з намальованим сайзером):&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU9nl_g03I/AAAAAAAAEoI/XP4AnZamjrw/s1600-h/sizer41.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU9nl_g03I/AAAAAAAAEoI/XP4AnZamjrw/s400/sizer41.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378773080386622322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Розглянемо відступи навколо елементу. Оточимо другу кнопку межею розміром у 8 пікселів з усіх сторін, а параметр &lt;span style="font-style:italic;"&gt;border&lt;/span&gt; буде рівний 8:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1)&lt;br /&gt;    sizer.add_item(button2, :border =&amp;gt; 8, :flag =&amp;gt; Wx::ALL)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU-Kx67n3I/AAAAAAAAEoQ/6N_sWb1Kgcg/s1600-h/sizer50.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU-Kx67n3I/AAAAAAAAEoQ/6N_sWb1Kgcg/s400/sizer50.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378773684884053874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І те ж вікно з намальованим сайзером:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU-hfUyKNI/AAAAAAAAEoY/pn0YGoTqqYk/s1600-h/sizer51.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU-hfUyKNI/AAAAAAAAEoY/pn0YGoTqqYk/s400/sizer51.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378774075029203154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;А тепер розглянемо приклади, коли всередину одного сайзера додається інший. Для початку розглянемо, як зміниться поведінка сайзера, якщо він буде вкладеним у інший сайзер. Змінимо вищезгаданий приклад з вертикальним сайзером, таким чином, щоб кнопки додавалися не у головний сайзер, а у дочірній, який теж буде вертикальним:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    parent_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;    child_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    child_sizer.add_item(button1, :flag =&amp;gt; Wx::ALIGN_RIGHT)&lt;br /&gt;    child_sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;    parent_sizer.add(child_sizer)&lt;br /&gt;&lt;br /&gt;    set_sizer(parent_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У цьому прикладі для змінної &lt;span style="font-style:italic;"&gt;parent_sizer&lt;/span&gt; ми використовуємо метод &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt;, який приймає не елемент керування, а інший сайзер. В результаті виконання скрипта ми побачимо, що не дивлячись на те, що першу кнопку ми вирівнюємо по правому краю. Вона залишається зліва, так як, на відміну від головного сайзера, дочірній не розтягується на всю ширину вікна.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU_LzxTz1I/AAAAAAAAEog/rtIAbnAp3L0/s1600-h/sizer60.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqU_LzxTz1I/AAAAAAAAEog/rtIAbnAp3L0/s400/sizer60.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378774802072063826" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;На наступному малюнку батьківський сайзер намальований червоним кольором, а дочірній - синім:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU_ZtzDT6I/AAAAAAAAEoo/HAMW2DS276k/s1600-h/sizer61.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU_ZtzDT6I/AAAAAAAAEoo/HAMW2DS276k/s400/sizer61.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378775040986927010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Щоб дочірній сайзер по розмірах співпадав з головним, достатньо його розтягнути, вказавши прапорець &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    parent_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;    child_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    child_sizer.add_item(button1, :flag =&amp;gt; Wx::ALIGN_RIGHT)&lt;br /&gt;    child_sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;    parent_sizer.add(child_sizer)&lt;br /&gt;&lt;br /&gt;    set_sizer(parent_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В результаті ми побачимо вже знайоме нам розміщення кнопок у вікні:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU_0OItihI/AAAAAAAAEow/P3zur1I_1po/s1600-h/sizer70.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqU_0OItihI/AAAAAAAAEow/P3zur1I_1po/s400/sizer70.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378775496344308242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Цікавим може виявитися приклад, який показує, що вкладений сайзер по поведінці нічим не відрізняється від вкладеного елементу керування. У наступному прикладі вкладений сайзер вирівнюється по правому краю разом з усіма кнопками, які він містить:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    parent_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;    child_sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    child_sizer.add_item(button1)&lt;br /&gt;    child_sizer.add_item(button2)&lt;br /&gt;&lt;br /&gt;    parent_sizer.add_item(child_sizer, :flag =&amp;gt; Wx::ALIGN_RIGHT)&lt;br /&gt;&lt;br /&gt;    set_sizer(parent_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVAKrgepsI/AAAAAAAAEo4/1Z_yLxPdjuo/s1600-h/sizer80.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVAKrgepsI/AAAAAAAAEo4/1Z_yLxPdjuo/s400/sizer80.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378775882185746114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І те ж вікно з намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVAa-1d1CI/AAAAAAAAEpA/oSuymYulFm0/s1600-h/sizer81.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVAa-1d1CI/AAAAAAAAEpA/oSuymYulFm0/s400/sizer81.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378776162251953186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;У наступному прикладі чотири кнопки розташовуються в два рядки і в два стовпці:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    vert_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    hor1_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;    hor2_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    vert_sizer.add(hor1_sizer)&lt;br /&gt;    vert_sizer.add(hor2_sizer)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;    button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;    button4 = Wx::Button.new(self, :label =&amp;gt; 'Button 4')&lt;br /&gt;&lt;br /&gt;    hor1_sizer.add(button1)&lt;br /&gt;    hor1_sizer.add(button2)&lt;br /&gt;    &lt;br /&gt;    hor2_sizer.add(button3)&lt;br /&gt;    hor2_sizer.add(button4)&lt;br /&gt;&lt;br /&gt;    set_sizer(vert_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тут структура трохи складніша. По-перше, ми створюємо головний вертикальний сайзер, який буде прив'язаний до вікна і, відповідно, розтягнутий на всю ширину вікна (тому що сайзер вертикальний). В коді він називається &lt;span style="font-style:italic;"&gt;vert_sizer&lt;/span&gt;. Він у нас буде відігравати роль горизонтальних полиць, на кожній з яких може розташовуватись тільки один елемент. Цим елементом у нас буде інший сайзер, вже горизонтальний. На першу полицю ми покладемо сайзер &lt;span style="font-style:italic;"&gt;hor1_sizer&lt;/span&gt;, а на другу -  &lt;span style="font-style:italic;"&gt;hor2_sizer&lt;/span&gt;. Ці горизонтальні сайзери будуть містити в собі кнопки, кожен сайзер по дві кнопки. &lt;span style="font-style:italic;"&gt;hor1_sizer&lt;/span&gt; містить кнопки &lt;span style="font-style:italic;"&gt;button1&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;button2&lt;/span&gt;, а  &lt;span style="font-style:italic;"&gt;hor2_sizer&lt;/span&gt; - &lt;span style="font-style:italic;"&gt;button3&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;button4&lt;/span&gt;.&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVBPzIs-uI/AAAAAAAAEpI/anJthpOxcBs/s1600-h/sizer90.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVBPzIs-uI/AAAAAAAAEpI/anJthpOxcBs/s400/sizer90.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378777069644479202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Те ж вікно із намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVBfoHOrhI/AAAAAAAAEpQ/J5Cdj7zjr9o/s1600-h/sizer91.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVBfoHOrhI/AAAAAAAAEpQ/J5Cdj7zjr9o/s400/sizer91.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378777341563416082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тут червоним кольором намальований вертикальний сайзер &lt;span style="font-style:italic;"&gt;vert_sizer&lt;/span&gt;, а синім і зеленим - горизонтальні сайзери, відповідно, &lt;span style="font-style:italic;"&gt;hor1_sizer&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;hor2_sizer&lt;/span&gt;.&lt;br /&gt;Як видно з малюнка, вертикальний червоний сайзер займає всю ширину вікна, але кожна його комірка прагне зайняти якомога менше місця по вертикалі (при умові, що параметр &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt; методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt; рівний 0). Саме цим розміром і обмежується вертикальний розмір вкладених сайзерів, які, навпаки, намагаються по можливості зменшити свої горизонтальні розміри (при тій же умові), але зайняти якомога більше місця по вертикалі.&lt;br /&gt;&lt;br /&gt;А тепер розглянемо простий приклад, який показує як одні комірки впливають на розміри інших комірок того ж сайзера.&lt;br /&gt;Змінимо попередній приклад і додамо навколо другої кнопки відступи:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    vert_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    hor1_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;    hor2_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    vert_sizer.add(hor1_sizer)&lt;br /&gt;    vert_sizer.add(hor2_sizer)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;    button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;    button4 = Wx::Button.new(self, :label =&amp;gt; 'Button 4')&lt;br /&gt;&lt;br /&gt;    hor1_sizer.add(button1)&lt;br /&gt;    hor1_sizer.add_item(button2, :flag =&amp;gt; Wx::ALL, :border =&amp;gt; 8)&lt;br /&gt;    &lt;br /&gt;    hor2_sizer.add(button3)&lt;br /&gt;    hor2_sizer.add(button4)&lt;br /&gt;&lt;br /&gt;    set_sizer(vert_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта виглядає наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVCX0lAgkI/AAAAAAAAEpY/yfYGdjbfZP0/s1600-h/sizer100.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVCX0lAgkI/AAAAAAAAEpY/yfYGdjbfZP0/s400/sizer100.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378778306982216258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І те ж саме з намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVCiW1l9LI/AAAAAAAAEpg/lb0dGUE3HYA/s1600-h/sizer101.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVCiW1l9LI/AAAAAAAAEpg/lb0dGUE3HYA/s400/sizer101.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378778487977276594" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як видно з малюнку, кнопка &lt;span style="font-style:italic;"&gt;"Button 2"&lt;/span&gt; збільшила висоту і першої комірки сайзера &lt;span style="font-style:italic;"&gt;hor1_sizer&lt;/span&gt;. Тобто, в горизонтального сайзера &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt; всі комірки мають однакову висоту. Аналогічний експеримент можна провести з вертикальним сайзером, у нього всі комірки будуть мати однакову ширину.&lt;br /&gt;&lt;br /&gt;Наступний приклад буде показувати використання прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;, який, нагадаю, вказує, що елемент керування повинен займати все вдоступне місце у комірці. Заодно цей приклад допоможе нам переконатися, що розмір першої комірки &lt;span style="font-style:italic;"&gt;hor1_sizer&lt;/span&gt; дійсно займає все вільне місце. Отже, виправимо трохи попередній приклад:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    vert_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    hor1_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;    hor2_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    vert_sizer.add(hor1_sizer)&lt;br /&gt;    vert_sizer.add(hor2_sizer)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;    button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;    button4 = Wx::Button.new(self, :label =&amp;gt; 'Button 4')&lt;br /&gt;&lt;br /&gt;    hor1_sizer.add_item(button1, :flag =&amp;gt; Wx::EXPAND)&lt;br /&gt;    hor1_sizer.add_item(button2, :flag =&amp;gt; Wx::ALL, :border =&amp;gt; 8)&lt;br /&gt;    &lt;br /&gt;    hor2_sizer.add(button3)&lt;br /&gt;    hor2_sizer.add(button4)&lt;br /&gt;&lt;br /&gt;    set_sizer(vert_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Після запуску скрипта ми побачимо наступне розміщення кнопок у вікні:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVDY9Ox_PI/AAAAAAAAEpo/WXPcBgmg8bs/s1600-h/sizer110.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVDY9Ox_PI/AAAAAAAAEpo/WXPcBgmg8bs/s400/sizer110.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378779425996406002" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І те ж вікно з намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVDkskfimI/AAAAAAAAEpw/kL6fOhcc8L0/s1600-h/sizer111.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVDkskfimI/AAAAAAAAEpw/kL6fOhcc8L0/s400/sizer111.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378779627682499170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Як ми і очікували кнопка &lt;span style="font-style:italic;"&gt;"Button 1"&lt;/span&gt; розтягнулася на всю комірку.&lt;br /&gt;&lt;br /&gt;Повернемося до методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt; класу &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;. Як ви пам'ятаєте, він має один необов'язковий параметр &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;, який визначає у яких співвідношеннях елементи керування одного сайзеру повинні займати вільне місце.&lt;br /&gt;До цього усюди ми неявно використовували значення, прийняте по замовчуванню, тобто &lt;span style="font-style:italic;"&gt;proportion = 0&lt;/span&gt;. У цьому випадку вертикальний сайзер намагається якомога більше зменшити висоту своїх комірок. Якщо значення параметру &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt; відмінне від 0, то поведінка сайзера різко змінюється. В цьому випадку вертикальний сайзер буде займати все вільне місце по вертикалі, а висота кожної комірки буде розраховуватись виходячи з відповідних значень параметра &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Розглянемо приклад з однією кнопкою:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :proportion =&amp;gt; 1)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Розміщення елементів у вікні виглядає наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVEtfbtVbI/AAAAAAAAEp4/EjWrimDeMQA/s1600-h/sizer120.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVEtfbtVbI/AAAAAAAAEp4/EjWrimDeMQA/s400/sizer120.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378780878286443954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тепер єдина комірка сайзера у цьому випадку займає все вікно:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVE6kJdqTI/AAAAAAAAEqA/ZKSN9YhCKe0/s1600-h/sizer121.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVE6kJdqTI/AAAAAAAAEqA/ZKSN9YhCKe0/s400/sizer121.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378781102890395954" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;По горизонталі вона займає все вікно, тому що вертикальний сайзер намагається зайняти якомога більше місця по ширині, а по вертикалі - тому що значення параметра &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt; відмінне від нуля.&lt;br /&gt;&lt;br /&gt;А тепер додамо у той же вертикальний сайзер другу кнопку також із значенням параметра &lt;span style="font-style:italic;"&gt;proportion = 1&lt;/span&gt; :&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :proportion =&amp;gt; 1)&lt;br /&gt;    sizer.add_item(button2, :proportion =&amp;gt; 1)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Вікно з таким розміщенням кнопок буде виглядати наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVF6VPzH2I/AAAAAAAAEqI/9b_90DtZJjM/s1600-h/sizer130.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVF6VPzH2I/AAAAAAAAEqI/9b_90DtZJjM/s400/sizer130.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378782198402064226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Якщо змінити розміри вікна, то висота кнопок збільшиться на однакову кількість пікселів:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVGGT6jUsI/AAAAAAAAEqQ/3gX-fMroD5k/s1600-h/sizer131.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 327px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVGGT6jUsI/AAAAAAAAEqQ/3gX-fMroD5k/s400/sizer131.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378782404202943170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тобто співвідношення між висотами кнопок завжди рівне 1:1, у відповідності з значеннями параметрів &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;.&lt;br /&gt;Змінимо попередній приклад таким чином, щоб висота верхньої кнопки завжди була вдвічі більша нижньої. Для цього встановимо значення &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt; першої кнопки рівне 2:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :proportion =&amp;gt; 2)&lt;br /&gt;    sizer.add_item(button2, :proportion =&amp;gt; 1)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;У результаті отримаємо:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVGgRQkk1I/AAAAAAAAEqY/njUwW4vBlms/s1600-h/sizer132.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVGgRQkk1I/AAAAAAAAEqY/njUwW4vBlms/s400/sizer132.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378782850166592338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Нам залишилося розглянути ще два прапорці, які ми не використовували до цього. Один з них це &lt;span style="font-style:italic;"&gt;Wx::SHAPED&lt;/span&gt;, який вказує, що при зміні розмірів елемент повинен зберігати вихідні співвідношення сторін. Напишемо код для вікна з двома кнопками, одна з яких буде додана в сайзер із використанням прапорця &lt;span style="font-style:italic;"&gt;Wx::SHAPED&lt;/span&gt;. Крім цього ми будемо використовувати значення параметру &lt;span style="font-style:italic;"&gt;proportion = 1&lt;/span&gt;, щоб розмір кнопок змінювався при зміні розмірів вікна.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :proportion =&amp;gt; 1)&lt;br /&gt;    sizer.add_item(button2, :proportion =&amp;gt; 1, :flag =&amp;gt; Wx::SHAPED)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVG9k79VgI/AAAAAAAAEqg/7dW2fgRzjZs/s1600-h/sizer140.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVG9k79VgI/AAAAAAAAEqg/7dW2fgRzjZs/s400/sizer140.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378783353665050114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Якщо змінити розмір вікна, то друга кнопка зменшить не тільки свою висоту, але й ширину, щоб відношення сторін залишилось попереднім:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVHON6H02I/AAAAAAAAEqo/3ty385DMebY/s1600-h/sizer141.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 250px; height: 127px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVHON6H02I/AAAAAAAAEqo/3ty385DMebY/s400/sizer141.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378783639541109602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І коротко розглянемо прапорець &lt;span style="font-style:italic;"&gt;Wx::FIXER_MINSIZE&lt;/span&gt;. Цей прапорець має специфічне призначення. При використанні цього прапорця сайзер не буде враховувати мінімальний розмір елементу, який задається за допомогою методу &lt;span style="font-style:italic;"&gt;set_min_size()&lt;/span&gt;, а буде використовувати мінімальний розмір, встановлений для деяких елементів.&lt;br /&gt;Нехай у нас є кнопка, для якої встановлений мінімальний розмір 200х35:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button1.set_min_size([200, 35])&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тоді ми побачимо наступне розміщення елементів:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVHtkTk-dI/AAAAAAAAEqw/yhc0VRwmlaU/s1600-h/sizer150.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqVHtkTk-dI/AAAAAAAAEqw/yhc0VRwmlaU/s400/sizer150.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378784178129402322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Встановивши прапорець &lt;span style="font-style:italic;"&gt;Wx::FIXED_MINSIZE&lt;/span&gt;, кнопка змінить розмір до звичних значень:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button1.set_min_size([200, 35])&lt;br /&gt;&lt;br /&gt;    sizer.add_item(button1, :flag =&amp;gt; Wx::FIXED_MINSIZE)&lt;br /&gt;&lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVRxLgJu0I/AAAAAAAAEq4/h25ziyBP1f4/s1600-h/sizer151.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVRxLgJu0I/AAAAAAAAEq4/h25ziyBP1f4/s400/sizer151.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378795235307010882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ми розглянули як в комірки сайзера можна додавати елементи керування та інші сайзери. Залишилось розглянути, як додавати порожні комірки. Достатньо у якості перших двох параметрів методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt; передати ширину і висоту, тобто розміри невидимого елементу керування, розмір якого і буде визначати розміри комірки. Розглянемо приклад:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    vert_sizer  = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;&lt;br /&gt;    hor1_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;    hor2_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    vert_sizer.add(hor1_sizer)&lt;br /&gt;    vert_sizer.add(10, 100)&lt;br /&gt;    vert_sizer.add(hor2_sizer)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;    button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;    button4 = Wx::Button.new(self, :label =&amp;gt; 'Button 4')&lt;br /&gt;&lt;br /&gt;    hor1_sizer.add(button1)&lt;br /&gt;    hor1_sizer.add(100, 10)&lt;br /&gt;    hor1_sizer.add(button2)&lt;br /&gt;    &lt;br /&gt;    hor2_sizer.add(button3)&lt;br /&gt;    hor2_sizer.add(100, 10)&lt;br /&gt;    hor2_sizer.add(button4)&lt;br /&gt;&lt;br /&gt;    set_sizer(vert_sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тут між рядками вертикального сайзера, який містить кнопки, ми додаємо порожній рядок, розмір якого задається шириною і висотою у пікселях. В нашому випадку горизонтальний розмір не впливає, так як він менший ширини вікна. А ось вертикальний розмір розсуне полиці з кнопками на 100 пікселів. Аналогічно між комірками горизонтального сайзера додане порожнє місце 100х10, яке розсуне по горизонталі кнопки, але в нашому випадку не буде впливати на вертикальний розмір, так як розмір 10 пікселів буде меншим, ніж вертикальний розмір кнопок. Вікна з таким розміщенням елементів керування виглядає наступним чином:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVSKMtF2XI/AAAAAAAAErA/9Amf3xyOdO4/s1600-h/sizer160.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVSKMtF2XI/AAAAAAAAErA/9Amf3xyOdO4/s400/sizer160.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378795665126447474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І той же малюнок з намальованими сайзерами:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVSUodmH9I/AAAAAAAAErI/3AINjY55Lts/s1600-h/sizer161.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqVSUodmH9I/AAAAAAAAErI/3AINjY55Lts/s400/sizer161.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378795844376338386" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Крім того в класі &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt; є допоміжний метод &lt;span style="font-style:italic;"&gt;add_spacer()&lt;/span&gt;, який дозволяє спростити додавання порожніх комірок, у яких ширина рівна висоті.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;add_spacer(Integer size)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;В якості параметра задається сторона квадрата. Наступні два рядки рівносильні:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sizer.add(20, 20)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sizer.add_spacer(20)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Також ви можете вставити порожній простір між елементами (наприклад між двома кнопками) за допомогою методу &lt;span style="font-style:italic;"&gt;add_stretch_spacer()&lt;/span&gt;, і змусити цей простір розтягуватись за допомогою параметру &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;. У результаті ліва кнопка буде притиснена до лівої стінки сайзера, а права - до правої, а простір між ними буде тягучим під час зміни розмірів вікна.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  def do_sizer&lt;br /&gt;    sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)&lt;br /&gt;&lt;br /&gt;    button1 = Wx::Button.new(self, :label =&amp;gt; 'Button 1')&lt;br /&gt;    button2 = Wx::Button.new(self, :label =&amp;gt; 'Button 2')&lt;br /&gt;    button3 = Wx::Button.new(self, :label =&amp;gt; 'Button 3')&lt;br /&gt;&lt;br /&gt;    sizer.add(button1)&lt;br /&gt;    sizer.add_stretch_spacer&lt;br /&gt;    sizer.add(button2)&lt;br /&gt;    sizer.add(button3)&lt;br /&gt;    &lt;br /&gt;    set_sizer(sizer)&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVTQBA1M2I/AAAAAAAAErQ/7x1IgLky1PI/s1600-h/sizer170.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVTQBA1M2I/AAAAAAAAErQ/7x1IgLky1PI/s400/sizer170.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378796864578859874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;І той же малюнок із намальованим сайзером:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVTZ8QI1eI/AAAAAAAAErY/5Hy43050J-U/s1600-h/sizer171.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 308px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqVTZ8QI1eI/AAAAAAAAErY/5Hy43050J-U/s400/sizer171.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378797035099575778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Якщо змінити розмір вікна, то перша кнопка залишиться притисненою до лівого краю, а друга і третя - до правого:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVTjO3pw1I/AAAAAAAAErg/0ZyOLuyAWxI/s1600-h/sizer173.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 206px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SqVTjO3pw1I/AAAAAAAAErg/0ZyOLuyAWxI/s400/sizer173.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378797194715972434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Ось ми і розглянули всі можливі прапорці і параметри, які використовуються для додавання елементів у сайзер. Заодно і познайомилися з сайзером &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;. У наступній статті ми оглянемо інші сайзерами, які є у &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;На все добре і успіхів.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-7344378208754340647?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/7344378208754340647/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=7344378208754340647" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7344378208754340647?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7344378208754340647?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/1o7SAf3TMIk/wxruby-2.html" title="wxRuby → Сайзери (2 частина)" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqU5C89InJI/AAAAAAAAEnI/6Bt5mji7DYE/s72-c/sizer0.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/wxruby-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEQBQ3w7fyp7ImA9WxNVGEQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-6596431412966910305</id><published>2009-09-05T14:29:00.015+03:00</published><updated>2009-10-30T11:52:32.207+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-30T11:52:32.207+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="wx" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>wxRuby → Сайзери (1 частина)</title><content type="html">Під час створення графічного інтерфейсу, вам потрібно займатися розміщенням елементів на формі. Наприклад, вам може знадобитись текстове поле і кнопка справа під ним. Ви можете розмістити ці елементи керування(&lt;span style="font-style:italic;"&gt;Wx::TextCrt&lt;/span&gt; і &lt;span style="font-style:italic;"&gt;Wx::Button&lt;/span&gt;), чітко вказавши позицію і розміри у пікселях. Ймовірно це не найкраща ідея, але ви можете зробити це у будь-якому випадку:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;&lt;br /&gt;require 'wx'&lt;br /&gt;&lt;br /&gt;class HelloFrame &amp;lt; Wx::Frame&lt;br /&gt;  def initialize&lt;br /&gt;    super(nil, :id =&amp;gt; -1, :title =&amp;gt; 'Hello World!', :size =&amp;gt; [200, 200])&lt;br /&gt;    text = Wx::TextCtrl.new(self, :id =&amp;gt; -1,&lt;br /&gt;                                  :text =&amp;gt; 'Type in here',&lt;br /&gt;                                  :pos =&amp;gt; [0, 0],&lt;br /&gt;                                  :size =&amp;gt; [200, 175],&lt;br /&gt;                                  :style =&amp;gt; Wx::TE_MULTILINE)&lt;br /&gt;    button = Wx::Button.new(self, :id =&amp;gt; -1,&lt;br /&gt;                                  :label =&amp;gt; 'Press me',&lt;br /&gt;                                  :pos =&amp;gt; [100, 175],&lt;br /&gt;                                  :size =&amp;gt; [100, 25])&lt;br /&gt;&lt;br /&gt;    show&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class HelloApp &amp;lt; Wx::App&lt;br /&gt;  def on_init&lt;br /&gt;    HelloFrame.new&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;app = HelloApp.new&lt;br /&gt;app.main_loop()&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Результат виконання скрипта:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqJMTqEjlMI/AAAAAAAAEmQ/xtSlj6X57Eo/s1600-h/img01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 208px; height: 233px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqJMTqEjlMI/AAAAAAAAEmQ/xtSlj6X57Eo/s400/img01.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5377944805628417218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Чому це погана ідея? Спробуйте збільшити і зменшити розміри вікна. Елементи залишаються на своїх місцях.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqJMgdB5jHI/AAAAAAAAEmY/9UJrQToA1iM/s1600-h/img02.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqJMgdB5jHI/AAAAAAAAEmY/9UJrQToA1iM/s400/img02.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5377945025465912434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;wxWidgets&lt;/span&gt; використовує інший підхід до розміщення елементів на формі. Елементи розміщуються не лише по відношенню до верхнього лівого кута. Їхній розмір також задається по відношенню до висоти і ширини.&lt;br /&gt;Тобто, повертаючись до прикладу із статті &lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-welcome-to-wxruby.html"&gt;Welcome to wxRuby!&lt;/a&gt;, ми помістили у вікно лише одну кнопку, по замовчуванню вона має висоту і ширину рівну, відповідно, висоті і ширині вікна.&lt;br /&gt;&lt;br /&gt;Замість організації віджетів, використовуючи точні розміри і позиції, можна використовувати так звані сайзери, тобто класи похідні від &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;. Саме сайзери визначають поведінку дочірніх елементів при зміні розмірів головного вікна. На мою думку, сайзери є найбільш складною для освоєння частиною бібліотеки &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt;. І саме сайзерам буде присвячена ця стаття.&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Загальні відомості про сайзери.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Для того щоб краще зрозуміти, як користуватися сайзерами, їх найкраще уявити собі у вигляді книжкових полиць або шафок, розділених на секції. Всередині кожної секції може розміщуватися тільки один елемент. Ці елементи ви можете пересунути до лівої стінки полиці, так щоб справа залишилось вільне місце, або навпаки до правої. На відміну від книжок, елемент керування ви можете приклеїти до стелі, або примусити висіти по центру. На відміну від справжніх меблів, ці полички та шафки можуть розтягувати книжки, щоб вони займали все вільне місце.&lt;br /&gt;Для початку розглянемо клас &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;, який є базовим для всіх сайзерів. При створені інтерфейсу будуть використовуватись похідні від &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt; класи. Ви не можете безпосередньо використовувати &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;. Замість цього використовуєте один із похідних від нього класів. На даний час це:&lt;br /&gt;&lt;ul&gt; &lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::StaticBoxSizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::GridSizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::FlexGridSizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::GridBagSizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Варто пам'ятати, сайзери не є вікнами, тобто елементами керування, а тільки вміють змінювати розміщення і розміри своїх "підопічних" елементів.&lt;br /&gt;Клас &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt; містить доволі багато методів, але нас в першу чергу цікавить тільки один - метод &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt;, за допомогою якого можна додати один елемент в "шафку". Слід зазначити, що всередині сайзеру замість елементу керування можна помістити інший сайзер. Завдяки цьому ми можемо розбити кожну "полицю" на декілька комірок.&lt;br /&gt;&lt;br /&gt;Розглянемо параметри методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::SizerItem#add(Wx::Window window,&lt;br /&gt;                Integer proportion = 0,&lt;br /&gt;                Integer flag = 0,&lt;br /&gt;                Integer border = 0&lt;br /&gt;                Object user_data = nil)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;item&lt;/span&gt;. У якості першого параметру можуть виступати 3 види об'єктів:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Елементи керування, а точніше вікна, похідні від класу &lt;span style="font-style:italic;"&gt;Wx::Window&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Інші сайзери, тобто класи, похідні від &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::Size&lt;/span&gt;(не плутати з &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;), який представляє собою клас обгортку над двома числовими значеннями - шириною і висотою. Якщо в метод &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt; передати екземпляр класу &lt;span style="font-style:italic;"&gt;Wx::Size&lt;/span&gt;, то замість елементу керування в комірку сайзера буде додане порожнє місце заданого розміру.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;. Цей параметр може використовуватись класом &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;, про який ми поговоримо пізніше. При використанні цього параметру можна визначити як будуть змінюватись розміри елементів при зміні їх батьківського вікна. Якщо він рівний 0(значення по замовчуванню), то елемент буде займати мінімальний розмір. Якщо сайзер містить декілька елементів з однаковими значеннями &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;, то при зміні розмірів батьківського вікна, елементи будуть змінювати свої розміри таким чином, щоб мати однакові розміри відносно однієї із осей(яка це вісь, горизонтальна чи вертикальна, залежатиме від орієнтації сайзера). Якщо елементи будуть мати різні значення &lt;span style="font-style:italic;"&gt;proportion&lt;/span&gt;, то їх розміри вздовж вісі будуть пропорційні значенням proportion.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;flag&lt;/span&gt;. Це, мабуть, самий важливий параметр, який більше всіх визначає розміщення і розміри елементів керування. Є цілочисловим значенням, яке складається із набору констант. Всі ці константи умовно можна розділили на 3 групи:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Прапорці, які задають невидиму рамку навколо елементів керування.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Прапорці, які задають вирівнювання елементів керування.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Прапорці, які задають поведінку при зміні розмірів батьківського вікна.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;До першої групи належать:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::TOP&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::BOTTOM&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::LEFT&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::RIGHT&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALL&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Вони задають з якої сторони від елементу керування буде невидима рамка: зверху, знизу, зліва, справа чи з усіх сторін відповідно. Рамка представляє собою порожнє місце, розмір якого задається у наступному параметрі методу add(). Якщо ми, наприклад, хочемо щоб зліва і справа від елементу було залишене порожнє місце, то прапорець повинен мати наступний вигляд:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::LEFT | Wx::RIGHT&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;До прапорців, що задають вирівнювання елементів керування належать:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_CENTER&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_LEFT&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_RIGHT&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_TOP&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_BOTTOM&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_CENTER_VERTICAL&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::ALIGN_CENTER_HORIZONTAL&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Ці прапорці позначають відповідно, що елемент керування буде "приклеєний" до центру, до лівої або правої стінки, до верху або низу комірки. Останні два прапорці дають можливість зазначити, що вирівнювання по центру потрібно робити тільки по вертикалі або тільки по горизонталі, у той час як &lt;span style="font-style:italic;"&gt;Wx::ALIGN_CENTER&lt;/span&gt; означає, що вирівнювання по центру буде проводитися по обох осях.&lt;br /&gt;&lt;br /&gt;Крім того є ще три прапорці, які впливають не на розміщення, а на розмір елементів.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt; позначає, що елемент повинен займати всю комірку сайзера  на скільки він зможе розтягнутися.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::SHAPED&lt;/span&gt; позначає, що елемент знову ж таки повинен зайняти по можливості всю комірку, але при цьому він повинен зберігати вихідні пропорції між його довжиною і шириною.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;Wx::FIXED_MINSIZE&lt;/span&gt; означає, що при зміні розмірів елементу, не буде враховуватися мінімально можливий розмір, тобто елемент може бути меншим заданого мінімального розміру.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;А тепер перейдемо до огляду інших параметрів методу &lt;span style="font-style:italic;"&gt;add()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;border&lt;/span&gt;. Цей параметр визначає розміри рамки у пікселях. Таким чином цей параметр необхідний у тому випадку, якщо використовуються прапорці з першої групи.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;user_data&lt;/span&gt;. Представляє собою дані користувача, які можуть прикріплятися до елемента, щоб більш точно визначати розташування елементу. Наразі &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt; не підтримує цей параметр.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Встановлення сайзера для вікна.&lt;/span&gt;&lt;br /&gt;Припустимо, ми створили сайзер, заповнили його елементами керування або іншими сайзерами. Тепер головному вікну потрібно вказати, що створений сайзер потрібно використовувати для розміщення елементів.&lt;br /&gt;Для цього у класу &lt;span style="font-style:italic;"&gt;Wx::Window&lt;/span&gt; є метод &lt;span style="font-style:italic;"&gt;set_sizer()&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Wx::Window#set_sizer(Wx::Sizer sizer, Boolean delete_old = true)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Перший параметр представляє собою екземпляр сайзера.&lt;br /&gt;Другий параметр &lt;span style="font-style:italic;"&gt;delete_old&lt;/span&gt; позначає, що попередній сайзер, встановлений для вікна повинен бути знищеним. Значення по замовчуванню &lt;span style="font-style:italic;"&gt;true&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Варто пам'ятати, що вікно буде розтягувати сайзер на всю доступну область, що нагадує використання прапорця &lt;span style="font-style:italic;"&gt;Wx::EXPAND&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Отже, загальний алгоритм роботи з сайзерами складається з наступних етапів:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Створити екземпляр вікна - батька для елементів керування&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Після створення вікна створити екземпляр одного із класів похідних від &lt;span style="font-style:italic;"&gt;Wx::Sizer&lt;/span&gt;. Це буде головний для вікна сайзер.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Заповнити головний сайзер елементами керування або іншими сайзерами.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Приєднати головний сайзер до вікна за допомогою методу &lt;span style="font-style:italic;"&gt;Wx::Window#set_sizer()&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;У якості прикладу створимо вікно з текстовим полем і однією кнопкою справа під ним. Але на відміну від прикладу, який наводився на початку статті, для позиціонування будемо використовувати сайзер &lt;span style="font-style:italic;"&gt;Wx::BoxSizer&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;&lt;br /&gt;require 'wx'&lt;br /&gt;&lt;br /&gt;class HelloFrame &amp;lt; Wx::Frame&lt;br /&gt; def initialize&lt;br /&gt;   super(nil, :id =&amp;gt; -1,:title =&amp;gt; 'Hello World!', :size =&amp;gt; [200, 200])&lt;br /&gt;   sizer = Wx::BoxSizer.new(Wx::VERTICAL)&lt;br /&gt;   text = Wx::TextCtrl.new(self, :id =&amp;gt; -1,&lt;br /&gt;                                 :text =&amp;gt; 'Type in here',&lt;br /&gt;                                 :pos =&amp;gt; Wx::DEFAULT_POSITION,&lt;br /&gt;                                 :size =&amp;gt; Wx::DEFAULT_SIZE,&lt;br /&gt;                                 :style =&amp;gt; Wx::TE_MULTILINE)&lt;br /&gt;   button = Wx::Button.new(self, :id =&amp;gt; -1,&lt;br /&gt;                                 :label =&amp;gt; 'Press me')&lt;br /&gt;&lt;br /&gt;   sizer.add(text, 1, Wx::GROW|Wx::ALL, 2)&lt;br /&gt;   sizer.add(button, 0, Wx::ALIGN_RIGHT, 2)&lt;br /&gt;   set_sizer(sizer)&lt;br /&gt;  &lt;br /&gt;   show&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class HelloApp &amp;lt; Wx::App&lt;br /&gt; def on_init&lt;br /&gt;   HelloFrame.new&lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;app = HelloApp.new&lt;br /&gt;app.main_loop()&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Запустіть цей приклад і спробуйте змінити розміри вікна.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqJSe0rXO7I/AAAAAAAAEmg/Bo-hLDnNovI/s1600-h/img03.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 208px; height: 233px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SqJSe0rXO7I/AAAAAAAAEmg/Bo-hLDnNovI/s400/img03.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5377951594523868082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqJSmPwvRTI/AAAAAAAAEmo/wcWntAOQvvI/s1600-h/img04.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 317px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SqJSmPwvRTI/AAAAAAAAEmo/wcWntAOQvvI/s400/img04.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5377951722053256498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;У наступній статті ми детальніше розглянемо сайзери, які існують в бібліотеці &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt; і на прикладах побачимо як впливають на розміщення елементів всі прапорці з методу &lt;span style="font-style:italic;"&gt;Wx::Sizer#add()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;На все добре і успіхів.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-6596431412966910305?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/6596431412966910305/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=6596431412966910305" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6596431412966910305?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6596431412966910305?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/VRxPLyEy9q0/wxruby-1.html" title="wxRuby → Сайзери (1 частина)" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_lXvcYH2YnAY/SqJMTqEjlMI/AAAAAAAAEmQ/xtSlj6X57Eo/s72-c/img01.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/wxruby-1.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ak4FRHo7eSp7ImA9WxNRE0g.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-5423970608884384715</id><published>2009-09-03T21:21:00.009+03:00</published><updated>2009-09-08T00:28:35.401+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-08T00:28:35.401+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="wx" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>wxRuby → Вікно</title><content type="html">У статті &lt;a href="http://ruby-ua.blogspot.com/2009/09/wxruby-welcome-to-wxruby.html"&gt;Welcome to wxRuby!&lt;/a&gt; ми познайомилися з бібліотекою віджетів &lt;span style="font-style:italic;"&gt;wxWidgets&lt;/span&gt; та обгорткою для роботи з &lt;span style="font-style:italic;"&gt;Ruby&lt;/span&gt;.  Також  ми створили простий додаток на &lt;span style="font-style:italic;"&gt;wxRuby&lt;/span&gt;, який показує вікно з однією кнопкою.&lt;br /&gt;&lt;br /&gt;Розглянемо докладніше цей код.&lt;br /&gt;У класі &lt;span style="font-style:italic;"&gt;HelloApp&lt;/span&gt; є метод &lt;span style="font-style:italic;"&gt;on_init()&lt;/span&gt;, який викликається під час запуску додатку.&lt;br /&gt;Займемося головним вікном. За створення вікна відповідає конструктор класу &lt;span style="font-style:italic;"&gt;Wx::Frame&lt;/span&gt;. Фрейм - це вікно, розмір і позиція якого можуть бути змінені користувачем. Зазвичай воно має рамку і заголовок, а також опціонально може містити рядок меню, панель інструментів і рядок стану(про які ми поговоримо в одній із майбутніх статей).&lt;br /&gt;&lt;br /&gt;Конструктор класу &lt;span style="font-style:italic;"&gt;Wx::Frame&lt;/span&gt;  приймає 7 параметрів:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:parent =&gt; (Wx::Window)&lt;/span&gt; - це посилання на батьківський об'єкт(обов'язковий параметр)&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:id =&gt; (Fixnum)&lt;/span&gt; - ідентифікатор вікна. -1 - значення по замовчуванню&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:title =&gt; (String)&lt;/span&gt; - заголовок вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:pos =&gt; (Wxruby2::Point)&lt;/span&gt; - позиція вікна на екрані&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:size =&gt; (Wxruby2::Size)&lt;/span&gt; - розмір вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:style =&gt; (Fixnum)&lt;/span&gt; - стиль вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;:name =&gt; (String)&lt;/span&gt; - назва вікна&lt;br /&gt;&lt;br /&gt;Змінимо код додатку з першої частини так, щоб наше вікно з'явилося у верхньому лівому куті і мало розмір 320х240 пікселів. Зміни вносимо у метод &lt;span style="font-style:italic;"&gt;initialize()&lt;/span&gt; класу &lt;span style="font-style:italic;"&gt;HelloFrame&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;super(nil, :id =&amp;gt; -1, :title =&amp;gt; 'Hello World!', :pos =&amp;gt; [0, 0], :size =&amp;gt; [320, 240], :style =&amp;gt; Wx::DEFAULT_FRAME_STYLE, :name =&amp;gt; 'frame')&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Щоб вікно з'явилося у центрі екрану можна скористатися методом &lt;span style="font-style:italic;"&gt;centre()&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;self.centre&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Для зміни позиції вікна після ініціалізації можна скористатись методам &lt;span style="font-style:italic;"&gt;move(Wx::Point point)&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;self.move([100, 100])&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Для зміни розміру вікна є метод &lt;span style="font-style:italic;"&gt;set_size(Wx::Size size)&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;self.set_size([640, 480])&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Для вікна можна задати один із стилів:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::DEFAULT_FRAME_SLYLE&lt;/span&gt;  - стиль по замовчуванню. Включає в себе &lt;span style="font-style:italic;"&gt;Wx::MINIMIZE_BOX|Wx::MAXIMIZE_BOX|Wx::RESIZE_BORDER|Wx::SYSTEM_MENU|Wx::CAPTION|Wx::CLOSE_BOX|Wx::CLIP_CHILDREN&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::ICONIZE&lt;/span&gt; - показувати мінімізоване вікно. Тільки Windows&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::CAPTION&lt;/span&gt; - показувати заголовок вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::MINIMIZE&lt;/span&gt; - аналогічно Wx::ICONIZE&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::MINIMIZE_BOX&lt;/span&gt; - показувати кнопку згортання вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::MAXIMIZE&lt;/span&gt; - показувати максимізоване вікно. Тільки Windows&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::MAXIMIZE_BOX&lt;/span&gt; - показувати кнопку розгортання вікна на весь екран&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::CLOSE_BOX&lt;/span&gt; - показувати кнопку закриття вікна&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::STAY_ON_TOP&lt;/span&gt; - показувати поверх всіх вікон&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::SYSTEM_MENU&lt;/span&gt; - вікно буде мати системне меню&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::RESIZE_BORDER&lt;/span&gt; - показувати рамку для зміни розміру вікна.&lt;br /&gt;Wx::FRAME_TOOL_WINDOW - вікно з рамкою невеликого розміру, і також вікно не буде показуватися на панелі задач. Тільки Windows і GTK+&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::FRAME_NO_TASKBAR&lt;/span&gt; - нормальне вікно, але воно не буде показуватися на панелі задач. Тільки Windows і GTK+&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::FRAME_FLOAT_ON_PARENT&lt;/span&gt; - вікно буде показуватися тільки поверх батьківського вікна (на відміну від Wx::STAY_ON_TOP)&lt;br /&gt;&lt;br /&gt;Для того щоб створити вікно, розмір якого не може змінювати користувач, можна використати таку комбінацію стилів:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Wx::DEFAULT_FRAME_STYLE &amp;amp; ~ (Wx::RESIZE_BORDER|Wx::RESIZE_BOX|Wx::MAXIMIZE_BOX)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Тепер ви можете поекспериментувати із розміром, позицією і стилями вікна.&lt;br /&gt;Стаття вийшла доволі коротка, і ми тут не розглянули всі нюанси роботи з вікнами. Виправлю цей недолік у майбутніх статтях.&lt;br /&gt;На домашнє завдання така задачка: у випадку натиснення на кнопку пересунути вікно у позицію [10, 10].&lt;br /&gt;&lt;br /&gt;На все добре і успіхів.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-5423970608884384715?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/5423970608884384715/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=5423970608884384715" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5423970608884384715?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5423970608884384715?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/LJX42oDGYUE/wxruby.html" title="wxRuby → Вікно" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/wxruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUUEQn0_eSp7ImA9WxNSGE0.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-5799784263984825015</id><published>2009-09-01T13:07:00.009+03:00</published><updated>2009-09-01T14:06:43.341+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-01T14:06:43.341+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="wx" /><category scheme="http://www.blogger.com/atom/ns#" term="gui" /><title>wxRuby → Welcome to wxRuby!</title><content type="html">Цим записом я розпочну серію статей присвячену основам створення графічних додатків за допомогою бібліотеки wxWidgets на мові Ruby.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SpzykpIjJPI/AAAAAAAAElY/jYl-5Azv-J8/s1600-h/cross.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 238px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SpzykpIjJPI/AAAAAAAAElY/jYl-5Azv-J8/s400/cross.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5376438766504453362" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.wxwidgets.org/"&gt;wxWidgets&lt;/a&gt;(раніше відома як wxWindows) — це крос-платформена бібліотека інструментів з відкритим вихідним кодом для побудови графічного інтерфейсу користувача(GUI).&lt;br /&gt;wxWidgets розповсюджується під ліцензією LGPL. Проект був запущений в 1992 Юіаном Смартом (Julian Smart), який до сих пір залишається головним розробником. У 2004 році проект wxWidgets на прохання Microsoft Corporation змінив оригінальну назву "wxWindows" на "wxWidgets", за що отримав фінансову допомогу.&lt;br /&gt;wxWidgets дозволяє створювати додатки для багатьох комп'ютерних платформ із мінімальними змінами у вихідному коді, або взагалі без них. Вона підтримує системи Microsoft Windows, Apple Macintosh, UNIX-подібні(для X11, Motif і GTK+), OpenVMS і OS/2.  WxWidgets не імітує вигляд компонентів, використовуючи графічні примітиви різних підтримуваних платформ.  Натомість wxWidgets надає тонку абстракцію до існуючих компонентів системи.&lt;br /&gt;Бібліотека розроблена на C++, але може бути підключеною до багатьох інших розповсюджених мов, таких як Ruby, Python, Perl, Java, C#/.NET та інших.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/Spzzb1-FE2I/AAAAAAAAElg/_m-S_vek8sk/s1600-h/wxruby.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 199px; height: 72px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/Spzzb1-FE2I/AAAAAAAAElg/_m-S_vek8sk/s400/wxruby.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5376439714843005794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://wxruby.rubyforge.org/"&gt;wxRuby&lt;/a&gt; - це обгортка бібліотеки wxWidgets для роботи з Ruby. Вона однаково добре працює на Windows, Linux, Mac OS X, і з Ruby версіями 1.8 та 1.9.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Інсталяція wxRuby2&lt;/span&gt;&lt;br /&gt;Є два методи інсталяції wxRuby2:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Використовуючи Rubygems для встановлення бінарного gem-у(без залежностей)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Із вихідних кодів&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Для більшості людей на більшості операційних систем перший метод є зручнішим і швидшим. Для цього достатньо у командному рядку виконати:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;gem install wxruby&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Слід зазначити, що при написанні власних додатків використовуючи wxRuby, встановлену із gem-ів, ви повинні попередньо завантажити(не обов'язково для ruby &gt;= 1.9 ) бібліотеку rubygems. Це можна зробити кількома способами:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Запустити &lt;span style="font-style:italic;"&gt;ruby&lt;/span&gt; з аргументом &lt;span style="font-style:italic;"&gt;-rubygems&lt;/span&gt;. Наприклад: r&lt;span style="font-style:italic;"&gt;uby -rubygems my_wxruby_script.rb&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Встановити &lt;span style="font-style:italic;"&gt;RUBYOPT&lt;/span&gt; змінну оточення як &lt;span style="font-style:italic;"&gt;-rubygems&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Додати на початку програми рядок &lt;span style="font-style:italic;"&gt;require 'rubygems'&lt;/span&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Розпочнемо з просто прикладу. Покажемо вікно з кнопкою "Press me", при натисканні на яку відобразиться діалогове повідомлення.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;&lt;br /&gt;# &amp;#1055;&amp;#1110;&amp;#1076;&amp;#1082;&amp;#1083;&amp;#1102;&amp;#1095;&amp;#1072;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1073;&amp;#1110;&amp;#1073;&amp;#1083;&amp;#1110;&amp;#1086;&amp;#1090;&amp;#1077;&amp;#1082;&amp;#1091; wxruby2 &lt;br /&gt;require 'wx'&lt;br /&gt;&lt;br /&gt;# &amp;#1057;&amp;#1090;&amp;#1074;&amp;#1086;&amp;#1088;&amp;#1102;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1089;&amp;#1074;&amp;#1110;&amp;#1081; &amp;#1082;&amp;#1083;&amp;#1072;&amp;#1089; &amp;#1089;&amp;#1087;&amp;#1072;&amp;#1076;&amp;#1082;&amp;#1086;&amp;#1108;&amp;#1084;&amp;#1077;&amp;#1094;&amp;#1100; Wx::Frame &amp;#1079; &amp;#1091;&amp;#1089;&amp;#1110;&amp;#1084;&amp;#1072; &amp;#1087;&amp;#1086;&amp;#1090;&amp;#1088;&amp;#1110;&amp;#1073;&amp;#1085;&amp;#1080;&amp;#1084;&amp;#1080; &amp;#1085;&amp;#1072;&amp;#1084; &amp;#1077;&amp;#1083;&amp;#1077;&amp;#1084;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1072;&amp;#1084;&amp;#1080;, &amp;#1072; &amp;#1087;&amp;#1086;&amp;#1090;&amp;#1110;&amp;#1084; &amp;#1074;&amp;#1080;&amp;#1082;&amp;#1086;&amp;#1088;&amp;#1080;&amp;#1089;&amp;#1090;&amp;#1086;&amp;#1074;&amp;#1091;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1081;&amp;#1086;&amp;#1075;&amp;#1086;.&lt;br /&gt;class HelloFrame &amp;lt; Wx::Frame&lt;br /&gt;  def initialize&lt;br /&gt;    super(nil, :title =&amp;gt; 'Hello World!')&lt;br /&gt;    button = Wx::Button.new(self, :label =&amp;gt; 'Press me') # &amp;#1057;&amp;#1090;&amp;#1074;&amp;#1086;&amp;#1088;&amp;#1102;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1082;&amp;#1085;&amp;#1086;&amp;#1087;&amp;#1082;&amp;#1091;. &amp;#1047;&amp;#1072; &amp;#1076;&amp;#1086;&amp;#1087;&amp;#1086;&amp;#1084;&amp;#1086;&amp;#1075;&amp;#1086;&amp;#1102; &amp;#1087;&amp;#1086;&amp;#1089;&amp;#1080;&amp;#1083;&amp;#1072;&amp;#1085;&amp;#1085;&amp;#1103; self &amp;#1074;&amp;#1086;&amp;#1085;&amp;#1072; &amp;#1089;&amp;#1072;&amp;#1084;&amp;#1072; &amp;#1089;&amp;#1077;&amp;#1073;&amp;#1077; &amp;#1076;&amp;#1086;&amp;#1076;&amp;#1072;&amp;#1089;&amp;#1090;&amp;#1100; &amp;#1091; &amp;#1092;&amp;#1088;&amp;#1077;&amp;#1081;&amp;#1084;&lt;br /&gt;    &lt;br /&gt;    evt_button(button.get_id, :bt_evt) # &amp;#1059; &amp;#1074;&amp;#1080;&amp;#1087;&amp;#1072;&amp;#1076;&amp;#1082;&amp;#1091; &amp;#1085;&amp;#1072;&amp;#1090;&amp;#1080;&amp;#1089;&amp;#1085;&amp;#1077;&amp;#1085;&amp;#1085;&amp;#1103; &amp;#1074;&amp;#1080;&amp;#1082;&amp;#1083;&amp;#1080;&amp;#1082;&amp;#1072;&amp;#1108;&amp;#1084;&amp;#1086; bt_evt()&lt;br /&gt;    show # &amp;#1087;&amp;#1086;&amp;#1082;&amp;#1072;&amp;#1079;&amp;#1091;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1074;&amp;#1110;&amp;#1082;&amp;#1085;&amp;#1086;&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def bt_evt&lt;br /&gt;    Wx::MessageDialog.new(self, &amp;quot;Hello world!&amp;quot;, &amp;quot;Test&amp;quot;, Wx::OK).show_modal # &amp;#1089;&amp;#1090;&amp;#1074;&amp;#1086;&amp;#1088;&amp;#1102;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1076;&amp;#1110;&amp;#1072;&amp;#1083;&amp;#1086;&amp;#1075; &amp;#1079; &amp;#1086;&amp;#1076;&amp;#1085;&amp;#1110;&amp;#1108;&amp;#1102; &amp;#1082;&amp;#1085;&amp;#1086;&amp;#1087;&amp;#1082;&amp;#1086;&amp;#1102; OK &amp;#1110; &amp;#1074;&amp;#1110;&amp;#1076;&amp;#1086;&amp;#1073;&amp;#1088;&amp;#1072;&amp;#1078;&amp;#1072;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1081;&amp;#1086;&amp;#1075;&amp;#1086; &amp;#1079;&amp;#1072; &amp;#1076;&amp;#1086;&amp;#1087;&amp;#1086;&amp;#1084;&amp;#1086;&amp;#1075;&amp;#1086;&amp;#1102; show_modal()&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class HelloApp &amp;lt; Wx::App&lt;br /&gt;  def on_init&lt;br /&gt;    HelloFrame.new # &amp;#1089;&amp;#1090;&amp;#1074;&amp;#1086;&amp;#1088;&amp;#1102;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1077;&amp;#1082;&amp;#1079;&amp;#1077;&amp;#1084;&amp;#1087;&amp;#1083;&amp;#1103;&amp;#1088; &amp;#1085;&amp;#1072;&amp;#1096;&amp;#1086;&amp;#1075;&amp;#1086; &amp;#1082;&amp;#1083;&amp;#1072;&amp;#1089;&amp;#1091;&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;app = HelloApp.new&lt;br /&gt;app.main_loop() # &amp;#1047;&amp;#1072;&amp;#1087;&amp;#1091;&amp;#1089;&amp;#1082;&amp;#1072;&amp;#1108;&amp;#1084;&amp;#1086; &amp;#1075;&amp;#1086;&amp;#1083;&amp;#1086;&amp;#1074;&amp;#1085;&amp;#1080;&amp;#1081; &amp;#1094;&amp;#1080;&amp;#1082;&amp;#1083; Wx. &amp;#1047; &amp;#1094;&amp;#1100;&amp;#1086;&amp;#1075;&amp;#1086; &amp;#1084;&amp;#1086;&amp;#1084;&amp;#1077;&amp;#1085;&amp;#1090;&amp;#1091; &amp;#1087;&amp;#1088;&amp;#1086;&amp;#1075;&amp;#1088;&amp;#1072;&amp;#1084;&amp;#1072; &amp;#1086;&amp;#1095;&amp;#1110;&amp;#1082;&amp;#1091;&amp;#1108; &amp;#1085;&amp;#1072; &amp;#1088;&amp;#1110;&amp;#1079;&amp;#1085;&amp;#1110; &amp;#1087;&amp;#1086;&amp;#1076;&amp;#1110;&amp;#1111;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;У результаті будемо мати таке віконечко:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/Spz0waWhF3I/AAAAAAAAElo/EzqSfM3FjYk/s1600-h/img1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 400px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/Spz0waWhF3I/AAAAAAAAElo/EzqSfM3FjYk/s400/img1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5376441167718193010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;В даний час API представляє собою прямий порт wxWidgets C++ інтерфейсу. Місцями цей інтерфейс є трохи аляповий, завдяки своїй довгій історії. В майбутньому розробники планують додати Ruby-специфічний шар поверх базового Wx API, аналогічно тому як це зроблено у &lt;a href="http://www.fxruby.org/"&gt;FXRuby&lt;/a&gt; для Fox. Це розширене API буде простіше у використанні і орієнтуватиметься на Ruby-стиль. Крім того розробники створили підпроект wxSugar(який може використовуватись поверх wxRuby) у якості випробувального полігону для покращень синтаксису.&lt;br /&gt;&lt;br /&gt;У гем пакеті wxRuby є досить багато прикладів роботи з різноманітними віджетами, тому цього цілком вистачить, для демонстрації можливостей Ruby + wxWidgets.&lt;br /&gt;У мене це &lt;span style="font-style:italic;"&gt;/opt/lib/ruby/gems/1.9.1/gems/wxruby-ruby19-2.0.0-x86-linux/samples&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/Spz1WuCR8RI/AAAAAAAAElw/ujUr_E-11DM/s1600-h/img2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 307px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/Spz1WuCR8RI/AAAAAAAAElw/ujUr_E-11DM/s400/img2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5376441825837052178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Посилання:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://wxruby.rubyforge.org"&gt;http://wxruby.rubyforge.org&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.wxwidgets.org/"&gt;http://www.wxwidgets.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://ru.wikipedia.org/wiki/WxWidgets"&gt;http://ru.wikipedia.org/wiki/WxWidgets&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-5799784263984825015?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/5799784263984825015/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=5799784263984825015" title="2 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5799784263984825015?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5799784263984825015?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/_QIyOP60MCE/wxruby-welcome-to-wxruby.html" title="wxRuby → Welcome to wxRuby!" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/SpzykpIjJPI/AAAAAAAAElY/jYl-5Azv-J8/s72-c/cross.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/09/wxruby-welcome-to-wxruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcBQHY9fip7ImA9WxNTFkk.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-5305614507294806971</id><published>2009-08-19T02:53:00.002+03:00</published><updated>2009-08-19T03:00:51.866+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-19T03:00:51.866+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="life" /><title>Quake Live for Linux</title><content type="html">Те, що так довго очікувалося, нарешті збулося! Хай гримлять литаври і б’ють в барабани, хай нічні феєрверки не згасають цілу ніч, а вдень падають на землю важким дощем.Збулось!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/quakelive"&gt;Twitter&lt;/a&gt; доставив приємну звісточку:&lt;br /&gt;&lt;blockquote&gt;QUAKE LIVE is back online, now with Mac &amp; Linux support! Read more at &lt;a href="http://www.quakelive.com/forum/showthread.php?t=31851"&gt;www.quakelive.com/forum/showthread.php?t=31851&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Протестовано на Ubuntu 9.04 з Firefox 3.0.13.&lt;br /&gt;Плагін для Firefox оформлений у вигляді xpi-файла.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sos_c2u3AGI/AAAAAAAAEVk/R_XBX3nQkwA/s1600-h/194.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sos_c2u3AGI/AAAAAAAAEVk/R_XBX3nQkwA/s400/194.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5371456745530392674" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-5305614507294806971?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/5305614507294806971/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=5305614507294806971" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5305614507294806971?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/5305614507294806971?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/tYzzk27_R_c/quake-live-for-linux.html" title="Quake Live for Linux" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sos_c2u3AGI/AAAAAAAAEVk/R_XBX3nQkwA/s72-c/194.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/08/quake-live-for-linux.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcNRn88eip7ImA9WxNTFk4.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-8530958879785555934</id><published>2009-08-19T00:47:00.003+03:00</published><updated>2009-08-19T02:28:17.172+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-19T02:28:17.172+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><title>I18N. Підтримка української мови в Ruby і Ruby On Rails</title><content type="html">&lt;a href="http://github.com/romanvbabenko/ukrainian/tree/master"&gt;Ukrainian language support for Ruby &amp; Ruby and Rails | Підтримка української мови для Ruby та Ruby on Rails&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Що це і кому це може знадобиться?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Ukrainian&lt;/span&gt; – бібліотека повноцінної підтримки української мови(форматування дати та часу, плюралізації та інтернаціоналізації вцілому)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Ruby on Rails&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Пакет мість в собі переклади стандартних бібліотек: ActionView, ActiveRecord, ActiveSupport, а також підтримку плюралізацій для таких методів як &lt;span style="font-style:italic;"&gt;distance_of_time_in_words&lt;/span&gt; та &lt;span style="font-style:italic;"&gt;distance_of_time_in_words_to_now&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-8530958879785555934?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/8530958879785555934/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=8530958879785555934" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8530958879785555934?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8530958879785555934?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/4ef1IX3MMP0/i18n-ruby-ruby-on-rails.html" title="I18N. Підтримка української мови в Ruby і Ruby On Rails" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/08/i18n-ruby-ruby-on-rails.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkcEQXk-eyp7ImA9WxJaGE8.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-2413540509387803338</id><published>2009-08-09T15:03:00.003+03:00</published><updated>2009-08-09T15:13:20.753+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-09T15:13:20.753+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="news" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><title>Плани на Ruby 1.9.2</title><content type="html">&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sn67Fh-LB2I/AAAAAAAAEVc/d6xkXkpEBlA/s1600-h/192.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 245px; height: 106px;" src="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sn67Fh-LB2I/AAAAAAAAEVc/d6xkXkpEBlA/s400/192.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5367933509565089634" /&gt;&lt;/a&gt;&lt;br /&gt;Фінальна версія Ruby 1.9.2 &lt;a href="http://osdir.com/ml/ruby-core/2009-06/msg00325.html"&gt;запланована&lt;/a&gt; на кінець 2009 року (25 грудня).&lt;br /&gt;Вже зараз ви можете спробувати &lt;a href="http://www.ruby-lang.org/en/news/2009/07/20/ruby-1-9-2-preview-1-released/"&gt;перший попередній реліз&lt;/a&gt;, який був представлений 17 липня, під час японської конференції &lt;a href="http://rubykaigi.org/2009/en"&gt;Ruby Kaigi 2009&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Наступні цікаві особливості будуть включені до 1.9.2, якщо вони будуть реалізовані вчасно до заморожування (25 вересня 2009 року, 1.9.2 preview release 3):&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;підтримка &lt;a href="http://uk.wikipedia.org/wiki/%D0%97%D0%BD%D0%B5%D0%B2%D0%B0%D0%B4%D0%B6%D1%83%D0%B2%D0%B0%D1%87"&gt;зневаджувача&lt;/a&gt;(debugger)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;підтримка &lt;a href="http://uk.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%84%D1%96%D0%BB%D1%8E%D0%B2%D0%B0%D0%BD%D0%BD%D1%8F_(%D0%BA%D0%BE%D0%BC%D0%BF%27%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%96_%D0%BD%D0%B0%D1%83%D0%BA%D0%B8)"&gt;профайлера&lt;/a&gt;(profiler)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;підтримка DTrace на FreeBSD, OpenSolaris та OSX.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sqlite.org/"&gt;SQLite&lt;/a&gt; як стандартна бібліотека&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Крім того розробники обіцяють оптимізувати інтепритатор YARV а також внести зміни до стандартної бібліотеки. Докладніше &lt;a href="http://svn.ruby-lang.org/repos/ruby/trunk/NEWS"&gt;тут&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-2413540509387803338?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/2413540509387803338/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=2413540509387803338" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2413540509387803338?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/2413540509387803338?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/dh9rHfrr8N4/ruby-192.html" title="Плани на Ruby 1.9.2" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_lXvcYH2YnAY/Sn67Fh-LB2I/AAAAAAAAEVc/d6xkXkpEBlA/s72-c/192.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/08/ruby-192.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4HRno-fip7ImA9WxNTEkk.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-9196411883127194002</id><published>2009-08-08T23:15:00.010+03:00</published><updated>2009-08-14T12:58:57.456+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-14T12:58:57.456+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><title>Ruby for System Administration → Ruby-inotify</title><content type="html">&lt;span style="font-style:italic;"&gt;Inotify&lt;/span&gt; - це підсистема ядра &lt;span style="font-style:italic;"&gt;Linux&lt;/span&gt;, яка дозволяє отримувати повідомлення про зміни у файловій системі. У основне ядро була включена починаючи з &lt;span style="font-style:italic;"&gt;2.6.13&lt;/span&gt;. Основна сфера використання - в системах пошуку (наприклад &lt;span style="font-style:italic;"&gt;Beagle&lt;/span&gt;), таким чином програмі-індексатору не потрібно сканувати всю файлову систему кожні кілька хвилин.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://dinhe.net/~aredridel/projects/ruby/ruby-inotify.html"&gt;ruby-inotify&lt;/a&gt; - це &lt;span style="font-style:italic;"&gt;Ruby&lt;/span&gt; інтерфейс для доступу до системних викликів &lt;span style="font-style:italic;"&gt;Linux Inotify&lt;/span&gt;.&lt;br /&gt;Дозволяє виявляти, якщо файл був відкритий, закритий, переміщений, видалений, модифікований і багато чого іншого.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Доступні події:&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ACCESS&lt;/span&gt; - звернення до файлу(читання).&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MODIFY&lt;/span&gt; - файл був змінений(запис).&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CREATE&lt;/span&gt; - файл був створений.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ATTRIB&lt;/span&gt; - змінені метадані (права, дата створення/редагування, розширені атрибути, і т.д.).&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CLOSE_WRITE&lt;/span&gt; - файл, відкритий для запису, був закритий.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CLOSE_NOWRITE&lt;/span&gt; - файл, не відкритий для запису, був закритий.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;OPEN&lt;/span&gt; - файл був відкритий.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MOVED_FROM&lt;/span&gt; - файл був переміщений від слідкування.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MOVED_TO&lt;/span&gt; - файл був переміщений до слідкування.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;DELETE&lt;/span&gt; - файл був видалений.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;DELETE_SELF&lt;/span&gt; - відслідковуваний файл/каталог був видалений.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;CLOSE&lt;/span&gt; - IN_CLOSE_WRITE | IN_CLOSE_NOWRITE&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;MOVE&lt;/span&gt; - IN_MOVED_FROM | IN_MOVED_TO&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ALL_EVENTS&lt;/span&gt; - будь-яка з подій.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UNMOUNT&lt;/span&gt; - файлова система була відмонтована.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Q_OVERFLOW&lt;/span&gt; - черава inotify переповнена.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;IGNORED&lt;/span&gt; - відслідковуваний файл був автоматично видалений, тому що файл був видалений або файлова система розмонтована.&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;ISDIR&lt;/span&gt; - подій відбулася відносто каталогу.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Процес інсталяції з вихідних кодів є дуже простим:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ wget http://dinhe.net/~aredridel/projects/ruby/ruby-inotify-0.0.2.tar.gz&lt;br /&gt;$ tar xzvf ruby-inotify-0.0.2.tar.gz&lt;br /&gt;$ cd ruby-inotify-0.0.2/&lt;br /&gt;$ rake1.9.1&lt;br /&gt;$ sudo make install&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Як воно працює?&lt;/span&gt;&lt;br /&gt;У каталозі examples міститься скрипт watcher.rb, який є простим прикладом роботи з &lt;span style="font-style:italic;"&gt;ruby-inotify&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#!usr/bin/ruby&lt;br /&gt;&lt;br /&gt;require 'inotify'&lt;br /&gt;require 'find'&lt;br /&gt;&lt;br /&gt;i = Inotify.new&lt;br /&gt;&lt;br /&gt;t = Thread.new do&lt;br /&gt;i.each_event do |ev|&lt;br /&gt;p ev.name&lt;br /&gt;p ev.mask&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;raise("Specify a directory") if !ARGV[0]&lt;br /&gt;&lt;br /&gt;Find.find(ARGV[0]) do |e|&lt;br /&gt;if ['.svn', 'CVS', 'RCS'].include? File.basename(e) or !File.directory? e&lt;br /&gt;Find.prune&lt;br /&gt;else&lt;br /&gt;begin&lt;br /&gt;  puts "Adding #{e}"&lt;br /&gt;  i.add_watch(e, Inotify::CREATE | Inotify::DELETE | Inotify::MOVE)&lt;br /&gt;rescue&lt;br /&gt;  puts "Skipping #{e}: #{$!}"&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;t.join&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;При створенні/видаленні/переміщені будь-якого файлу чи каталогу на екран буде виведене його ім’я і маска.&lt;br /&gt;Як бачите все доволі просто.&lt;br /&gt;&lt;br /&gt;Запустимо скрипт:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ ruby1.9.1 watcher.rb .&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Створимо файл з іменем test.txt і подивимось на результат роботи скрипта&lt;br /&gt;результат:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;"test.txt"&lt;br /&gt;256&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Створимо каталог з іменем test&lt;br /&gt;результат:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;"test"&lt;br /&gt;1073742080&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Видалимо файл test.txt&lt;br /&gt;результат:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;"test.txt"&lt;br /&gt;512&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Видалимо каталог test&lt;br /&gt;результат:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;"test"&lt;br /&gt;1073742336&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Де застосовувати?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Та де завгодно! Наприклад на мому домашньому сервері крутиться скрипт, який слідкує за каталогом /mnt/smb/downloads (у який користувачі через ssh скачують файли з інтернету) і виводить час створення або видалення файлів на web-сторінку.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Посилання:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.linuxjournal.com/article/8478"&gt;Kernel Korner - Intro to inotify&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-9196411883127194002?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/9196411883127194002/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=9196411883127194002" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9196411883127194002?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9196411883127194002?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/LHUdvYLyhV4/ruby-for-system-administration-ruby.html" title="Ruby for System Administration → Ruby-inotify" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/08/ruby-for-system-administration-ruby.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkAMRX88fCp7ImA9WxJaF0k.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-6202549846659457654</id><published>2009-08-08T14:00:00.003+03:00</published><updated>2009-08-08T17:13:04.174+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-08T17:13:04.174+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><category scheme="http://www.blogger.com/atom/ns#" term="ubuntu" /><title>Ruby 1.9.1 on Ubuntu Jaunty</title><content type="html">В репозиторії Ubuntu Jaunty немає Ruby 1.9.1, а лише пакети версії 1.9.0.&lt;br /&gt;Тому ви повинні збирати його з вихідного коду або використовувати сторонні репозиторії.&lt;br /&gt;&lt;br /&gt;Починаючи з версії 1.9.1. у комплект Ruby також входить &lt;a href="http://rubygems.org"&gt;Rubygems&lt;/a&gt;, так сказати Just Work™.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Встановлення із вихідних кодів&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Спочатку встановдюємо необхідні залежності:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo apt-get install build-essential libssl-dev libreadline5 libreadline5-dev zlib1g zlib1g-dev&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Далі скачуємо найсвіжішу версію Ruby 1.9.1 з &lt;a href="http://www.ruby-lang.org/en/downloads/"&gt;офіційного сайту&lt;/a&gt;.&lt;br /&gt;Компілюємо і встановлюємо:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;./configure --prefix=/opt/ruby191&lt;br /&gt;make&lt;br /&gt;make test&lt;br /&gt;sudo make install&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;І на сам кінець для зручності створимо відповідні посилання:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo ln -s /opt/ruby191/bin/ruby /usr/local/bin/ruby1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/testrb /usr/local/bin/testrb1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/rake /usr/local/bin/rake1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/ri /usr/local/bin/ri1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/rdoc /usr/local/bin/rdoc1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/irb /usr/local/bin/irb1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/gem /usr/local/bin/gem1.9.1&lt;br /&gt;sudo ln -s /opt/ruby191/bin/erb /usr/local/bin/erb1.9.1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Готово!&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ ruby1.9.1 -e 'puts RUBY_DESCRIPTION'&lt;br /&gt;ruby 1.9.1p243 (2009-07-16 revision 24175) [i686-linux]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Встановлення з репозиторію Ubuntu on Rails PPA&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Тим, хто вже тестує &lt;a href="https://edge.launchpad.net/~ubuntu-on-rails/+archive/ppa"&gt;Ubuntu on Rails PPA&lt;/a&gt; спеціальний бонус від &lt;a href="http://antono.info"&gt;Antono Vasiljev&lt;/a&gt;&lt;br /&gt;Додаємо новий репозиторій:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;deb http://ppa.launchpad.net/ubuntu-on-rails/ppa/ubuntu karmic main&lt;br /&gt;deb-src http://ppa.launchpad.net/ubuntu-on-rails/ppa/ubuntu karmic main&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;$ sudo apt-get update&lt;br /&gt;[...]&lt;br /&gt;W: GPG error: http://ppa.launchpad.net jaunty Release: &amp;#1057;&amp;#1083;&amp;#1110;&amp;#1076;&amp;#1091;&amp;#1102;&amp;#1095;&amp;#1110; &amp;#1087;&amp;#1110;&amp;#1076;&amp;#1087;&amp;#1080;&amp;#1089;&amp;#1080; &amp;#1085;&amp;#1077; &amp;#1084;&amp;#1086;&amp;#1078;&amp;#1091;&amp;#1090;&amp;#1100; &amp;#1073;&amp;#1091;&amp;#1090;&amp;#1080; &amp;#1087;&amp;#1077;&amp;#1088;&amp;#1077;&amp;#1074;&amp;#1110;&amp;#1088;&amp;#1077;&amp;#1085;&amp;#1110;, &amp;#1090;&amp;#1086;&amp;#1084;&amp;#1091; &amp;#1097;&amp;#1086;, &amp;#1087;&amp;#1091;&amp;#1073;&amp;#1083;&amp;#1110;&amp;#1095;&amp;#1085;&amp;#1080;&amp;#1081; &amp;#1082;&amp;#1083;&amp;#1102;&amp;#1095; &amp;#1074;&amp;#1110;&amp;#1076;&amp;#1089;&amp;#1091;&amp;#1090;&amp;#1085;&amp;#1110;&amp;#1081;: NO_PUBKEY B6C6326781C0BE11&lt;br /&gt;[...]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Додаємо публічний ключ:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;gpg --keyserver keyserver.ubuntu.com --recv B6C6326781C0BE11&lt;br /&gt;gpg --export --armor B6C6326781C0BE11 &amp;#124; sudo apt-key add -&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Встановлюємо Ruby 1.9.1:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo apt-get install ruby1.9.1 ri1.9.1 rdoc1.9.1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Також можете зібрати &lt;a href="https://launchpad.net/ubuntu/+source/ruby1.9.1"&gt;пакет&lt;/a&gt; самостійно як це описано &lt;a href="http://antono.info/ru/164-ruby-1-9-1-na-ubuntu-karmic"&gt;тут&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-6202549846659457654?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/6202549846659457654/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=6202549846659457654" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6202549846659457654?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6202549846659457654?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/a2HrCOFYImc/ruby-191-on-ubuntu-jaunty.html" title="Ruby 1.9.1 on Ubuntu Jaunty" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/08/ruby-191-on-ubuntu-jaunty.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UFQHs_eSp7ImA9WxJbE0s.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-7141627314630648185</id><published>2009-07-23T18:54:00.003+03:00</published><updated>2009-07-23T19:06:51.541+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-23T19:06:51.541+03:00</app:edited><title>Matz Has a Mac!</title><content type="html">Ця фотографія підняла мені настрій :)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiIIL4pLoI/AAAAAAAAEIA/wazSlLgoqTI/s1600-h/photo.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiIIL4pLoI/AAAAAAAAEIA/wazSlLgoqTI/s400/photo.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5361685030595276418" /&gt;&lt;/a&gt;&lt;br /&gt;Для тих хто не в курсі, це &lt;a href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto"&gt;Юкіхіро Мацумото&lt;/a&gt;(Yukihiro Matsumoto) також відомий як Matz, творець мови програмування Ruby.&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; &lt;a href="http://www.rubycentral.org/news/2009/02/26/matz-has-a-mac/"&gt;Подробиці&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-7141627314630648185?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/7141627314630648185/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=7141627314630648185" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7141627314630648185?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/7141627314630648185?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/ovbXexv4K90/matz-has-mac.html" title="Matz Has a Mac!" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiIIL4pLoI/AAAAAAAAEIA/wazSlLgoqTI/s72-c/photo.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/matz-has-mac.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYDQn8_eyp7ImA9WxJbE0s.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-3825969824484234646</id><published>2009-07-23T18:20:00.005+03:00</published><updated>2009-07-23T18:32:53.143+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-23T18:32:53.143+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="news" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="rails" /><title>Ubuntu on Rails</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiA0q7LRVI/AAAAAAAAEH4/FjSYjGExHOE/s1600-h/Ruby_on_Rails_logo.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 192px; height: 192px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiA0q7LRVI/AAAAAAAAEH4/FjSYjGExHOE/s320/Ruby_on_Rails_logo.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5361676998748620114" /&gt;&lt;/a&gt;&lt;br /&gt;Недавно на просторах &lt;a href="http://launchpad.net/"&gt;Launchpad.net&lt;/a&gt; була створена команда &lt;a href="https://launchpad.net/~ubuntu-on-rails"&gt;Ubuntu on Rails&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Ціль команди полягає у підтриманні пакетів для розробки на Ruby/Rails. Першочергово це актуальні версії rubygems і passenger.&lt;br /&gt;В команді беруть участь хлопці з &lt;a href="http://www.brightbox.co.uk/"&gt;Brightbox&lt;/a&gt;, які досі підтримують пакети passenger, nginx-passenger, ruby-ee для Ubuntu і Debian.&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; &lt;a href="http://habrahabr.ru/blogs/ruby/65157/"&gt;Подробиці&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-3825969824484234646?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/3825969824484234646/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=3825969824484234646" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3825969824484234646?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3825969824484234646?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/lXaRD2s6VqI/ubuntu-on-rails.html" title="Ubuntu on Rails" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/SmiA0q7LRVI/AAAAAAAAEH4/FjSYjGExHOE/s72-c/Ruby_on_Rails_logo.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/ubuntu-on-rails.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YHSHY9cSp7ImA9WxJbEUQ.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-6849988835446215353</id><published>2009-07-21T20:19:00.007+03:00</published><updated>2009-07-21T20:58:59.869+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-21T20:58:59.869+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="mechanize" /><category scheme="http://www.blogger.com/atom/ns#" term="vkontakte" /><title>Mechanize + Cookie + вКонтакте. Частина 6</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lXvcYH2YnAY/SmX6wNeZNgI/AAAAAAAAEHw/7pl8Y46cxMM/s1600-h/ruby_cookies.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 271px;" src="http://1.bp.blogspot.com/_lXvcYH2YnAY/SmX6wNeZNgI/AAAAAAAAEHw/7pl8Y46cxMM/s320/ruby_cookies.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5360966637612250626" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ru.wikipedia.org/wiki/HTTP_cookie"&gt;Куки&lt;/a&gt;(від англ. Cookie - печиво) - фрагмент даних, який створюється веб-сервером і зберігається на комп'ютері користувача у вигляді файлу, який веб-клієнт(зазвичай веб-браузер) кожен раз пересилає веб-серверу у HTTP-запиті при спробі відкрити сторінку відповідного сайту. Застосовується для збереження даних на стороні користувача, на практиці зазвичай використовується для:&lt;br /&gt;&lt;ul&gt; &lt;br /&gt;&lt;li&gt;автентифікації користувача;&lt;/li&gt; &lt;br /&gt;&lt;li&gt;зберігання персональних даних і налаштувань користувача;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;відслідковування стану сесії доступу користувача;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;ведення статистики про користувачів.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Бібліотека &lt;a href="http://mechanize.rubyforge.org/"&gt;WWW::Mechanize&lt;/a&gt; надає зручний інтерфей для роботи з куками -  &lt;a href="http://mechanize.rubyforge.org/mechanize/WWW/Mechanize/CookieJar.html"&gt;WWW::Mechanize::CookieJar&lt;/a&gt;. Цей клас використовується для керування куками, які були повернуті з якого-небудь конкретного сайту. Крім того дозволяє зберігати куки до файлу, з можливістю використовувати його пізніше(наприклад, для автентифікації користувача на сайті без необхідності вводу логіна і пароля). Доступні наступні формати для зберігання/завантаження куки: &lt;span style="font-style:italic;"&gt;:yaml&lt;/span&gt; &lt;- YAML структура і &lt;span style="font-style:italic;"&gt;:cookiestxt&lt;/span&gt; &lt;- Mozilla у форматі cookies.txt.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Повернемося до &lt;a href="http://ruby-ua.blogspot.com/2009/07/mechanize-nokogiri-5.html"&gt;попередньої статті&lt;/a&gt; і додамо можливість авторизації за допомогою пересилання куки вебсерверу.&lt;br /&gt;Авторизація здійснюється через надсилання куки &lt;span style="font-style:italic;"&gt;'remixpassword'&lt;/span&gt;. Значення &lt;span style="font-style:italic;"&gt;'remixpassword'&lt;/span&gt;, встановлюється в результаті успішної авторизації, і може бути використане для продовження ідентифікатора сесії(&lt;span style="font-style:italic;"&gt;'sid'&lt;/span&gt;).&lt;br /&gt;Цей метод можна використати і у &lt;a href="http://userapi.com"&gt;UserAPI&lt;/a&gt; при запиті до &lt;a href="http://login.userapi.com/auth?login=auto&amp;site=2"&gt;http://login.userapi.com/auth?login=auto&amp;site=2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Тут я не буду приводити повний лістинг.  А лише доповню код з &lt;a href="http://ruby-ua.blogspot.com/2009/07/mechanize-nokogiri-5.html"&gt;попередньої статті&lt;/a&gt;.&lt;br /&gt;Для початку потрібно авторизуватися на сайті &lt;a href="http://vkontakte.ru/"&gt;ВКонтакте&lt;/a&gt; і записати куки у файл на диску. Для цього створимо новий метод &lt;span style="font-style:italic;"&gt;save_cookie()&lt;/span&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;def save_cookie(cookie_file)&lt;br /&gt; @a.cookie_jar.save_as(cookie_file, format = :cookiestxt) &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Якщо авторизація пройшла успішно, записуємо куки у файл &lt;span style="font-style:italic;"&gt;cookie.txt&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;if login_force(id, email, pass)&lt;br /&gt;  puts &amp;quot;Successfully Authentication&amp;quot;&lt;br /&gt;  save_cookie('cookie.txt')&lt;br /&gt;else&lt;br /&gt;  puts &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Далі ми будемо авторизовуватись за допомогою цією куки. Створимо метод &lt;span style="font-style:italic;"&gt;login_auto()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;def login_auto(uid, cookie_file)&lt;br /&gt;  @a.cookie_jar.load(cookie_file, format = :cookiestxt)&lt;br /&gt;  login_page = @a.get('http://vkontakte.ru/')&lt;br /&gt;  return /http:\/\/vkontakte\.ru\/id(\d+)/ === login_page.uri.to_s ? ($1 == uid ? true : false) : false&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Надалі у нас нема необхідності використовувати метод &lt;span style="font-style:italic;"&gt;login_force()&lt;/span&gt;. Замість нього використовуємо &lt;span style="font-style:italic;"&gt;login_auto()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;if login_auto(id, 'cookie.txt')&lt;br /&gt;  puts &amp;quot;Successfully Authentication&amp;quot;&lt;br /&gt;else&lt;br /&gt;  puts &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Якщо комусь цікаво про плюси авторизації за допомогою куки(в т.ч. і на сайті ВКонтакте), залишайте коментарі.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-6849988835446215353?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/6849988835446215353/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=6849988835446215353" title="2 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6849988835446215353?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/6849988835446215353?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/bG2DXB0RRkc/mechanize-cookie-6.html" title="Mechanize + Cookie + вКонтакте. Частина 6" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_lXvcYH2YnAY/SmX6wNeZNgI/AAAAAAAAEHw/7pl8Y46cxMM/s72-c/ruby_cookies.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/mechanize-cookie-6.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUQFSX8_fyp7ImA9WxJUFU8.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-9108394456272160141</id><published>2009-07-14T00:07:00.007+03:00</published><updated>2009-07-14T01:15:18.147+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-14T01:15:18.147+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="life" /><title>розробка.com</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SluiLQeAy5I/AAAAAAAAEHY/W_EZMPalJAg/s1600-h/logo.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 267px; height: 61px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SluiLQeAy5I/AAAAAAAAEHY/W_EZMPalJAg/s400/logo.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5358054495970446226" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.rozrobka.com/"&gt;Розробка&lt;/a&gt; — молодий соціальний сайт для розробників, побудований по моделі &lt;a href="http://habrahabr.ru/"&gt;Хабрахабри&lt;/a&gt;. Сайт орієнтований на українську аудиторію розробників. Наразі проет ще досить малоактивний, але маю надію в майбутньому до нього буде залучатися все більше і більше людей.&lt;br /&gt;&lt;blockquote&gt;&lt;a href="http://www.rozrobka.com/blog/ruby/72.html"&gt;Це&lt;/a&gt; перша стаття на Розробці опублікована мною, проба пера так сказати. Прошу не судити строго. Можливо комусь вона буде цікавою. &lt;a href="http://ruby-ua.blogspot.com/2007/09/apach2-ruby-18-modruby-eruby.html"&gt;Ця стаття&lt;/a&gt; була написана мною у цьому блозі ще у вересні 2007 року. Хоча і досі не втратила своєї актуальності.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-9108394456272160141?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/9108394456272160141/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=9108394456272160141" title="4 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9108394456272160141?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9108394456272160141?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/OQ7zRLrcwmY/com.html" title="розробка.com" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_lXvcYH2YnAY/SluiLQeAy5I/AAAAAAAAEHY/W_EZMPalJAg/s72-c/logo.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/com.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUNSHs5fip7ImA9WxJUEko.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-8014579877716623315</id><published>2009-07-10T18:40:00.010+03:00</published><updated>2009-07-11T02:58:19.526+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-11T02:58:19.526+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="regexp" /><category scheme="http://www.blogger.com/atom/ns#" term="nokogiri" /><category scheme="http://www.blogger.com/atom/ns#" term="mechanize" /><category scheme="http://www.blogger.com/atom/ns#" term="vkontakte" /><title>Mechanize + Nokogiri + вКонтакте. Частина 5</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sld4REAun2I/AAAAAAAAEG4/eEzuYykd_eM/s1600-h/vkontakte_ruby.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 245px; height: 189px;" src="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sld4REAun2I/AAAAAAAAEG4/eEzuYykd_eM/s400/vkontakte_ruby.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5356882516310400866" /&gt;&lt;/a&gt;&lt;br /&gt;Ніхто не помітив зовнішніх змін. Положення тіла пацієнта &lt;a href="http://vkontakte.ru"&gt;вКонтакте&lt;/a&gt; на операційному столі залишалось незмінним. Але мушу повідомити неприємну новину: ідентифіковано мутації. Тому всі попередні дослідження [&lt;a href="http://ruby-ua.blogspot.com/2009/01/wwwmechanize-vkontakteru.html"&gt;1&lt;/a&gt;][&lt;a href="http://ruby-ua.blogspot.com/2009/03/mechanize-2.html"&gt;2&lt;/a&gt;][&lt;a href="http://ruby-ua.blogspot.com/2009/03/ruby-user-api-vkontakte-3.html"&gt;3&lt;/a&gt;][&lt;a href="http://ruby-ua.blogspot.com/2009/05/curb-ruby-curl-4.html"&gt;4&lt;/a&gt;] вважаються недійсними. Нічого... не треба падати духом.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Їжачки плакали і кололись, але продовжували кохатися з кактусами!&lt;/span&gt; &amp;copy;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;a href="http://nokogiri.rubyforge.org"&gt;Nokogiri&lt;/a&gt; - це парсер HTML, XML, SAX. Серед його численних можливостей можна виділити можливість використання &lt;a href="http://www.w3.org/TR/xpath"&gt;XPath(XML Path Language)&lt;/a&gt; і &lt;a href="http://www.w3.org/TR/css3-selectors/"&gt;CSS3 селекторів&lt;/a&gt; для пошуку.&lt;br /&gt;Крім того Nokogiri має сумісний з Hpricot синтаксис XPath та CSS.&lt;br /&gt;На даний час Nokogiri &lt;a href="http://www.rubyinside.com/ruby-xml-performance-benchmarks-1641.html"&gt;найшвидший&lt;/a&gt; парсер XML для Ruby.&lt;br /&gt;&lt;a href="http://mechanize.rubyforge.org"&gt;Mechanize&lt;/a&gt; для синтаксичного розбору html використовує саме Nokogiri.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Приклад використання:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Підключення необхідних бібліотек&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'nokogiri'&lt;br /&gt;require 'open-uri'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Завантаження HTML сторінки, використовуючи open-uri, який йде з Ruby&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;doc = Nokogiri::HTML(open('http://www.google.com/search?q=ruby-ua'))&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Пошук вузлів за допомогою CSS3 селекторів&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;doc.css('h3.r a.l').each{&amp;#124;link&amp;#124; puts link.content}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Пошук вузлів за допомогою XPath&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;doc.xpath('//h3/a[@class=&amp;quot;l&amp;quot;]').each {&amp;#124;link&amp;#124; puts link.content}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Автор рекомендує використовувати XPath селектори для вищої швидкодії - пошук CSS швидкий ніж у Hpricot, але не такий швидкий.&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Nokogiri::XML::Node#xpath(*paths)&lt;/span&gt; - функція пошук вузлів(nodes) для XPath шляхів(paths). Шлях повинен бути одним або декількома XPath запитами(queries).&lt;br /&gt;Цікавоє можливістю є задання власних функцій XPath із використанням регекспів(regexp). Для цього потрібно створити класс і застосувати функцію # яку хочете визначити. Наприклад:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;node.xpath('.//tr[mess(., &amp;quot;mess\d+&amp;quot;)]', Class.new {&lt;br /&gt;  def mess node_set, regex&lt;br /&gt;    node_set.find_all { &amp;#124;node&amp;#124; node['id'] =~ /#{regex}/ }&lt;br /&gt;  end&lt;br /&gt;}.new)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Така функція знайде всі вузли виду:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;tr id=&amp;quot;mess127&amp;quot;&amp;gt;[...]&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr id=&amp;quot;mess128&amp;quot;&amp;gt;[...]&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr id=&amp;quot;mess129&amp;quot;&amp;gt;[...]&amp;lt;/tr&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;вКонтакте!?&lt;/span&gt;&lt;br /&gt;У зв'язку зі змінами на сайті &lt;a href="http://vkontakte.ru"&gt;vkontakte.ru&lt;/a&gt; мої попередні дописи про вконтакте втратили свою актуальність. Не знаю скільки часу буде працездатним цей код. Але суть в іншому: показати принципи роботи з Mechanize і Nokogiri на реальному прикладі.&lt;br /&gt;Що ж робить нищеприведений код?&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Авторизація через надсилання email-адреси та пароля користувача; (login_force)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Отримання останніх приватних повідомлень; (get_messages)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;# -*- encoding: utf-8 -*-&lt;br /&gt;require 'mechanize' # recommended 0.9.2&lt;br /&gt;&lt;br /&gt;@a = WWW::Mechanize.new{&amp;#124;agent&amp;#124;&lt;br /&gt;  agent.user_agent_alias = 'Linux Konqueror'&lt;br /&gt;  agent.follow_meta_refresh = true&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;# Authorisation by submitting email and password (Login)&lt;br /&gt;#&lt;br /&gt;def login_force(uid, email, pass)&lt;br /&gt;  login_page = @a.get('http://vkontakte.ru/login.php')&lt;br /&gt;  login_form = login_page.form_with(:name =&amp;gt; &amp;quot;login&amp;quot;)&lt;br /&gt;  login_form.email = email&lt;br /&gt;  login_form.pass = pass&lt;br /&gt;  user_page = login_form.submit&lt;br /&gt;  return /http:\/\/vkontakte\.ru\/id(\d+)/ === user_page.uri.to_s ? ($1 == uid ? true : false) : false&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;# Getting private messages list for current user&lt;br /&gt;#&lt;br /&gt;# Structure of each entry of resulting array&lt;br /&gt;#   [0] - message from&lt;br /&gt;#   [1] - message date&lt;br /&gt;#   [2] - message title&lt;br /&gt;#   [3] - message_body&lt;br /&gt;#&lt;br /&gt;def get_messages&lt;br /&gt;  url = 'http://vkontakte.ru/mail.php'&lt;br /&gt;  messages_page = @a.get(url)&lt;br /&gt;  node = Nokogiri::HTML(messages_page.body)&lt;br /&gt;  message = node.xpath('.//tr[mess(., &amp;quot;mess\d+&amp;quot;)]', Class.new {&lt;br /&gt;    def mess node_set, regex&lt;br /&gt;      node_set.find_all { &amp;#124;node&amp;#124; node['id'] =~ /#{regex}/ }&lt;br /&gt;    end&lt;br /&gt;  }.new)&lt;br /&gt;  message_from = message.xpath('//td[@class=&amp;quot;messageFrom&amp;quot;]/div[@class=&amp;quot;name&amp;quot;]/a').map {&amp;#124;link&amp;#124; /\/id(\d+)/.match(link['href'])[1]}&lt;br /&gt;  message_date = message.xpath('//td[@class=&amp;quot;messageFrom&amp;quot;]/div[@class=&amp;quot;date&amp;quot;]').map {&amp;#124;link&amp;#124; link.content}&lt;br /&gt;  message_title = message.xpath('//a[@class=&amp;quot;new messageSubject&amp;quot;]/span').map {&amp;#124;link&amp;#124; link.content}&lt;br /&gt;  message_body = message.xpath('//a[@class=&amp;quot;new messageBody&amp;quot;]').map {&amp;#124;link&amp;#124; link.content}&lt;br /&gt;  messages = Array.new&lt;br /&gt;  messages = [message_from, message_date, message_title, message_body].transpose&lt;br /&gt;  return messages&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;id = &amp;quot;12345678&amp;quot;&lt;br /&gt;email = &amp;quot;username@example.com&amp;quot;&lt;br /&gt;pass = &amp;quot;secret&amp;quot;&lt;br /&gt;&lt;br /&gt;if login_force(id, email, pass)&lt;br /&gt;  puts &amp;quot;Successfully Authentication&amp;quot;&lt;br /&gt;  get_messages.each {&amp;#124;message&amp;#124;&lt;br /&gt;    puts &amp;quot;[#{message[1]}]: #{message[0]}&amp;quot;&lt;br /&gt;    puts message[2]&lt;br /&gt;    puts message[3]&lt;br /&gt;    puts &amp;quot;===&amp;quot;&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;  puts &amp;quot;Authentication Error&amp;quot;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-8014579877716623315?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/8014579877716623315/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=8014579877716623315" title="1 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8014579877716623315?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/8014579877716623315?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/y3uboYHSF3A/mechanize-nokogiri-5.html" title="Mechanize + Nokogiri + вКонтакте. Частина 5" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_lXvcYH2YnAY/Sld4REAun2I/AAAAAAAAEG4/eEzuYykd_eM/s72-c/vkontakte_ruby.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/mechanize-nokogiri-5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcHRX45fSp7ImA9WxJUEUo.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-3244865583546527371</id><published>2009-07-10T00:10:00.002+03:00</published><updated>2009-07-10T01:20:34.025+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-10T01:20:34.025+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="life" /><title>Blogger: Створи власний безкоштовний блог?</title><content type="html">Весь час перебування в Blogger мені не вистачало однієї корисною фічі з ЖЖ. І нарешті цей прикрий пробіл закритий.&lt;br /&gt;За &lt;a href="http://www.google.com/support/blogger/bin/answer.py?answer=42215&amp;amp;topic=8932"&gt;посиланням&lt;/a&gt; можна прочитати як створювати розширювані короткі описи повідомлень, такий собі аналог &amp;lt;lj-cut&amp;gt; з ЖЖ.&lt;br /&gt;Доведеться трохи повозитися з шаблоном. Але найважливіше воно працює :)&lt;br /&gt;Не встиг я потішитись обновці, як на і-мейл прийшов лист від Blogger.&lt;br /&gt;А-а-а-а-а!!!!!11 OMG! Хто б міг подумати? Я спамер!!! На жаль або на щастя в Україні немає безпосередньої відповідальності за поширення спаму.&lt;br /&gt;І тепер замість блогу красується заглушка з багатозначним надписом:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lXvcYH2YnAY/SlZnSywn4pI/AAAAAAAAEGo/q4W-WwBv5Bk/s1600-h/blogger.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 158px;" src="http://3.bp.blogspot.com/_lXvcYH2YnAY/SlZnSywn4pI/AAAAAAAAEGo/q4W-WwBv5Bk/s400/blogger.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5356582379364803218" /&gt;&lt;/a&gt;&lt;br /&gt;Я пам'ятайте, якщо ви читаєте цей пост, значить цей блог не містить потенційного спаму :). Перевірено Великим Ґуґло'м.&lt;br /&gt;&lt;br /&gt;Якщо комусь цікаво, під катом текст листа від Blogger.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-style:italic;"&gt;Вітаємо!&lt;br /&gt;&lt;br /&gt;   Ваш блог на: http://ruby-ua.blogspot.com/ ідентифіковано як блог із потенційним спамом.  Для вирішення цієї проблеми надішліть запит на перегляд, заповнивши форму на http://www.blogger.com/unlock-blog.g?lockedBlogID=4152168096498110483&lt;br /&gt;&lt;br /&gt;   Якщо ваш блог не буде переглянуто, його буде видалено через 20 днів, а впродовж цього періоду вашим читачам відображатиметься сторінка попередження. Після отримання запиту ми переглянемо ваш блог і розблокуємо його протягом двох робочих днів. Після того як ваш буде розглянуто та буде виявлено, що він не є спамом, блог буде розблоковано, а повідомлення на вашій панелі керування Blogger більше не відображатиметься. Якщо цей блог не належить вам, нічого робити не потрібно. Це не вплине на будь-які інші ваші блоги.&lt;br /&gt;&lt;br /&gt;   Ми шукаємо спам, використовуючи автоматичний класифікатор. Автоматичне виявлення спаму є неточним, і час від часу блоги, схожі на ваш, позначаються неправильно. Ми просимо вибачення за цю помилку. Однак за допомогою такої системи ми можемо забезпечити більше місця для зберігання, вищу пропускну здатність і більше технічних ресурсів для таких авторів блогів, як ви, а не для спамерів. Для отримання додаткової інформації див. довідку Blogger: http://help.blogger.com/bin/answer.py?answer=42577&lt;br /&gt;&lt;br /&gt;   Дякуємо за розуміння та допомогу в боротьбі зі спамом.&lt;br /&gt;&lt;br /&gt;   Із повагою,&lt;br /&gt;&lt;br /&gt;   команда Blogger&lt;br /&gt;&lt;br /&gt;   P.S. Ще одне нагадування: якщо ви не надішлете запит на перегляд вашого блогу, через 20 днів його буде видалено. Перейдіть за цим посиланням, щоб надіслати запит на перегляд: http://www.blogger.com/unlock-blog.g?lockedBlogID=4152168096498110483&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Мені от дійсно цікаво: хто і як буде перевіряти &lt;strike&gt;rub&lt;/strike&gt;україномовний блог на &lt;strike&gt;спам&lt;/strike&gt; відповідність умовам обслуговування Blogger?&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-3244865583546527371?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/3244865583546527371/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=3244865583546527371" title="1 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3244865583546527371?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/3244865583546527371?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/vTLmylzg-BM/blogger.html" title="Blogger: Створи власний безкоштовний блог?" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_lXvcYH2YnAY/SlZnSywn4pI/AAAAAAAAEGo/q4W-WwBv5Bk/s72-c/blogger.png" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/blogger.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQDSX85fip7ImA9WxJUEUo.&quot;"><id>tag:blogger.com,1999:blog-4152168096498110483.post-9005705297369167442</id><published>2009-07-05T16:22:00.006+03:00</published><updated>2009-07-09T23:46:18.126+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-09T23:46:18.126+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="regexp" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="bash" /><category scheme="http://www.blogger.com/atom/ns#" term="ruby1.9" /><title>Ruby for System Administration → Bash quoting</title><content type="html">Інколи використовую Ruby для задач системного адміністрування. Ruby з широким набором бібліотек чудово для цього підходить.&lt;br /&gt;Однією з поширених задач є виклик зовнішніх команд Linux, передачі їм різноманітних параметрів, отримання і обробки результатів. І тут ви обов'язково стикнетеся з маскуванням символів в bash.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Маскування(quoting) в bash використовується для відміни спеціального значення для команд інтерпрeтатора визначених символів або слів.&lt;br /&gt;Маскування можна використовувати для скасування специфічної обробки спеціальних символів, для запобігання розпізнавання зарезервованих слів, а також для запобігання підстановки параметрів.&lt;br /&gt;Метасимвол - це символ, який розділяє слова, якщо він не замаскований. Є одним з наступних символів:&lt;br /&gt;| &amp;amp; ; ( ) &lt; &gt; пробіл табуляція&lt;br /&gt;&lt;br /&gt;Існує три механізми маскування:&lt;br /&gt;символ маскування (escape character), одинарні лапки і подвійні лапки.&lt;br /&gt;&lt;br /&gt;Незамаскована зворотна коса риска (\) є символом маскування(escape character). Вона вимагає використовувати наступний за нею символ(за винятком переведення рядка) буквально.&lt;br /&gt;&lt;br /&gt;Усі символи в одиночних лапках (&lt;span style="font-weight: bold;"&gt;'&lt;/span&gt;) використовуються буквально. Символ одиночної лапки(апостроф) не повинен вказуватися між лапках, навіть якщо його випереджає зворотна коса.&lt;br /&gt;&lt;br /&gt;Символи в подвійних лапках(&lt;span style="font-weight: bold;"&gt;"&lt;/span&gt;) використовуються буквально, за виключенням $, !, ` і \&lt;br /&gt;Зворотна коса має спеціальне значення тільки якщо після неї йде один з спеціальних символів.&lt;br /&gt;&lt;br /&gt;З точки зору програмування, маскування з допомогою одинарних лапок є найпростішим (але не дозволяє маскувати символ одинарних лапок). Тоді як з допомогою зворотної косої - найскладніший.&lt;br /&gt;Ми не шукаємо простих шляхів :)&lt;br /&gt;&lt;br /&gt;Напишемо просто функцію, яка отримуватиме cтроку і повертатиме масковану строку, придатну для використання в bash.&lt;br /&gt;Зауважу, код буде працювати тільки в  версіями Ruby вище 1.9, оскільки в Regexp використовується нова можливість &lt;a href="http://oniguruma.rubyforge.org/"&gt;Oniguruma&lt;/a&gt; - іменовані групи(named groups).&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;#!/usr/bin/env ruby1.9&lt;br /&gt;# -*- encoding: utf8 -*-&lt;br /&gt;&lt;br /&gt;def quote_for_bash(text)&lt;br /&gt;text = text.dup&lt;br /&gt;text.gsub!( /(?&amp;lt;backslash&amp;gt;\\)/,       '\\\\\k&amp;lt;backslash&amp;gt;'       )&lt;br /&gt;text.gsub!( /(?&amp;lt;space&amp;gt;\s)/,           '\\\\\k&amp;lt;space&amp;gt;'           )&lt;br /&gt;text.gsub!( /(?&amp;lt;double-quotes&amp;gt;")/,    '\\\\\k&amp;lt;double-quotes&amp;gt;'   )&lt;br /&gt;text.gsub!( /(?&amp;lt;single-quotes&amp;gt;')/,    '\\\\\k&amp;lt;single-quotes&amp;gt;'   )&lt;br /&gt;text.gsub!( /(?&amp;lt;apostrophe&amp;gt;`)/,       '\\\\\k&amp;lt;apostrophe&amp;gt;'      )&lt;br /&gt;text.gsub!( /(?&amp;lt;brackets&amp;gt;[()&amp;lt;&amp;gt;])/,    '\\\\\k&amp;lt;brackets&amp;gt;'        )&lt;br /&gt;text.gsub!( /(?&amp;lt;semicolon&amp;gt;;)/,        '\\\\\k&amp;lt;semicolon&amp;gt;'       )&lt;br /&gt;text.gsub!( /(?&amp;lt;exclamation-mark&amp;gt;!)/, '\\\\\k&amp;lt;exclamation-mark&amp;gt;')&lt;br /&gt;text.gsub!( /(?&amp;lt;ampersand&amp;gt;&amp;amp;)/,        '\\\\\k&amp;lt;ampersand&amp;gt;'       )&lt;br /&gt;text.gsub!( /(?&amp;lt;dollar-sign&amp;gt;\$)/,     '\\\\\k&amp;lt;dollar-sign&amp;gt;'     )&lt;br /&gt;text.gsub!( /(?&amp;lt;number-sign&amp;gt;#)/,      '\\\\\k&amp;lt;number-sign&amp;gt;'     )&lt;br /&gt;text.gsub!( /(?&amp;lt;vertical&amp;gt;\|)/,        '\\\\\k&amp;lt;vertical&amp;gt;'        )&lt;br /&gt;return text&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Задамо текст, який, наприклад, в майбутньому будемо використовувати як параметр для якоїсь команди:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;text = %{#&amp;lt;b&amp;gt;$a;say "hello" &amp;amp; |Profit!|  -  (`1$)&amp;lt;/b&amp;gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Початковий текст матиме такий вигляд:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;puts text&lt;br /&gt;#&amp;lt;b&amp;gt;$a;say "hello" &amp;amp; |Profit!|  -  (`1$)&amp;lt;/b&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Маскований текст буде таким:&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;puts quote_for_bash(text)&lt;br /&gt;\#\&amp;lt;b\&amp;gt;\$a\;say\ \"hello\"\ \&amp;amp;\ \|Profit\!\|\ \ -\ \ \(\`2\$\)\&amp;lt;/b\&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4152168096498110483-9005705297369167442?l=ruby-ua.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://ruby-ua.blogspot.com/feeds/9005705297369167442/comments/default" title="Дописати коментарі" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=4152168096498110483&amp;postID=9005705297369167442" title="0 коментарі(в)" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9005705297369167442?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4152168096498110483/posts/default/9005705297369167442?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/ruby-ua/~3/MZ6HymUHN24/ruby-for-system-administration-bash.html" title="Ruby for System Administration → Bash quoting" /><author><name>_linux_</name><uri>http://www.blogger.com/profile/08026234658348754340</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="10405373108550967057" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://ruby-ua.blogspot.com/2009/07/ruby-for-system-administration-bash.html</feedburner:origLink></entry></feed>
