rubysl-rss 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rss.rb +1 -0
- data/lib/rss/0.9.rb +428 -0
- data/lib/rss/1.0.rb +452 -0
- data/lib/rss/2.0.rb +111 -0
- data/lib/rss/atom.rb +749 -0
- data/lib/rss/content.rb +31 -0
- data/lib/rss/content/1.0.rb +10 -0
- data/lib/rss/content/2.0.rb +12 -0
- data/lib/rss/converter.rb +162 -0
- data/lib/rss/dublincore.rb +161 -0
- data/lib/rss/dublincore/1.0.rb +13 -0
- data/lib/rss/dublincore/2.0.rb +13 -0
- data/lib/rss/dublincore/atom.rb +17 -0
- data/lib/rss/image.rb +193 -0
- data/lib/rss/itunes.rb +410 -0
- data/lib/rss/maker.rb +44 -0
- data/lib/rss/maker/0.9.rb +467 -0
- data/lib/rss/maker/1.0.rb +434 -0
- data/lib/rss/maker/2.0.rb +223 -0
- data/lib/rss/maker/atom.rb +172 -0
- data/lib/rss/maker/base.rb +868 -0
- data/lib/rss/maker/content.rb +21 -0
- data/lib/rss/maker/dublincore.rb +124 -0
- data/lib/rss/maker/entry.rb +163 -0
- data/lib/rss/maker/feed.rb +429 -0
- data/lib/rss/maker/image.rb +111 -0
- data/lib/rss/maker/itunes.rb +242 -0
- data/lib/rss/maker/slash.rb +33 -0
- data/lib/rss/maker/syndication.rb +18 -0
- data/lib/rss/maker/taxonomy.rb +118 -0
- data/lib/rss/maker/trackback.rb +61 -0
- data/lib/rss/parser.rb +541 -0
- data/lib/rss/rexmlparser.rb +54 -0
- data/lib/rss/rss.rb +1312 -0
- data/lib/rss/slash.rb +49 -0
- data/lib/rss/syndication.rb +67 -0
- data/lib/rss/taxonomy.rb +145 -0
- data/lib/rss/trackback.rb +288 -0
- data/lib/rss/utils.rb +111 -0
- data/lib/rss/xml-stylesheet.rb +105 -0
- data/lib/rss/xml.rb +71 -0
- data/lib/rss/xmlparser.rb +93 -0
- data/lib/rss/xmlscanner.rb +121 -0
- data/lib/rubysl/rss.rb +2 -0
- data/lib/rubysl/rss/rss.rb +19 -0
- data/lib/rubysl/rss/version.rb +5 -0
- data/rubysl-rss.gemspec +23 -0
- metadata +153 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rss/image'
|
2
|
+
require 'rss/maker/1.0'
|
3
|
+
require 'rss/maker/dublincore'
|
4
|
+
|
5
|
+
module RSS
|
6
|
+
module Maker
|
7
|
+
module ImageItemModel
|
8
|
+
def self.append_features(klass)
|
9
|
+
super
|
10
|
+
|
11
|
+
name = "#{RSS::IMAGE_PREFIX}_item"
|
12
|
+
klass.def_classed_element(name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.install_image_item(klass)
|
16
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
17
|
+
class ImageItem < ImageItemBase
|
18
|
+
DublinCoreModel.install_dublin_core(self)
|
19
|
+
end
|
20
|
+
EOC
|
21
|
+
end
|
22
|
+
|
23
|
+
class ImageItemBase < Base
|
24
|
+
include Maker::DublinCoreModel
|
25
|
+
|
26
|
+
attr_accessor :about, :resource, :image_width, :image_height
|
27
|
+
add_need_initialize_variable("about")
|
28
|
+
add_need_initialize_variable("resource")
|
29
|
+
add_need_initialize_variable("image_width")
|
30
|
+
add_need_initialize_variable("image_height")
|
31
|
+
alias width= image_width=
|
32
|
+
alias width image_width
|
33
|
+
alias height= image_height=
|
34
|
+
alias height image_height
|
35
|
+
|
36
|
+
def have_required_values?
|
37
|
+
@about
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_feed(feed, current)
|
41
|
+
if current.respond_to?(:image_item=) and have_required_values?
|
42
|
+
item = current.class::ImageItem.new
|
43
|
+
setup_values(item)
|
44
|
+
setup_other_elements(item)
|
45
|
+
current.image_item = item
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module ImageFaviconModel
|
52
|
+
def self.append_features(klass)
|
53
|
+
super
|
54
|
+
|
55
|
+
name = "#{RSS::IMAGE_PREFIX}_favicon"
|
56
|
+
klass.def_classed_element(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.install_image_favicon(klass)
|
60
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
61
|
+
class ImageFavicon < ImageFaviconBase
|
62
|
+
DublinCoreModel.install_dublin_core(self)
|
63
|
+
end
|
64
|
+
EOC
|
65
|
+
end
|
66
|
+
|
67
|
+
class ImageFaviconBase < Base
|
68
|
+
include Maker::DublinCoreModel
|
69
|
+
|
70
|
+
attr_accessor :about, :image_size
|
71
|
+
add_need_initialize_variable("about")
|
72
|
+
add_need_initialize_variable("image_size")
|
73
|
+
alias size image_size
|
74
|
+
alias size= image_size=
|
75
|
+
|
76
|
+
def have_required_values?
|
77
|
+
@about and @image_size
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_feed(feed, current)
|
81
|
+
if current.respond_to?(:image_favicon=) and have_required_values?
|
82
|
+
favicon = current.class::ImageFavicon.new
|
83
|
+
setup_values(favicon)
|
84
|
+
setup_other_elements(favicon)
|
85
|
+
current.image_favicon = favicon
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class ChannelBase; include Maker::ImageFaviconModel; end
|
92
|
+
|
93
|
+
class ItemsBase
|
94
|
+
class ItemBase; include Maker::ImageItemModel; end
|
95
|
+
end
|
96
|
+
|
97
|
+
makers.each do |maker|
|
98
|
+
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
99
|
+
class Channel
|
100
|
+
ImageFaviconModel.install_image_favicon(self)
|
101
|
+
end
|
102
|
+
|
103
|
+
class Items
|
104
|
+
class Item
|
105
|
+
ImageItemModel.install_image_item(self)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
EOC
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'rss/itunes'
|
2
|
+
require 'rss/maker/2.0'
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
module Maker
|
6
|
+
module ITunesBaseModel
|
7
|
+
def def_class_accessor(klass, name, type, *args)
|
8
|
+
name = name.gsub(/-/, "_").gsub(/^itunes_/, '')
|
9
|
+
full_name = "#{RSS::ITUNES_PREFIX}_#{name}"
|
10
|
+
case type
|
11
|
+
when nil
|
12
|
+
klass.def_other_element(full_name)
|
13
|
+
when :yes_other
|
14
|
+
def_yes_other_accessor(klass, full_name)
|
15
|
+
when :yes_clean_other
|
16
|
+
def_yes_clean_other_accessor(klass, full_name)
|
17
|
+
when :csv
|
18
|
+
def_csv_accessor(klass, full_name)
|
19
|
+
when :element, :attribute
|
20
|
+
recommended_attribute_name, = *args
|
21
|
+
klass_name = "ITunes#{Utils.to_class_name(name)}"
|
22
|
+
klass.def_classed_element(full_name, klass_name,
|
23
|
+
recommended_attribute_name)
|
24
|
+
when :elements
|
25
|
+
plural_name, recommended_attribute_name = args
|
26
|
+
plural_name ||= "#{name}s"
|
27
|
+
full_plural_name = "#{RSS::ITUNES_PREFIX}_#{plural_name}"
|
28
|
+
klass_name = "ITunes#{Utils.to_class_name(name)}"
|
29
|
+
plural_klass_name = "ITunes#{Utils.to_class_name(plural_name)}"
|
30
|
+
def_elements_class_accessor(klass, name, full_name, full_plural_name,
|
31
|
+
klass_name, plural_klass_name,
|
32
|
+
recommended_attribute_name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def def_yes_other_accessor(klass, full_name)
|
37
|
+
klass.def_other_element(full_name)
|
38
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
39
|
+
def #{full_name}?
|
40
|
+
Utils::YesOther.parse(@#{full_name})
|
41
|
+
end
|
42
|
+
EOC
|
43
|
+
end
|
44
|
+
|
45
|
+
def def_yes_clean_other_accessor(klass, full_name)
|
46
|
+
klass.def_other_element(full_name)
|
47
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
48
|
+
def #{full_name}?
|
49
|
+
Utils::YesCleanOther.parse(#{full_name})
|
50
|
+
end
|
51
|
+
EOC
|
52
|
+
end
|
53
|
+
|
54
|
+
def def_csv_accessor(klass, full_name)
|
55
|
+
klass.def_csv_element(full_name)
|
56
|
+
end
|
57
|
+
|
58
|
+
def def_elements_class_accessor(klass, name, full_name, full_plural_name,
|
59
|
+
klass_name, plural_klass_name,
|
60
|
+
recommended_attribute_name=nil)
|
61
|
+
if recommended_attribute_name
|
62
|
+
klass.def_classed_elements(full_name, recommended_attribute_name,
|
63
|
+
plural_klass_name, full_plural_name)
|
64
|
+
else
|
65
|
+
klass.def_classed_element(full_plural_name, plural_klass_name)
|
66
|
+
end
|
67
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
68
|
+
def new_#{full_name}(text=nil)
|
69
|
+
#{full_name} = @#{full_plural_name}.new_#{name}
|
70
|
+
#{full_name}.text = text
|
71
|
+
if block_given?
|
72
|
+
yield #{full_name}
|
73
|
+
else
|
74
|
+
#{full_name}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
EOC
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
module ITunesChannelModel
|
82
|
+
extend ITunesBaseModel
|
83
|
+
|
84
|
+
class << self
|
85
|
+
def append_features(klass)
|
86
|
+
super
|
87
|
+
|
88
|
+
::RSS::ITunesChannelModel::ELEMENT_INFOS.each do |name, type, *args|
|
89
|
+
def_class_accessor(klass, name, type, *args)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class ITunesCategoriesBase < Base
|
95
|
+
def_array_element("category", "itunes_categories",
|
96
|
+
"ITunesCategory")
|
97
|
+
class ITunesCategoryBase < Base
|
98
|
+
attr_accessor :text
|
99
|
+
add_need_initialize_variable("text")
|
100
|
+
def_array_element("category", "itunes_categories",
|
101
|
+
"ITunesCategory")
|
102
|
+
|
103
|
+
def have_required_values?
|
104
|
+
text
|
105
|
+
end
|
106
|
+
|
107
|
+
alias_method :to_feed_for_categories, :to_feed
|
108
|
+
def to_feed(feed, current)
|
109
|
+
if text and current.respond_to?(:itunes_category)
|
110
|
+
new_item = current.class::ITunesCategory.new(text)
|
111
|
+
to_feed_for_categories(feed, new_item)
|
112
|
+
current.itunes_categories << new_item
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
class ITunesImageBase < Base
|
119
|
+
add_need_initialize_variable("href")
|
120
|
+
attr_accessor("href")
|
121
|
+
|
122
|
+
def to_feed(feed, current)
|
123
|
+
if @href and current.respond_to?(:itunes_image)
|
124
|
+
current.itunes_image ||= current.class::ITunesImage.new
|
125
|
+
current.itunes_image.href = @href
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
class ITunesOwnerBase < Base
|
131
|
+
%w(itunes_name itunes_email).each do |name|
|
132
|
+
add_need_initialize_variable(name)
|
133
|
+
attr_accessor(name)
|
134
|
+
end
|
135
|
+
|
136
|
+
def to_feed(feed, current)
|
137
|
+
if current.respond_to?(:itunes_owner=)
|
138
|
+
_not_set_required_variables = not_set_required_variables
|
139
|
+
if (required_variable_names - _not_set_required_variables).empty?
|
140
|
+
return
|
141
|
+
end
|
142
|
+
|
143
|
+
unless have_required_values?
|
144
|
+
raise NotSetError.new("maker.channel.itunes_owner",
|
145
|
+
_not_set_required_variables)
|
146
|
+
end
|
147
|
+
current.itunes_owner ||= current.class::ITunesOwner.new
|
148
|
+
current.itunes_owner.itunes_name = @itunes_name
|
149
|
+
current.itunes_owner.itunes_email = @itunes_email
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
def required_variable_names
|
155
|
+
%w(itunes_name itunes_email)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module ITunesItemModel
|
161
|
+
extend ITunesBaseModel
|
162
|
+
|
163
|
+
class << self
|
164
|
+
def append_features(klass)
|
165
|
+
super
|
166
|
+
|
167
|
+
::RSS::ITunesItemModel::ELEMENT_INFOS.each do |name, type, *args|
|
168
|
+
def_class_accessor(klass, name, type, *args)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class ITunesDurationBase < Base
|
174
|
+
attr_reader :content
|
175
|
+
add_need_initialize_variable("content")
|
176
|
+
|
177
|
+
%w(hour minute second).each do |name|
|
178
|
+
attr_reader(name)
|
179
|
+
add_need_initialize_variable(name, '0')
|
180
|
+
end
|
181
|
+
|
182
|
+
def content=(content)
|
183
|
+
if content.nil?
|
184
|
+
@hour, @minute, @second, @content = nil
|
185
|
+
else
|
186
|
+
@hour, @minute, @second =
|
187
|
+
::RSS::ITunesItemModel::ITunesDuration.parse(content)
|
188
|
+
@content = content
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def hour=(hour)
|
193
|
+
@hour = Integer(hour)
|
194
|
+
update_content
|
195
|
+
end
|
196
|
+
|
197
|
+
def minute=(minute)
|
198
|
+
@minute = Integer(minute)
|
199
|
+
update_content
|
200
|
+
end
|
201
|
+
|
202
|
+
def second=(second)
|
203
|
+
@second = Integer(second)
|
204
|
+
update_content
|
205
|
+
end
|
206
|
+
|
207
|
+
def to_feed(feed, current)
|
208
|
+
if @content and current.respond_to?(:itunes_duration=)
|
209
|
+
current.itunes_duration ||= current.class::ITunesDuration.new
|
210
|
+
current.itunes_duration.content = @content
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
def update_content
|
216
|
+
components = [@hour, @minute, @second]
|
217
|
+
@content =
|
218
|
+
::RSS::ITunesItemModel::ITunesDuration.construct(*components)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class ChannelBase
|
224
|
+
include Maker::ITunesChannelModel
|
225
|
+
class ITunesCategories < ITunesCategoriesBase
|
226
|
+
class ITunesCategory < ITunesCategoryBase
|
227
|
+
ITunesCategory = self
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
class ITunesImage < ITunesImageBase; end
|
232
|
+
class ITunesOwner < ITunesOwnerBase; end
|
233
|
+
end
|
234
|
+
|
235
|
+
class ItemsBase
|
236
|
+
class ItemBase
|
237
|
+
include Maker::ITunesItemModel
|
238
|
+
class ITunesDuration < ITunesDurationBase; end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rss/slash'
|
2
|
+
require 'rss/maker/1.0'
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
module Maker
|
6
|
+
module SlashModel
|
7
|
+
def self.append_features(klass)
|
8
|
+
super
|
9
|
+
|
10
|
+
::RSS::SlashModel::ELEMENT_INFOS.each do |name, type|
|
11
|
+
full_name = "#{RSS::SLASH_PREFIX}_#{name}"
|
12
|
+
case type
|
13
|
+
when :csv_integer
|
14
|
+
klass.def_csv_element(full_name, :integer)
|
15
|
+
else
|
16
|
+
klass.def_other_element(full_name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
klass.module_eval do
|
21
|
+
alias_method(:slash_hit_parades, :slash_hit_parade)
|
22
|
+
alias_method(:slash_hit_parades=, :slash_hit_parade=)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class ItemsBase
|
28
|
+
class ItemBase
|
29
|
+
include SlashModel
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rss/syndication'
|
2
|
+
require 'rss/maker/1.0'
|
3
|
+
|
4
|
+
module RSS
|
5
|
+
module Maker
|
6
|
+
module SyndicationModel
|
7
|
+
def self.append_features(klass)
|
8
|
+
super
|
9
|
+
|
10
|
+
::RSS::SyndicationModel::ELEMENTS.each do |name|
|
11
|
+
klass.def_other_element(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ChannelBase; include SyndicationModel; end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rss/taxonomy'
|
2
|
+
require 'rss/maker/1.0'
|
3
|
+
require 'rss/maker/dublincore'
|
4
|
+
|
5
|
+
module RSS
|
6
|
+
module Maker
|
7
|
+
module TaxonomyTopicsModel
|
8
|
+
def self.append_features(klass)
|
9
|
+
super
|
10
|
+
|
11
|
+
klass.def_classed_element("#{RSS::TAXO_PREFIX}_topics",
|
12
|
+
"TaxonomyTopics")
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.install_taxo_topics(klass)
|
16
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
17
|
+
class TaxonomyTopics < TaxonomyTopicsBase
|
18
|
+
def to_feed(feed, current)
|
19
|
+
if current.respond_to?(:taxo_topics)
|
20
|
+
topics = current.class::TaxonomyTopics.new
|
21
|
+
bag = topics.Bag
|
22
|
+
@resources.each do |resource|
|
23
|
+
bag.lis << RDF::Bag::Li.new(resource)
|
24
|
+
end
|
25
|
+
current.taxo_topics = topics
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
EOC
|
30
|
+
end
|
31
|
+
|
32
|
+
class TaxonomyTopicsBase < Base
|
33
|
+
attr_reader :resources
|
34
|
+
def_array_element("resource")
|
35
|
+
remove_method :new_resource
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module TaxonomyTopicModel
|
40
|
+
def self.append_features(klass)
|
41
|
+
super
|
42
|
+
|
43
|
+
class_name = "TaxonomyTopics"
|
44
|
+
klass.def_classed_elements("#{TAXO_PREFIX}_topic", "value", class_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.install_taxo_topic(klass)
|
48
|
+
klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
49
|
+
class TaxonomyTopics < TaxonomyTopicsBase
|
50
|
+
class TaxonomyTopic < TaxonomyTopicBase
|
51
|
+
DublinCoreModel.install_dublin_core(self)
|
52
|
+
TaxonomyTopicsModel.install_taxo_topics(self)
|
53
|
+
|
54
|
+
def to_feed(feed, current)
|
55
|
+
if current.respond_to?(:taxo_topics)
|
56
|
+
topic = current.class::TaxonomyTopic.new(value)
|
57
|
+
topic.taxo_link = value
|
58
|
+
taxo_topics.to_feed(feed, topic) if taxo_topics
|
59
|
+
current.taxo_topics << topic
|
60
|
+
setup_other_elements(feed, topic)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
EOC
|
66
|
+
end
|
67
|
+
|
68
|
+
class TaxonomyTopicsBase < Base
|
69
|
+
def_array_element("topic", nil, "TaxonomyTopic")
|
70
|
+
alias_method(:new_taxo_topic, :new_topic) # For backward compatibility
|
71
|
+
|
72
|
+
class TaxonomyTopicBase < Base
|
73
|
+
include DublinCoreModel
|
74
|
+
include TaxonomyTopicsModel
|
75
|
+
|
76
|
+
attr_accessor :value
|
77
|
+
add_need_initialize_variable("value")
|
78
|
+
alias_method(:taxo_link, :value)
|
79
|
+
alias_method(:taxo_link=, :value=)
|
80
|
+
|
81
|
+
def have_required_values?
|
82
|
+
@value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class RSSBase
|
89
|
+
include TaxonomyTopicModel
|
90
|
+
end
|
91
|
+
|
92
|
+
class ChannelBase
|
93
|
+
include TaxonomyTopicsModel
|
94
|
+
end
|
95
|
+
|
96
|
+
class ItemsBase
|
97
|
+
class ItemBase
|
98
|
+
include TaxonomyTopicsModel
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
makers.each do |maker|
|
103
|
+
maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
|
104
|
+
TaxonomyTopicModel.install_taxo_topic(self)
|
105
|
+
|
106
|
+
class Channel
|
107
|
+
TaxonomyTopicsModel.install_taxo_topics(self)
|
108
|
+
end
|
109
|
+
|
110
|
+
class Items
|
111
|
+
class Item
|
112
|
+
TaxonomyTopicsModel.install_taxo_topics(self)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
EOC
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|