Показаны сообщения с ярлыком ruby. Показать все сообщения
Показаны сообщения с ярлыком ruby. Показать все сообщения

четверг, 5 января 2012 г.

Передача переменных в Ruby.

Привет.
Вот на дворе уже и новый 2012 год. Поздравляю всех с этим событием. Конец СВЕТА отменили, поэтому продолжаем жить дальше и познавать что-то новое.

Для начала простой пример1.
Пусть есть 2 переменные: var1 и var2.
var1 = 'I am var1'
var2 = var1

Какие значения имеют var1 и var2?
Правильный ответ:
var1  #=>  'I am var1'
var2  #=>  'I am var1'

А теперь давайте сделаем так:
var1 = 'I am not var1'
Какие теперь значения имеют var1 и var2?

Правильный ответ:
var1  #=> 'I am not var1' 
var2  #=> 'I am var1'

У вас не возник вопрос почему?
Ответ прост: var2 никогда не была var1, а просто указывала на тот же объект, что и var1. Новым присваиванием мы изменили ссылку на объект на который указывает var1.

Теперь еще раз =)

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

Пример2:
a = "abcdefg"
b = a
b #=> "abcdefg"
a[3] = 'R'
b #=> "abcRefg"

то есть при изменении значения переменной a, неявно изменилось и значение b, так как они содержат ссылку на один объект.

Всех с наступающим Рождеством.
Удачи.

четверг, 28 июля 2011 г.

Термин "Утиная Типизация" (Duck Typing)

Привет.

Сегодня немного расскажу о понятии "утиная типизация" или просто "утипизация" в Ruby. Ссылка на wiki-ru и wiki-eng.
Термин принадлежит Дейву Томасу (Dave Thomas) и восходит к поговорке: если что-то выглядит как утка, плавает как утка и крякает как утка, то, вероятно, это утка. (If it looks like a duck, swims like a duck and quacks like a duck, then it probably is a duck.).
Точный смысл термина "утипизация" - тема для отдельных дискуссий, скорее всего это намек на тенденцию Ruby заботиться не сколько о точном классе объекта, сколько о том, какие методы для него можно вызвать и какие операции над ним можно выполнять. Таким образом, обычным делом становится просто передать объект методу, зная, что при неправильном использовании будет выброшено исключение (exception).
Утиная типизация решает некоторые проблемы иерархической типизации:
  • невозможность явно указать (путем наследования) на совместимость интерфейса со всеми настоящими и будущими интерфейсами, с которыми он идейно совместим;
  • экспоненциальное увеличение числа связей в иерархии типов.

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

Как-то так. Всем спасибо за внимание.
До встречи.

вторник, 5 июля 2011 г.

Как проверить существование в хэше ключа (Ruby).

Привет.

Нам нужно быстро выполнить следующие действия.
Пусть есть  хэши:
hash1 = {:text => 'redf', :subtext => 'Her' }
hash2 = {:text => 'yels' }
Очется однобразно работать с этими хэшами, но в одном есть ключ subtext, а в другом нет.
Что делать?
Нужно проверить, есть ли нужный ключ в хэше и если он есть получить значение по этому ключу.
Это можно сделать используя try.
hash.try(:[], :subtext)
Если у hash есть ключ subtext, то получим значение по ключу, если ключа нет, то nil.
hash1.try(:[], :subtext) # Her
hash2.try(:[], :subtext) # nil

Вот так вот просто это делается в Ruby =)

Пока!!!

вторник, 31 мая 2011 г.

Немного про array и метод map в Ruby

В Ruby как и в других языках программирования есть массивы - класс Array.
Этот класс (Array) имеет много методов для работы с массивами раскажу об одном из этих методов map.
Поясню на примере:
Пусть есть массив arr1 = [4, 5, 6]
Мы можем создать новый массив arr2 на основе массива arr1 используя map.
arr2 = arr1.map { |a| a+6 } # [10, 11, 12]
Но есть особенность, мы хотим преобразовывать массив arr1 только для определенных элементов.
Например вот так: arr2 = arr1.map { |a| a+6 if (a > 4) } # [nil, 11, 12]
Как видно, если условие не выполнилось, то в новом массиве arr2 будут элементы nil. Для того, чтобы их не было можно воспользоваться методом compact.
arr2 = arr1.map { |a| a+6 if (a > 4) }.compact # [11, 12]
Во всех приведенных примерах методы map и compact создают ноые массивы.
Кто хочет может подумать, как оптимизировать работу с памятью.

Всем удачи.

пятница, 27 мая 2011 г.

Ключевые слова и идентификаторы в Ruby

Привет. Вот и пятница.

Сегодня в России официально начались продажи iPad2 =)

Но ... Приступим.

Ключевые (или зарезервированные) слова в Ruby обычно не применяются ни для каких иных целей. Вот их полный перечень, наверное =):
  • BEGIN 
  • END
  • alias
  • and
  • begin
  • break
  • case
  • class
  • def
  • defined?
  • do
  • else
  • elsif
  • end
  • ensure
  • false
  • for
  • if
  • in
  • module
  • next
  • nil
  • not
  • or
  • redo
  • rescue
  • retry-
  • return
  • self
  • super
  • then
  • true
  • undef
  • unless
  • until
  • when
  • while
  • yield
Имена переменных и других идентификаторов обычно начинаются с букв или специального модификатора. Основные правила таковы:
  • имена локальных переменных (и таких псевдопеременных, как self и nil начинаются со строчной буквы или знака подчеркивания _;
  • имена глобальных переменных начинаются со знака доллара $;
  • имена переменных экземпляра (принадлежащих инстанцированному объекту)  начинаются с знака «собачки» @;
  • имена переменных класса (принадлежащих классу) предваряются двум: знаками @ (@@);
  • имена констант начинаются с прописной буквы;
  • в именах идентификаторов знак подчеркивания _ можно использовать наравне со строчными буквами;
  • имена специальных переменных, начинающиеся со знака доллара (например, $1 и $/), здесь не рассматриваются.
Приведу некоторые примеры:
  • локальные переменные alpha, _ident, some_var;
  • псевдопеременные self, nil,__file__;
  • константы K6chip, Length, LENGTH;
  • переменные экземпляра @foobar, @thxll38, @not_const; 
  • переменные класса @@phydeaux, @@my_var, @@nOT_const;
  • глобальные переменные $beta, $B12vitamin, $not_CONst.
На этом все.
Удачи.

понедельник, 16 мая 2011 г.

Кое-что о Garbage Collector в Ruby

Garbage Collection (GC) в Ruby отличается от сборщиков мусора в Java, C# и некоторых других языков программирования. И отличает его то, что в Ruby GC не generational, т.е. non-generational. Это значит, что GC в Ruby не делит объекты на поколения. Суть использование «поколений объектов» (GC в Java, к примеру) сводится к тому, что вновь созданные объекты гораздо чаще становятся недостижимыми, чем те объекты, время жизни которых велико (поколений объектов - штука сама по себе не простая). Соответственно, GC, который учитывает поколения, сильно сокращает время выполнения сборки мусора, посколько количество просматриваемых объектов в ходе сборки не так уж и велико, поскольку сборщик обращает внимание только на «молодое» поколение, будучи уверенный в том, что остальные поколения он на славу почистил (существуют и другие поведенческие модели, но эта — основная). Такое деление на поколения и называется generational GC. Таким образом, GC в Ruby очень дорогая операция, потому что ему приходится просматривать все объекты в памяти, каждый раз, когда GC будет вызван.

В Ruby интересная модель управления памятью (How Ruby Manages Memory and Garbage Collection).


На этом все.
Удачной недели.


понедельник, 14 февраля 2011 г.

Если у вас undefined method `total_pages'.

Опишем ситуацию в общем виде:
Хотим сделать запрос к базе, получить данные и отсортировать их по определенному атрибуту.
Все идет хорошо и вдруг возникает ОШИБКА вида:
ActionView::TemplateError (undefined method `total_pages' for #<Array:0x5e82358>)

Это связано с испоьзованием:
escape_javascript will_paginate @transactions
и
@transactions = @transactions.sort_by { |transaction| transaction.name }

Проблема кроется в том, что Array не имеет метода total_pages.


Для того, что бы все было хорошо делаем так:
@transactions.sort! { |a,b| a.name <=> b.name }

И все работает. Спасибо ресурсу, а также.

четверг, 27 января 2011 г.

Для затравки. О проблемах с Single Table Inheritance.

Описание проблемы: Имеем разные SQL запросы для одного и того же ruby кода. Т.е. один и тотже код исполняется по разному.

Более подробнее поговорю об этом потом, а пока как решается проблема.

Глубокая статья о трудной жизни. (Ценное в комментариях)
When Rails Needs a Clue - Single Table Inheritance Problems

Ну и по этой теме.
When single-table inheritance attacks
Three Reasons Why You Shouldn't Use Single Table Inheritance
Problem with one-to-many relationship with Single Table Inheritance (Rails)
require_dependency

суббота, 15 января 2011 г.

Кратко о link_to и символах

В основе лежит пост Ruby Symbols

Как очень просто и быстро в view создать линк. Используем erb и link_to (это по "науке" ActionView helper function).
Пример использовыания:
<%= link_to 'link', :action => 'myaction' %>
Вопрос, что здесь такое :action. Это и есть символ (Symbol). В rails символы используются как строки для использования в разных местах. Если будет проще, то они являются "заполнителями" для идентификаторов и строк. 
В качестве примера, будем использовать в качестве имени действия не строку, а символ:

<%= link_to 'link', :action => :myaction %>
Вы наверное спросите: как создать символ?
Для создания символов есть несколько путей.
Приведем пример, как можно создать символ :myaction.
Это можно сделать следующими способами:

<%= link_to 'link', :action => :'myaction' %>
<% myvar = 'myaction' %>
<%= link_to 'link', :action => :"#{myvar}" %>
<%= link_to 'link', :action => myvar.intern %>
<%= link_to 'link', :action => "myaction".to_sym %>

В чем сокральная прелесть симоволов, а в том, когда символ создан, во время выполнения программы в памяти хранится только одна его копия. То есть Ruby, вместо того чтобы делать копию за копией, хранит ссылку на адрес единственной ячейки памяти.
Экономия памяти, господа, ЭКОНОМИЯ!!! =)

Быстренько о FasterCSV

Нужно просто и быстро импортировать или экспортировать в CSV!
На помощь приходит FasterCSV.
Описание и примеры использования по ссылкам:
Код и описание
Документация
Примеры как парсить CSV в Ruby (различные способы)

Если нужны примеры кода в таких постах пишем замечания в сообщениях =)

четверг, 13 января 2011 г.

Пакет RubyGems


Пакет RubyGems - менеджер пакетов для Ruby, предоставляющий возможности манипулирования гемами (gems).
gem - функциональный модуль, написанный для Ruby On Rails.


Часто используемые возможности пакета:
  • текущая версия
gem -v
  • обновление RubyGems на последнюю версию
gem update --system          # необходимо быть администратором или root
  •  поиск гема
gem search postgres -r
  • установка гема
gem install postgres
  • удаление гема
gem uninstall postgres
  • получение списка гемов, установленных локально
gem list
  • получение списка гемов на удаленных серверах
gem list -r
  • возможность использования из Ruby-кода
require 'rubygems'
  • поддержка многоверсионности при администрировании
  • поддержка многоверсионности при программировании
require 'rubygems'
gem 'activerecord', '= 1.4.0'


Дополнительная информация на rubygems.org.

Ruby и &

В Ruby можно встретить такие вот "элегантные" (элегантности хоть отбавляй) конструкции:



def contrived(a, &f)
    # блок (block) может быть доступен через f
    f.call(a)
    # но yield также работает!
    yield(a)
end
def some_method(&block) 
    block.class 
end


Объяснение этой элегантности можно найти в Унарный амперсанд

Рассмотрим пример:

User.all.map &:name           # получить массив имен пользователей

вместо


User.all.map { |user| user.name }

Сначала кажется что это свойство перечисляемых классов, но на самом деле это не так.

Магия #1.

Когда ruby встречает амперсанд (&) в последнем аргументе вызова метода,
то пытается превратить его в выполняемый блок кода (Proc). Например:

a = (1..10).to_a
a.map { |n| n*n }             # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
 
l = lambda { |n| n*n }
a.map &l                      # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Магия #2.

Ruby, встречая амперсанд, превращает обьект в выполняемый блок через вызов метода #to_proc.

И вот он главный сюрприз, вызывая #to_proc у Symbol мы получаем примерно следующий блок кода:

lambda { |x| x.send(self) }

То есть Symbol#to_proc возвращет именно тот блок, который мы от него ожидали, потому что он в таком виде уже определен в классе Symbol.


Пару слов про:


def some_method(&block) 
    block.class 
end
 
В этом примере знак & - это способ отметить аргумент, который будет соответствовать передаваемому блоку.
Для вызова блока нужно вызвать метод call у нашего блока c требуемыми параметрами (our_block.call(x))
 
Давайте узнаем, чем же на самом деле в последнем примере является наш блок (block).
 
puts some_method {}# => Proc


Вот такие чудеса.


вторник, 11 января 2011 г.

Ставим nokogiri

Бывает так, что стартуешь сервер: script/server
А он тебе в ответ:
=> Booting WEBrick
=> Rails 2.3.5 application starting on http://0.0.0.0:3000
The following gems have native components that need to be built
  nokogiri  = 1.4.1

Run `rake gems:build` to build the unbuilt gems.

Делаешь rake gems:build
А в ответ:
rake aborted!
ERROR: Failed to build gem native extension.
...
libxslt is missing.  try 'port install libxslt' or 'yum install libxslt-devel'

Выход есть!!! =)

Если у вас Ubuntu делаем так:

# ruby developer packages
sudo apt-get install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8
sudo apt-get install libreadline-ruby1.8 libruby1.8 libopenssl-ruby

# nokogiri requirements
sudo apt-get install libxslt-dev libxml2-dev
sudo gem install nokogiri

Если нужна определенная версия например 1.4.1
sudo gem install nokogiri --version '= 1.4.1'

Если остались вопросы идем: Installing Nokogiri