Skip to content

Instantly share code, notes, and snippets.

@foxweb
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save foxweb/24216ea74194a4fd66d2 to your computer and use it in GitHub Desktop.
Save foxweb/24216ea74194a4fd66d2 to your computer and use it in GitHub Desktop.
# create_table :domains, force: true do |t|
# t.string :slug, null: false
# t.integer :path, default: [], null: false, array: true
# t.datetime :created_at
# t.datetime :updated_at
# end
#
# add_index :domains, [:slug, :path], name: :index_domains_on_slug_and_path, unique: true, using: :btree
class Domain < ActiveRecord::Base
has_many :urls
scope :with_path_including, -> (number) { where('path @> ARRAY[?]', number) }
# Возвращает полное название хоста со всеми поддоменами всех уровней на основе path.
def full_hostname
([slug] + path.reverse.map{|id| Domain.select(:slug).find(id).slug }).join('.')
end
# Находит или создаёт запись на основе строки домена
#
# @param [String] hostname Полное имя хоста (news.yandex.ru)
#
# @return [Domain] первый найденный или созданный домен
#
# @todo Избавиться от domain.reload и сделать так, чтобы на последней итерации в path не добавлялся id самого себя.
def self.find_or_create_by_hostname(hostname)
domain = nil
slugs_array(hostname).each_with_object([]) do |slug, path|
domains = Domain.where(slug: slug)
domains = path.empty? ? domains.where("path = '{}'") : domains.where('path = ARRAY[?]', path)
begin
domain = domains.first_or_create do |domain|
domain.path = path
end
rescue ActiveRecord::RecordNotUnique
retry
end
path << domain.id
end
domain.reload
end
# Находит или создаёт запись на основе строки домена
#
# @param [String] hostname Полное имя хоста (news.yandex.ru)
#
# @return [Array] массив фрагментов домена, перевёрнутый наоборот и без пустых элементов (`['ru', 'yandex', 'news']`)
def self.slugs_array(hostname)
return [] unless hostname.is_a?(String)
hostname.split('.').reverse.reject(&:empty?)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment