dircat 0.1.12 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE.txt +1 -1
- data/README.md +31 -6
- data/bin/dircat +5 -1
- data/bin/scat +9 -0
- data/dircat.gemspec +48 -15
- data/examples/example.rb +2 -1
- data/lib/dircat.rb +29 -34
- data/lib/dircat/cat_on_sqlite/cat_on_sqlite.rb +177 -0
- data/lib/dircat/cat_on_sqlite/directory_visitor.rb +106 -0
- data/lib/dircat/cat_on_sqlite/migration/00_create_dircat_properties.rb +13 -0
- data/lib/dircat/cat_on_sqlite/migration/01_create_categories.rb +12 -0
- data/lib/dircat/cat_on_sqlite/migration/02_create_images.rb +16 -0
- data/lib/dircat/cat_on_sqlite/migration/03_create_items.rb +23 -0
- data/lib/dircat/cat_on_sqlite/migration/04_create_taggings.rb +13 -0
- data/lib/dircat/cat_on_sqlite/migration/05_create_tags.rb +13 -0
- data/lib/dircat/cat_on_sqlite/model/category.rb +16 -0
- data/lib/dircat/cat_on_sqlite/model/image.rb +24 -0
- data/lib/dircat/cat_on_sqlite/model/item.rb +19 -0
- data/lib/dircat/cat_on_sqlite/model/tag.rb +58 -0
- data/lib/dircat/cat_on_sqlite/model/tagging.rb +9 -0
- data/lib/dircat/cat_on_sqlite/simple_cataloger_error.rb +9 -0
- data/lib/dircat/cat_on_sqlite_cli/cli_cat.rb +25 -0
- data/lib/dircat/cat_on_sqlite_cli/cli_server.rb +65 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_create.rb +56 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_list.rb +72 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_server.rb +62 -0
- data/lib/dircat/cat_on_sqlite_cli/cmd_update.rb +49 -0
- data/lib/dircat/{cat.rb → cat_on_yaml/cat_on_yaml.rb} +22 -10
- data/lib/dircat/cat_on_yaml/entry.rb +64 -0
- data/lib/dircat/{cli → cat_on_yaml_cli}/cli_dircat.rb +0 -0
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_build.rb +53 -12
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_diff.rb +4 -4
- data/lib/dircat/{cli → cat_on_yaml_cli}/command_query.rb +16 -2
- data/lib/dircat/config.rb +25 -0
- data/lib/dircat/extensions.rb +26 -0
- data/lib/dircat/server/helpers.rb +60 -0
- data/lib/dircat/server/my_static.rb +40 -0
- data/lib/dircat/server/web_server.rb +176 -0
- data/lib/dircat/version.rb +2 -1
- data/lib/dircat_on_sqlite.rb +31 -0
- data/lib/dircat_on_sqlite_cli.rb +37 -0
- data/lib/simple_cataloger_dm/cli.rb +32 -0
- data/lib/simple_cataloger_dm/core.rb +43 -0
- data/lib/simple_cataloger_dm/core/catalog.rb +141 -0
- data/lib/simple_cataloger_dm/core/directory_visitor.rb +107 -0
- data/lib/simple_cataloger_dm/core/extensions.rb +26 -0
- data/lib/simple_cataloger_dm/core/simple_cataloger_error.rb +9 -0
- data/lib/simple_cataloger_dm/models/category.rb +21 -0
- data/lib/simple_cataloger_dm/models/image.rb +30 -0
- data/lib/simple_cataloger_dm/models/item.rb +24 -0
- data/lib/simple_cataloger_dm/models/tag.rb +62 -0
- data/lib/simple_cataloger_dm/models/tagging.rb +11 -0
- data/lib/simple_cataloger_dm/server/helpers.rb +60 -0
- data/lib/simple_cataloger_dm/server/my_static.rb +40 -0
- data/lib/simple_cataloger_dm/server/web_server.rb +171 -0
- data/spec/dircat/cat_on_sqlite/cat_on_sqlite_spec.rb +41 -0
- data/spec/dircat/cat_on_sqlite_web/web_server_spec.rb +30 -0
- data/spec/dircat/{cat_spec.rb → cat_on_yaml/cat_on_yaml_spec.rb} +20 -14
- data/spec/dircat/{cli → cat_on_yaml_cli}/cli_dircat_spec.rb +0 -0
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_build_spec.rb +4 -4
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_diff_spec.rb +0 -0
- data/spec/dircat/{cli → cat_on_yaml_cli}/command_query_spec.rb +1 -1
- data/spec/fixtures/certified_output/cat_dir1_20120811.yaml +25 -0
- data/spec/fixtures/certified_output/cat_dir2_20120811.yaml +34 -0
- data/spec/fixtures/certified_output/{dircat1.yaml → dircat1_version_0.1.yaml} +0 -0
- data/spec/fixtures/certified_output/{dircat2.yaml → dircat2_version_0.1.yaml} +0 -0
- data/spec/fixtures/dir4/file1.txt +1 -0
- data/spec/fixtures/dir4/file2.txt +1 -0
- data/spec/fixtures/dir4/subdir/file3.txt +1 -0
- data/spec/fixtures/films/A-Z/A/Arancia meccanica [Stanley Kubrick][1971]/folder.jpg +0 -0
- data/spec/fixtures/films/A-Z/P/Plan 9 [Edward Wood][1959]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1940] Dersu Uzala [5]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Akira Kurosawa]/[1965] Barbarossa [Toshiro Mifune][4]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Federico Fellini]/[1963] 8 e mezzo [Marcello Mastroianni][Claudia Cardinale][5]/folder.jpg +0 -0
- data/spec/fixtures/films/Directors/[Woody Allen]/[1977] Annie Hall [Diane Keaton][5]/folder.jpg +0 -0
- data/{.gemtest → spec/fixtures/readme.txt} +0 -0
- data/spec/fixtures/tmp/test_ar.sqlite3 +0 -0
- data/spec/fixtures/tmp/test_ar.yml +7 -0
- data/spec/generate_directories_to_catalog.rb +80 -0
- data/spec/generate_mysql_catalog.rb +124 -0
- data/spec/spec_helper.rb +29 -0
- data/tasks/rspec.rake +0 -2
- metadata +390 -112
- data/lib/dircat/entry.rb +0 -61
- data/lib/dircat/extension_md5.rb +0 -25
- data/lib/dircat/extension_numeric.rb +0 -15
- data/spec/dircat/md5_spec.rb +0 -8
- data/spec/dircat/numeric_spec.rb +0 -13
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# std lib
|
|
4
|
+
#
|
|
5
|
+
require 'pp'
|
|
6
|
+
require 'optparse'
|
|
7
|
+
require 'fileutils'
|
|
8
|
+
require 'ostruct'
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# rubygems
|
|
12
|
+
#
|
|
13
|
+
gem "treevisitor", "0.2.2"
|
|
14
|
+
require 'treevisitor'
|
|
15
|
+
|
|
16
|
+
gem "optparse-command", "0.1.7"
|
|
17
|
+
require 'optparse-command'
|
|
18
|
+
|
|
19
|
+
require 'dm-core'
|
|
20
|
+
require 'dm-migrations'
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
# simple catalog
|
|
24
|
+
#
|
|
25
|
+
require 'simple_cataloger/version'
|
|
26
|
+
require 'simple_cataloger/simple_cataloger_error'
|
|
27
|
+
require 'simple_cataloger/extensions'
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# db models
|
|
31
|
+
#
|
|
32
|
+
require 'simple_cataloger/models/item'
|
|
33
|
+
require 'simple_cataloger/models/tag'
|
|
34
|
+
require 'simple_cataloger/models/tagging'
|
|
35
|
+
require 'simple_cataloger/models/category'
|
|
36
|
+
require 'simple_cataloger/models/image'
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# app
|
|
40
|
+
#
|
|
41
|
+
require 'simple_cataloger/directory_visitor'
|
|
42
|
+
require 'simple_cataloger/catalog'
|
|
43
|
+
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
class Catalog
|
|
4
|
+
|
|
5
|
+
attr_reader :name
|
|
6
|
+
|
|
7
|
+
def initialize(name)
|
|
8
|
+
@name = name
|
|
9
|
+
|
|
10
|
+
# find directory where to store catalog data
|
|
11
|
+
home_dir = ENV['HOME'] || ENV['APPDATA']
|
|
12
|
+
if RUBY_PLATFORM =~ /linux/
|
|
13
|
+
catalogs_dir = File.expand_path(File.join(home_dir, ".simple_cataloger"))
|
|
14
|
+
else
|
|
15
|
+
catalogs_dir = File.expand_path(File.join(home_dir, "simple_cataloger"))
|
|
16
|
+
end
|
|
17
|
+
Dir.mkdir(catalogs_dir) unless File.directory?(catalogs_dir)
|
|
18
|
+
|
|
19
|
+
db_filepath = File.join(catalogs_dir, "#{name}.sqlite3")
|
|
20
|
+
db_log_filepath = File.join(catalogs_dir, "#{name}.log")
|
|
21
|
+
@config_filepath = File.join(catalogs_dir, "#{name}.yml")
|
|
22
|
+
setup_db(db_filepath, db_log_filepath)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#
|
|
26
|
+
# Create a new catalog
|
|
27
|
+
# @param array of directories
|
|
28
|
+
#
|
|
29
|
+
def create(*catalog_roots)
|
|
30
|
+
if File.exist? @config_filepath
|
|
31
|
+
raise SimpleCatalogerError, "cannot create already existent catalog '#{@name}'"
|
|
32
|
+
end
|
|
33
|
+
@config = {
|
|
34
|
+
:roots => catalog_roots,
|
|
35
|
+
:ignore => ['sub', 'subtitles', 'images'],
|
|
36
|
+
:version => SimpleCataloger::VERSION
|
|
37
|
+
}
|
|
38
|
+
write_config
|
|
39
|
+
update
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Rebuild catalog
|
|
44
|
+
#
|
|
45
|
+
def update
|
|
46
|
+
unless File.exist? @config_filepath
|
|
47
|
+
raise "cannot update catalog #{@name}"
|
|
48
|
+
end
|
|
49
|
+
read_config
|
|
50
|
+
#
|
|
51
|
+
# migrate db
|
|
52
|
+
#
|
|
53
|
+
DataMapper.auto_migrate!
|
|
54
|
+
#DataMapper.auto_upgrade!
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Initialize categories
|
|
58
|
+
#
|
|
59
|
+
if @config[:categories]
|
|
60
|
+
# pp @config[:categories]
|
|
61
|
+
@config[:categories].each_pair do |category, tags|
|
|
62
|
+
# puts category
|
|
63
|
+
cat = Category.first_or_create(:name => category)
|
|
64
|
+
tags.each do |name|
|
|
65
|
+
tag = Tag.first_or_create(:name => name)
|
|
66
|
+
tag.category = cat
|
|
67
|
+
tag.save
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# read catalog root
|
|
74
|
+
#
|
|
75
|
+
@config[:roots].each do |root|
|
|
76
|
+
dtw = TreeRb::DirTreeWalker.new(root)
|
|
77
|
+
dtw.ignore /^\./
|
|
78
|
+
@config[:ignore].each do |i|
|
|
79
|
+
dtw.ignore i
|
|
80
|
+
end
|
|
81
|
+
dtw.visit_file=true
|
|
82
|
+
dtw.run(DirectoryVisitor.new(root))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
#
|
|
86
|
+
# cache rating tag
|
|
87
|
+
#
|
|
88
|
+
rating = Category.first(:name => "rating")
|
|
89
|
+
if rating
|
|
90
|
+
Item.all.each do |item|
|
|
91
|
+
t = item.tags.find { |t| t.category == rating }
|
|
92
|
+
if t
|
|
93
|
+
item.rating = t.name.to_i
|
|
94
|
+
item.save
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def setup_db(db_path, db_log_filepath)
|
|
101
|
+
#TODO: logger usabile per loggare altri eventi oltre a quelli del db
|
|
102
|
+
DataMapper::Logger.new(db_log_filepath, :debug)
|
|
103
|
+
DataMapper.setup(:default, "sqlite3:#{db_path}")
|
|
104
|
+
DataMapper.finalize
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
#
|
|
108
|
+
# array of roots
|
|
109
|
+
#
|
|
110
|
+
def roots
|
|
111
|
+
read_config unless @config
|
|
112
|
+
@config[:roots]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
#
|
|
116
|
+
# update config file with tag category list and association from category to tag name,
|
|
117
|
+
# so to not lose the association next time the catalog is rebuilt (updated)
|
|
118
|
+
#
|
|
119
|
+
def update_categories
|
|
120
|
+
h = {}
|
|
121
|
+
Category.all.each do |category|
|
|
122
|
+
next if ["rating", "year", "unknown"].include?(category.name)
|
|
123
|
+
h[category.name] = category.tags.collect { |tag| tag.name }
|
|
124
|
+
end
|
|
125
|
+
@config[:categories] = h
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def write_config
|
|
129
|
+
File.open(@config_filepath, "w") { |f| f.write @config.to_yaml }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private
|
|
133
|
+
|
|
134
|
+
def read_config
|
|
135
|
+
#noinspection RubyResolve
|
|
136
|
+
@config = YAML.load(File.open(@config_filepath))
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end # class
|
|
140
|
+
|
|
141
|
+
end # module SimpleCatalog
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module SimpleCataloger
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Find directory without subdirectories
|
|
5
|
+
#
|
|
6
|
+
class DirectoryVisitor
|
|
7
|
+
|
|
8
|
+
def initialize(catalog_root)
|
|
9
|
+
super
|
|
10
|
+
@stack = []
|
|
11
|
+
@files = []
|
|
12
|
+
@nr = 0
|
|
13
|
+
@catalog_root = catalog_root
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def enter_node(pathname)
|
|
17
|
+
# each directory is associated to a number,
|
|
18
|
+
# so when exit_tree_node is called and the number @nr is not increased
|
|
19
|
+
# the directory doesn't have subdirectories
|
|
20
|
+
@nr += 1
|
|
21
|
+
|
|
22
|
+
dirname = File.basename(pathname)
|
|
23
|
+
tags = Tag.extract_tags(dirname)
|
|
24
|
+
tags = tags.concat(@stack.last.tags).uniq unless @stack.empty?
|
|
25
|
+
info = OpenStruct.new(:nr => @nr, :pathname => pathname, :tags => tags, :name => Tag.extract_name(dirname))
|
|
26
|
+
|
|
27
|
+
@files = []
|
|
28
|
+
@stack.push(info)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def exit_node(pathname)
|
|
32
|
+
info = @stack.pop
|
|
33
|
+
|
|
34
|
+
if info.nr == @nr
|
|
35
|
+
# this directory doesn't have subdirectories
|
|
36
|
+
name = info.name
|
|
37
|
+
tag_names = info.tags
|
|
38
|
+
puts name
|
|
39
|
+
# pp tags
|
|
40
|
+
|
|
41
|
+
# every name must be unique, two films cannot have the some name
|
|
42
|
+
if Item.first( :name => name )
|
|
43
|
+
raise "item #{name} is not unique path #{pathname}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
item = Item.create(
|
|
47
|
+
:name => name,
|
|
48
|
+
:added_at => File.lstat(pathname).ctime,
|
|
49
|
+
:path => pathname,
|
|
50
|
+
:path_from_catalog_root => pathname[File.dirname(@catalog_root).length..-1]
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# Associate item and tags
|
|
55
|
+
#
|
|
56
|
+
unknown = Category.first_or_create(:name => "unknown")
|
|
57
|
+
tag_names.each do |tag_name|
|
|
58
|
+
tag = Tag.first(:name => tag_name)
|
|
59
|
+
unless tag
|
|
60
|
+
tag = Tag.match_category(tag_name)
|
|
61
|
+
unless tag
|
|
62
|
+
tag = Tag.first_or_create(
|
|
63
|
+
:name => tag_name,
|
|
64
|
+
:category => unknown
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
Tagging.first_or_create(:item=>item, :tag=> tag)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Searches images
|
|
73
|
+
#
|
|
74
|
+
@files.each do |pathname|
|
|
75
|
+
next unless pathname.match /(jpg|jpeg)$/
|
|
76
|
+
|
|
77
|
+
image = Image.first_or_create(
|
|
78
|
+
:path => pathname,
|
|
79
|
+
:path_from_catalog_root => pathname[File.dirname(@catalog_root).length..-1]
|
|
80
|
+
)
|
|
81
|
+
item.images << image
|
|
82
|
+
|
|
83
|
+
filename = File.basename(pathname)
|
|
84
|
+
tag_names = Tag.extract_tags(filename)
|
|
85
|
+
tag_names.each do |tag_name|
|
|
86
|
+
tag = Tag.first(:name => tag_name)
|
|
87
|
+
if tag
|
|
88
|
+
tag.images << image
|
|
89
|
+
tag.save
|
|
90
|
+
else
|
|
91
|
+
puts "WARNING: tag '#{tag_name}' not found"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
item.save
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
#
|
|
101
|
+
# called when visit leaf node
|
|
102
|
+
#
|
|
103
|
+
def visit_leaf(pathname)
|
|
104
|
+
@files << pathname
|
|
105
|
+
end
|
|
106
|
+
end # class
|
|
107
|
+
end # module SimpleCataloger
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
module CoreExtensions
|
|
4
|
+
module Array
|
|
5
|
+
def extract_options!
|
|
6
|
+
last.is_a?(::Hash) ? pop : {}
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class Array
|
|
13
|
+
include SimpleCataloger::CoreExtensions::Array
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module URI
|
|
17
|
+
class << self
|
|
18
|
+
|
|
19
|
+
def parse_with_safety(uri)
|
|
20
|
+
parse_without_safety uri.gsub('[', '%5B').gsub(']', '%5D')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# alias parse_without_safety parse
|
|
24
|
+
# alias parse parse_with_safety
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Category
|
|
5
|
+
include DataMapper::Resource
|
|
6
|
+
|
|
7
|
+
property :id, Serial
|
|
8
|
+
property :name, String
|
|
9
|
+
|
|
10
|
+
has n, :tags, :order => [:name]
|
|
11
|
+
|
|
12
|
+
def self.order_by_name
|
|
13
|
+
all(:order => [:name])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def items
|
|
17
|
+
tags.collect { |t| t.items }.flatten
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Image
|
|
5
|
+
include DataMapper::Resource
|
|
6
|
+
|
|
7
|
+
property :id, Serial
|
|
8
|
+
property :path, String
|
|
9
|
+
property :path_from_catalog_root, String
|
|
10
|
+
|
|
11
|
+
belongs_to :item, :required => false
|
|
12
|
+
belongs_to :tag, :required => false
|
|
13
|
+
|
|
14
|
+
def to_json(*a)
|
|
15
|
+
{:item => if item then
|
|
16
|
+
item.name
|
|
17
|
+
else
|
|
18
|
+
nil
|
|
19
|
+
end,
|
|
20
|
+
:tag => if tag then
|
|
21
|
+
tag.name
|
|
22
|
+
else
|
|
23
|
+
nil
|
|
24
|
+
end,
|
|
25
|
+
:src => path_from_catalog_root}.to_json(*a)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Item
|
|
5
|
+
include DataMapper::Resource
|
|
6
|
+
property :id, Serial
|
|
7
|
+
property :name, String
|
|
8
|
+
|
|
9
|
+
property :added_at, Date
|
|
10
|
+
property :path, String
|
|
11
|
+
property :path_from_catalog_root, String
|
|
12
|
+
property :rating, Integer
|
|
13
|
+
property :flagged_at, Date
|
|
14
|
+
|
|
15
|
+
has n, :taggings
|
|
16
|
+
has n, :tags, :through => :taggings
|
|
17
|
+
has n, :images
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
@name
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module SimpleCataloger
|
|
3
|
+
|
|
4
|
+
class Tag
|
|
5
|
+
include DataMapper::Resource
|
|
6
|
+
|
|
7
|
+
property :id, Serial
|
|
8
|
+
property :name, String
|
|
9
|
+
|
|
10
|
+
belongs_to :category, 'Category', :child_key => [:category_id]
|
|
11
|
+
has n, :taggings
|
|
12
|
+
has n, :items, :through => :taggings, :order => [:name]
|
|
13
|
+
has n, :images
|
|
14
|
+
|
|
15
|
+
##################################################
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
RE_TAG = /\[([^\]]+)\]/
|
|
19
|
+
|
|
20
|
+
# extracts tags from directory or file name
|
|
21
|
+
def self.extract_tags(dir_or_file_name)
|
|
22
|
+
tags = []
|
|
23
|
+
match_data = dir_or_file_name.match(RE_TAG)
|
|
24
|
+
while match_data
|
|
25
|
+
tags << match_data[1]
|
|
26
|
+
match_data = dir_or_file_name.match(RE_TAG, match_data.end(0))
|
|
27
|
+
end
|
|
28
|
+
tags
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.extract_name(dir_or_file_name)
|
|
32
|
+
dir_or_file_name.gsub(Tag::RE_TAG, '').strip
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
RE_RATING = /^\d$/
|
|
36
|
+
RE_YEAR = /^\d\d\d\d$/
|
|
37
|
+
|
|
38
|
+
MATCHES = [
|
|
39
|
+
[RE_RATING, "rating", proc { |tag_name| tag_name.to_i }],
|
|
40
|
+
[RE_YEAR, "year", proc { |tag_name| tag_name.to_i }]
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# decode standard tags
|
|
45
|
+
#
|
|
46
|
+
def self.match_category(tag_name)
|
|
47
|
+
MATCHES.each do |re, category_name, convert|
|
|
48
|
+
if re.match tag_name
|
|
49
|
+
category = Category.first_or_create(:name => category_name)
|
|
50
|
+
tag = Tag.first_or_create(
|
|
51
|
+
:name => convert.call(tag_name),
|
|
52
|
+
:category => category
|
|
53
|
+
)
|
|
54
|
+
return tag
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end # class Tag
|
|
61
|
+
|
|
62
|
+
end # module SimpleCatalog
|