Уже давно хотел избавиться от упоминания в запросах sql конструкций.
Но построение через хеши условий для поиска в нынейней версии RoR(2.1) к сожалению не возможно.
Такие запросы типа: Строка по маске, больше чем, меньше чем, больше, находиться в диапазоне, не находиться в диапазоне - построить с помощью хешей невозможно.
Объединение условий по OR опять же сводилось к написанию SQL.
Плагин conditions_fu расширяет возможности ActiveRecord::Base#find методами позволяющими решить вышеуказнные проблемы.
Установка
$ script/plugin install git://github.com/xgamerx/conditions_fu.git Использование
Person.all(:conditions => { :age.gt => 30, :name.like => "%упкин" })
найдет всех кто заканчивается на "упкин" старше 30 лет
Person.any(:conditions => { :age.gt => 30, :name.like => Person.all(:conditions => { :age.gt => 30, :name.like => "%name%" })
})
найдет всех старше 30 лет или чье имя заканчивается на "упкин"
Подробней и перечень операторов можно посомтреть тут rubyhammer.com/articles/2008-08-20-182530-conditions_fu-postroitel-zaprosov
Существует определенный класс задач, когда необходимо реализовать отношение "многие-ко-многим". Довольно интересным являеться случай когда узел может иметь больше одного родителя. Проще говоря, математический граф построенный на одной модели когда его элементы пренадлежат одной сущности.
Ruby CMF Web
\ | /
\_|_/
Rails
/ | \
/ | \
AR AV AC
Создадим миграцию для модели категорий
class CreateCategories < ActiveRecord::Migration
def self.up
create_table :categories do |t|
t.column :name, :string
t.timestamps
end
end
def self.down
drop_table :categories
end
end
Создадим миграцию для таблицы со связями
class Relations < ActiveRecord::Migration
def self.up
create_table :relations, :id => false do |t|
t.column :parent_id, :integer
t.column :child_id, :integer
end
end
def self.down
drop table :relations
end
end
Основной интерес составляет модель категорий и декларация связей has_and_belongs_to_many через вышеупомянутую таблицу.
class Category < ActiveRecord::Base
has_and_belongs_to_many :parents,
:join_table => 'relations',
:foreign_key => 'parent_id',
:association_foreign_key => 'child_id',
:class_name =>'Category'
has_and_belongs_to_many :children,
:join_table => 'relations',
:foreign_key => 'child_id',
:association_foreign_key => 'parent_id',
:name => 'Category'
end
Миграция заполняющая тестовые данные моделирующиее граф указанный на картинке
class TestDataGenerate < ActiveRecord::Migration
def self.up
c_ruby = Category.create :name => 'Ruby'
c_cmf = Category.create :name => 'CMF'
c_web = Category.create :name => 'WEB'
c_rails = Category.create :name => 'Rails'
c_ar = Category.create :name => 'AR'
c_av = Category.create :name => 'AV'
c_ac = Category.create :name => 'AC'
c_rails.parents << [c_ruby, c_cmf, c_web]
c_rails.children << [c_ar, c_av, c_ac]
end
def self.down
end
end
Переходим в консоль и проверяем правильность выполнения поставленной задачи. Находим категорию Rails и запрашиваем у нее имена(для краткости вывода) дочерних и родительских категорий.
>> rs = Category.find_by_name('Rails')
=> #
>> rs.children.find :all, :select => :name
=> [#, #, #]
>> rs.parents.find :all, :select => :name
=> [#, #, #]
Хочу отметить, что такое решение являеться независимым от синтаксиса SQL большенства реляционных БД отвечающим стандарту SQL92.
Другие варианты решения и нюансы описаны в статьях:
* http://szeryf.wordpress.com/2007/06/27/self-referential-many-to-many-relations-in-ruby-on-rails/
* http://wiki.rubyonrails.org/rails/pages/HowToCreateASelfReferentialManyToManyRelationship
Существует решение в виде плагина: http://tammersaleh.com/posts/acts_as_graph
Но как пишет его автор, плагин давно не тестировался.
P.S. acts_as_graph -реализует рекурсивный обход графа.
Немно смешно и грустно. Но иногда встречаются посты на тему "все не работает".
Кот в сапогах попросил людоеда превратиться в мышь.
- Да. Ответил людоед. ОП - и.... превратился в мышь...
- Кот кинулся на мышь .... а мыш взлетела и повисла на потолке... потому как _летучей_ оказалась !
Вывод: если хотите получить правильный результат, то максимально точно формулируйте задачу...
Платформа: win, nix ?
Версия rails ?
Хостинг или локальное использование ?
Версия базы данных ?
Кодировка базы данных ?
Можно прописать это все в коментариях к профайлу и отображать в каждом посте, если вышеуказанные параметры более-менее стабильны.
Каждая мелочь приближает вас с решению вашей проблемы :-)
P.S. "шеф все пропало" - приключения капитана Врунгеля :-)
По мотивам Как получить полный список дерикторый samba машины
Это даже не пост, а скорее резюме "злоключений" решения данной задачи для Debian Lenny/sid.
Проблемы начались после скачивания исходников и запуска:
sudo ruby extsetup.rb
Не находило: mkmf
Помогла установка пакета:
sudo apt-get install ruby1.8-dev
Небыло команды locate, чтобы поискать файлы. И хоть к делу ето не относится, но все равно пусть будет :-)
sudo aptitude install mlocate
sudo updatedb
Библиотеки для samba
sudo aptitude install libsmbclient-dev
После запуска простого скрипта
require 'smb'
сломалось с уведомлением
params.c:OpenConfFile() - Unable to open configuration file "/home/myhome/.smb/smb.conf":
No such file or directory
cp /etc/samba/smb.conf /home/myhome/.smb/
После этого все почесному заработало. Спасибо Руслану за рекомендации и помощь :-)
Волей судеб так сложилось, что я работаю под windows и основным моим IDE являеться FAR :-)
Кому-то это может показаться довольно аскетично. Но поднимать IDE типа NetBeans или Eclipse для написания скриптовых утилит я считаю нерациональным решением.
На днях мне понадобилось конвертировать данные n-го количество файлов в кодировке Win1251 в нижний регистр.
Как известно методы работы с регистром для неанглийских языков в Ruby нереализованны(по крайне мере так говорят книги). Связываться с кодировкой utf-8 так же не хотелось, так как встроенный редактор FAR ее просто не поддерживает, без дополнительніх плагинов. Скорость работы скриптов мне тоже была не критична, так что задача была решена следующим способом:
# Устанавливаем кодировку UTF-8
$KCODE = "UTF8"
# Задействуем библиотеку activesupport, чтобы получить доступ к
# Модулю мультибайт Multibyte (Юлий Тарханову),
# который добавит к строкам метод chars (<прокси> для операций над utf-8-символами)
require 'activesupport'
# Добавим библиотеку iconv для поддержки конвертации строк из одной кодировки
# в другую и добавим несколько вспомогательных методов, имена которых говорят
# сами за себя
require 'iconv'
class String
def win1251_to_utf8
Iconv.new("UTF-8", "WINDOWS-1251").iconv self.to_s
end
def utf8_to_win1251
Iconv.new("WINDOWS-1251", "UTF-8").iconv self.to_s
end
def downcase_win1251
self.to_s.win1251_to_utf8.chars.downcase.utf8_to_win1251
end
end
puts "ПРИВЕТ МИР".downcase_win1251 # привет мир
puts "прЮвет мИр".win1251_to_utf8.chars.upcase.utf8_to_win1251 # ПРЮВЕТ МИР
puts "прЮвет мИр".win1251_to_utf8.chars.capitalize.utf8_to_win1251 # Прювет мир
Наверное возможны более компактные варианты, но на данном этапе такое решение задачи меня удовлетворило :-)