Play - музыкальный сервер от GitHubAlex Soulim

Продолжая тему слайдов, хочу поделиться ссылкой на стопку слайдов к выступлению Зака Холмана (Zach Holman) - . Вы узнаете о проекте Play - музыкальном сервере в офисе GitHub.

Просто красивые слайды, это еще не конец истории :) Код Play открыт и доступен на GitHub - . Play имеет специфичные требования к окружению, но об этом подробно рассказано в README.

P.S. Советую посмотреть и другие слайды от Зака, если вы этого еще не сделали.

Слайды доклада "10 Things You Didn't Know Rails Could do" от JEG2Сергей Резванов

Прогугливаясь по просторам интернета в поисках инетересной информации, я наткнулся на доклад ruby-гуру Джеймса Эдварда Грея II. В нем собрана информация о функциональности rails, о которой вы, возможно, и не знали. Лично я для себя нашел достаточно много нового, надеюсь, вы тоже найдете... Приятного чтения!

Ссылка:

С уважением, .

Комментарии
Ben Goikhman

Презентация действительно очень хорошая. Всем очень рекомендую.

"Stay young, stay curious, stay hippy..." - доклад Дэвида Хайнемайера Хенссона с конференции "RailsConf 2012"Сергей Резванов

В сети выложен видео-доклад Дэвида с конференеции "RailsConf 2012". Всем, кто еще не видел, очень советую...

Молодой, знергичный, дерзкий и в то же время достаточно мудрый, он высказал свою точку зрения на прогресс в разработке программного обеспечения в целом и rails в частности.

Несмотря на наличие ненормативной лексики, доклад получился очень и очень хорошим. Я получил массу удовольствия и не раз посмеялся, чего и вам желаю.

Ссылка:

С уважением, .

Skypekit for RubyAlexey

Skypekit для Ruby - библиотека для работы со Skype протоколом

ActiveRecord::Relation#merge или как объединиться с друзьямиRoman

Цель данного обзора показать пару приемов использования метода #merge из модуля ActiveRecord::SpawnMethods, предназначенного для объединения скоупов. relation_destination.merge(relation_source) добавляет sql-выражение из relation_source в итоговый relation_destination. Приведу пару примеров.

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

Order.paid.joins(:user).where(:users => { :eye_color => 'blue' })

# => SELECT "orders".* 
     FROM "orders" 
     INNER JOIN "users" ON "users"."id" = "orders"."user_id" 
     WHERE "orders"."status" = 3 AND "users"."eye_color" = 'blue'

Но в таком подходе есть проблема: мы должны знать все тонкости выборки этих самых клиентов с голубыми глазами. И возможно, что таковыми должны быть не только клиенты с признаком eye_color => 'blue', но и со статусом равным 1. В таком случае, чтобы разместить логику «голубых глаз» в едином удобном месте логично сделать scope в модели User:

class User < ActiveRecord::Base
  STATUS = { :visible => 1 }
  has_many :orders

  scope :blue_eye, where(:eye_color => 'blue', :status => STATUS[:visible])
end

Теперь мы можем изменить первый вариант на:

Order.paid.where(:user_id => User.blue_eye.pluck(:id))

# => SELECT id FROM "users" 
     WHERE "users"."eye_color" = 'blue' AND "users"."status" = 1
# => SELECT "orders".* FROM "orders" 
     WHERE "orders"."status" = 3 AND "orders"."user_id" IN (2, 3)   

Таким образом мы избавились от первоначальной проблемы. Но возник другой момент: такая запись генерирует 2 запроса к БД (к пользователям и к заказам). При этом id'шники пользователей будут переданы во второй sql-запрос. И если пользователей с голубыми глазами будет много (сотни/тысячи), то sql-команда получится очень длинной и в большинстве случаев далеко не оптимальной (разбор плана и т.д.).

И вот на помощь к нам приходит Relation#merge:

Order.paid.joins(:user).merge(User.blue_eye)

# => SELECT "orders".* 
     FROM "orders" INNER JOIN "users" ON "users"."id" = "orders"."user_id" 
     WHERE "orders"."status" = 3 AND "users"."eye_color" = 'blue' 
     AND "users"."status" = 1

Такая цепочка вернет нужные нам заказы за один запрос с использованием SQL оператора JOIN. На мой взгляд, это выглядит достаточно лаконично, причём как с точки зрения AR, так и точки зрения результирующего sql-запроса. Если по какой-то причине мы изменим логику получения клиентов с голубыми глазами, то достаточно будет изменить scope в модели User и все другие запросы получат новые условия.

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

class Friendship < ActiveRecord::Base
  STATUS = {:verified => 5}
  belongs_to :user
  belongs_to :friend, :class_name => 'User',
             :conditions => { :friendships => { :status => STATUS[:verified] } }
end

class Article < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  STATUS = { :visible => 1 }
  has_many :friendships, :dependent => :destroy
  has_many :friends, :through => :friendships,
           :conditions => { :status => STATUS[:visible] }
  has_many :articles

end

Несколько вариантов достижения поставленной цели:

1) Все условия в одном вызове:

 user = User.first

 Article.joins(:user).
   joins('INNER JOIN friendships on users.id = friendships.friend_id').
   where(:friendships => 
     { :user_id => user, :status => Friendship::STATUS[:verified]}).
   where( :users => {:status => User::STATUS[:visible]}).
   order('articles.rating desc')

# => SELECT "articles".* 
     FROM "articles" INNER JOIN "users" ON "users"."id" = "articles"."user_id" 
     INNER JOIN friendships on users.id = friendships.friend_id 
     WHERE "friendships"."user_id" = 1 AND "friendships"."status" = 5 
     AND "users"."status" = 1 
     ORDER BY articles.rating desc

2) 2 sql-запроса, идентификаторы пользователей передаются списком в функцию IN:

user = User.first
Article.where(:user_id => user.friends).
  order('articles.rating desc')

# => SELECT "users".* 
     FROM "users" INNER JOIN "friendships" 
       ON "users"."id" = "friendships"."friend_id" 
     WHERE "friendships"."user_id" = 1 
     AND ("friendships"."status" = 5 AND "users"."status" = 1)

# => SELECT "articles".* FROM "articles" 
     WHERE "articles"."user_id" IN (2, 3) 
     ORDER BY articles.rating desc

3) В один запрос с JOIN:

user = User.first
Article.joins(:user).merge(user.friends.scoped).
  order('articles.rating desc')

# => SELECT "articles".* 
     FROM "articles" INNER JOIN "users" ON "users"."id" = "articles"."user_id" 
     INNER JOIN "friendships" ON "users"."id" = "friendships"."friend_id" 
     WHERE "friendships"."user_id" = 1 
     AND ("friendships"."status" = 5 AND "users"."status" = 1) 
     ORDER BY articles.rating desc

Пример с Relation#merge демонстрирует как получить sql-запрос с объединением по друзьям. Немаловажно то, что в запрос включены все те условия, которые мы задали в ассоциациях.

На этом можно было бы и закончить данный обзор, но остался ещё один подводный камень: в Rails 3.0.x такой красивый merge к сожалению изменит SELECT "articles".* FROM на SELECT "users".* FROM, что в результате вернет пользователей, а не статьи. Чтобы это побороть, можно добавить метод экземпляра в модель User:

def join_friends
  Friendship.scoped.
    joins('INNER JOIN friendships on friendships.friend_id = users.id').
    where(:user_id => id, :status => Friendship::STATUS[:verified]).
    where(:users => {:status => STATUS[:visible]})
end

Тогда популярные статьи друзей можно получить так:

user = User.first
Article.joins(:user).merge(user.join_friends).
  order('articles.rating desc')

# => SELECT "articles".* 
     FROM "articles" INNER JOIN "users" ON "users"."id" = "articles"."user_id" 
     INNER JOIN friendships on friendships.friend_id = users.id 
     WHERE "friendships"."user_id" = 1 AND "friendships"."status" = 5 
     AND "users"."status" = 1 
     ORDER BY articles.rating desc

Вот и все, спасибо за внимание!

Полезные ссылки:

Комментарии
Nikita

Хороший обзор, спасибо. Только "немаловажно" в три слова режет глаз )

DevConf: открыто голосованиеAlex Soulim

Всего подано 57 заявок в восьми категориях. В категории посвященной Ruby предлагаются следующие темы:

У вас есть возможность отдать свой голос за интересные доклады -

Для заинтересовавшихся RubyMotionAlex Soulim

Репозиторий с эксперементальными проектами - .

В файле можно найти большое количество ссылок на проекты с открытым кодом на базе RubyMotion.

Если вы еще не знаете что такое RubyMotion, то начните со статьи "Ruby для iOS".

Комментарии
Alex Soulim

iOS определяет то, что проект рассчитан на разработчиков, использующих Mac OS. Насколько мне известно, на данный момент единственной операционной системой, в которой можно вести полноценную разработку софта для iOS является Mac OS.

SeedDumpAlex Soulim

SeedDump - плагин добавляющий rake-задачу db:seed:dump. Эта задача генерирует файл db/seeds.rb на основе уже существующей базы данных.

Пример:

rake db:seed:dump

Получаем файл db/seeds.rb со следующим содержимым:

# Autogenerated by the db:seed:dump task
# Do not hesitate to tweak this to your needs

products = Product.create([
  { :category_id => 1, :description => "Long Sleeve Shirt", :name => "Long Sleeve Shirt" },
  { :category_id => 3, :description => "Plain White Tee Shirt", :name => "Plain T-Shirt" }
])

users = User.create([
  { :id => 1, :password => "123456", :username => "test_1" },
  { :id => 2, :password => "234567", :username => "tes2" }
])

Есть возможность добавлять в файл, а не перезаписывать его. Можно указать другой выходной файл, а не только db/seeds.rb.

Узнайте остальные подробности в README на GitHub -

Комментарии
Pavel Galeta

Кстати, а как быть с паролями? Они же шифруются...

Bloggy - возможность добавить блог на базе Jekyll в Rails-приложениеAlex Soulim

Bloggy - это небольшая библиотека, позволяющая "завести" блог на базе Jekyll в вашем Rails-приложении.

Jekyll - это генератор статических сайтов, созданный Томом Престоном-Вернером ().

Чтобы начать пользоваться Bloggy, добавьте в Gemfile следующую строку:

gem ‘bloggy’

и выполните

$ bundle

Далее генерируем все необходимое для первого старта:

$ rails g jekyll:blog blog

Готово! Ваш блог доступен по адресу

Хотите знать больше? Читайте подробности в README на GitHub -

Фестиваль профессионального развития для IT-специалистов – Bit ByteAlex Soulim

19 мая компания ITmozg проводит в Санкт-Петербурге крупнейшее мероприятие для IT-специалистов – Bit Byte.

Bit Byte – это фестиваль профессионального развития, где студенты технических специальностей, и специалисты с опытом работы в IT в 2-4 года после окончания ВУЗа смогут пообщаться с представителями крупнейших IT-компаний и успешных стартапов и послушать выступления звезд IT.

В программе:

Общение с лучшими компаниями страны и города: EMC, Mail.ru Group, Oracle, Embria, Motorola Mobility, Ascreen , Epam, «Код безопасности», «Институт Сетевых технологий» и другие.

Выступления экспертов. Своим опытом поделятся эксперты из проекта «Одноклассники» компании Mail.ru Group, компаний «Яндекс.Деньги», «Фотострана.ру», Oktogo, Sup Media. Из Москвы специально на мероприятие приезжают Алена Попова и Леонид Бугаев. Руководитель ЖЖ в России, Илья Дронов, тоже приедет на конференцию, правда, не выступать, а просто как участник.


А также внимание к стартапам, гаджеты и игрушки.

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

Все подробности на .