Class: Cacofonix::Element
- Inherits:
-
Object
- Object
- Cacofonix::Element
- Extended by:
- Dry::Core::ClassAttributes
- Includes:
- ROXML
- Defined in:
- lib/cacofonix/core/element.rb
Direct Known Subclasses
AgentIdentifier, Audience, AudienceRange, BatchBonus, Bible, Complexity, Conference, ConferenceSponsor, ContentItem, CopyrightOwner, CopyrightStatement, DiscountCoded, Extent, Identifier, Illustrations, Imprint, Language, MainSubject, MarketDate, MarketRepresentation, Measure, MediaFile, NameBase, NewSupplier, NotForSale, OnOrderDetail, OtherText, PageRun, PersonDate, Price, Prize, ProductBase, ProductClassification, ProductFormFeature, ProfessionalAffiliation, Publisher, Reissue, ReligiousText, ReligiousTextFeature, SalesOutlet, SalesRestriction, SalesRights, Series, Set, Stock, StockQuantityCoded, Subject, SupplyDetail, TextItem, Title, Website
Class Method Summary collapse
- .alias_accessor(new_accessor, old_accessor) ⇒ Object
-
.onix_boolean_flag(name, tag_name, options = {}) ⇒ Object
An accessor that treats an empty string as a true value – so that something like <NoContributor /> is recognised as “there is no contributor”.
-
.onix_code_from_list(name, tag_name, options = {}) ⇒ Object
An accessor that maps a “code” string into an Cacofonix::Code object.
-
.onix_codes_from_list(name, tag_name, options = {}, &blk) ⇒ Object
Like onix_code_from_list, but for an array of codes.
-
.onix_composite(name, klass, options = {}) ⇒ Object
An accessor to an array of element instances.
-
.onix_date_accessor(name, tag_name, options = {}) ⇒ Object
An accessor that treats the input/output as a date.
-
.onix_space_separated_list(name, tag_name, options = {}) ⇒ Object
An accessor that treats the input as a space-separated list, and creates an array for it.
-
.onix_spaced_codes_from_list(name, tag_name, options) ⇒ Object
Sugar for a common case – country or territory codes.
- .xml_accessor(attr, *args, **options) ⇒ Object
Instance Method Summary collapse
-
#fetch(composite_symbol, mthd, query) ⇒ Object
Query a composite array within this element, looking for an attribute (‘mthd’) that has a value equal to ‘query’.
-
#fetch_all(composite_symbol, mthd, query) ⇒ Object
Queries a composite array like #fetch, but returns all composites that have a match.
-
#initialize ⇒ Element
constructor
A new instance of Element.
Constructor Details
#initialize ⇒ Element
Returns a new instance of Element.
259 260 261 262 263 264 265 266 267 |
# File 'lib/cacofonix/core/element.rb', line 259 def initialize(*) if self.class.xml_array_accessors self.class.xml_array_accessors.each do |attr| send :"#{attr}=", [] end end super end |
Class Method Details
.alias_accessor(new_accessor, old_accessor) ⇒ Object
244 245 246 247 |
# File 'lib/cacofonix/core/element.rb', line 244 def self.alias_accessor(new_accessor, old_accessor) alias_method(new_accessor, old_accessor) alias_method("#{new_accessor}=", "#{old_accessor}=") end |
.onix_boolean_flag(name, tag_name, options = {}) ⇒ Object
An accessor that treats an empty string as a true value – so that something like <NoContributor /> is recognised as “there is no contributor”.
60 61 62 63 64 65 66 67 |
# File 'lib/cacofonix/core/element.rb', line 60 def self.onix_boolean_flag(name, tag_name, = {}) = .merge( :from => tag_name, :to_xml => Cacofonix::Formatters.boolean ) prep = lambda { |v| v ? true : false } xml_accessor(name, **, &prep) end |
.onix_code_from_list(name, tag_name, options = {}) ⇒ Object
An accessor that maps a “code” string into an Cacofonix::Code object. A Code object can return the simple code (or “key”), or the value that is associated with it in ONIX code lists, and so on.
Required:
:list - integer referring to an ONIX Code List
Special options for Code instantiation are:
:length - how many digits to pad (default is taken from total list size)
As well as the normal accessor (x/x=), this will create a special accessor for the richer Code object (#x_code/#x_code=). For example:
class Foo < Cacofonix::Element
onix_code_from_list(:message_type, "MessageType", :list => 1)
end
foo = Foo.new
foo.message_type = 1
foo.message_type
>> 1
foo.message_type_code
>> #<Cacofonix::Code:.......>
foo.message_type_code.key
>> 1
foo.message_type_code.to_s
>> "01"
foo.message_type_code.value
>> "Early notification"
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/cacofonix/core/element.rb', line 110 def self.onix_code_from_list(name, tag_name, = {}) unless list_number = .delete(:list) raise Cacofonix::CodeListNotSpecified end code_opts = .slice(:length, :enforce) .delete(:enforce) prep = lambda { |value| Cacofonix::Code.new(list_number, value, code_opts) } = .merge(:from => tag_name) xml_accessor("#{name}_code", **, &prep) define_method(name) do send("#{name}_code").key end define_method("#{name}=") do |val| val = prep.call(val) unless val.kind_of?(Cacofonix::Code) send("#{name}_code=", val) end end |
.onix_codes_from_list(name, tag_name, options = {}, &blk) ⇒ Object
Like onix_code_from_list, but for an array of codes.
Required:
:list - integer referring to an ONIX Code List
One important caveat: when assigning to this accessor, you must pass in the complete array – if you assign an array that you later push or shift items into, you might get unexpected results.
Similar to onix_code_from_list, this creates a special accessor for the Code objects at (#x_codes/#x_codes=). For example:
class Bar < Cacofonix::Element
onix_codes_from_list(:identifiers, "Identifier", :list => 5)
end
bar = Bar.new
bar.identifiers = [1, 5, 13]
bar.identifiers_codes.collect { |ids| ids.value }
>> ["Proprietary", "ISMN-10", "LLCN"]
If a block is given, each value is passed into it first - return an array of the actual values.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/cacofonix/core/element.rb', line 159 def self.onix_codes_from_list(name, tag_name, = {}, &blk) unless list_number = .delete(:list) raise Cacofonix::CodeListNotSpecified end code_opts = .slice(:length, :enforce) .delete(:enforce) prep = lambda { |values| if block_given? values = [values].flatten.collect { |v| blk.call(v) } end [values].flatten.collect do |data| Cacofonix::Code.new(list_number, data, code_opts) end } = .merge(:from => tag_name, :as => []) xml_accessor("#{name}_codes", **, &prep) define_method(name) do codes = send("#{name}_codes") codes ? codes.collect { |cd| cd.key } : nil end # FIXME: Hmm, adding to array? what happens with push, etc? define_method("#{name}=") do |vals| vals = [vals].flatten.collect { |v| v.kind_of?(Cacofonix::Code) ? v : prep.call(v) }.flatten send("#{name}_codes=", vals) end end |
.onix_composite(name, klass, options = {}) ⇒ Object
An accessor to an array of element instances.
Options:
:from - defaults to the class name, but you can override this.
:singular - accessor is not an array, just a single object.
18 19 20 21 22 |
# File 'lib/cacofonix/core/element.rb', line 18 def self.onix_composite(name, klass, = {}) [:as] = .delete(:singular) ? klass : [klass] [:from] ||= klass.to_s.split("::").last xml_accessor(name, **) end |
.onix_date_accessor(name, tag_name, options = {}) ⇒ Object
An accessor that treats the input/output as a date.
Options: none yet.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/cacofonix/core/element.rb', line 28 def self.onix_date_accessor(name, tag_name, = {}) = .merge( :from => tag_name, :to_xml => Cacofonix::Formatters.yyyymmdd ) if [:as].kind_of?(Array) prep = lambda { |vs| [vs].flatten.collect { |v| Date.parse(v) rescue nil } } else prep = lambda { |v| Date.parse(v) rescue nil } end xml_accessor(name, **, &prep) end |
.onix_space_separated_list(name, tag_name, options = {}) ⇒ Object
An accessor that treats the input as a space-separated list, and creates an array for it.
46 47 48 49 50 51 52 53 |
# File 'lib/cacofonix/core/element.rb', line 46 def self.onix_space_separated_list(name, tag_name, = {}) = .merge( :from => tag_name, :to_xml => Cacofonix::Formatters.space_separated ) prep = lambda { |v| v ? v.split : [] } xml_accessor(name, **, &prep) end |
.onix_spaced_codes_from_list(name, tag_name, options) ⇒ Object
Sugar for a common case – country or territory codes.
193 194 195 196 |
# File 'lib/cacofonix/core/element.rb', line 193 def self.onix_spaced_codes_from_list(name, tag_name, ) [:to_xml] ||= Cacofonix::Formatters.space_separated onix_codes_from_list(name, tag_name, ) { |v| v ? v.split : [] } end |
.xml_accessor(attr, *args, **options) ⇒ Object
250 251 252 253 254 255 256 |
# File 'lib/cacofonix/core/element.rb', line 250 def self.xml_accessor(attr, *args, **) if [:as] && [:as].kind_of?(Array) xml_array_accessors(Array(xml_array_accessors) + [attr]) end super end |
Instance Method Details
#fetch(composite_symbol, mthd, query) ⇒ Object
Query a composite array within this element, looking for an attribute (‘mthd’) that has a value equal to ‘query’.
The idea is that you can shorten this:
product.websites.detect { |ws| ws.website_role == 1 }
To this:
product.fetch(:websites, :website_role, 1)
Note: query may be an array of values, will return the first composite that matches one of them. So this:
product.websites.detect { |ws| ws.website_role == 1 } ||
product.websites.detect { |ws| ws.website_role == 2 }
becomes this:
product.fetch(:websites, :website_role, [1, 2])
220 221 222 223 224 225 226 227 228 |
# File 'lib/cacofonix/core/element.rb', line 220 def fetch(composite_symbol, mthd, query) result = nil [query].flatten.each do |matcher| break if result = send(composite_symbol).detect do |comp| comp.send(mthd) == matcher end end result end |
#fetch_all(composite_symbol, mthd, query) ⇒ Object
Queries a composite array like #fetch, but returns all composites that have a match.
233 234 235 236 237 238 239 240 241 |
# File 'lib/cacofonix/core/element.rb', line 233 def fetch_all(composite_symbol, mthd, query) [query].flatten.inject([]) do |acc, matcher| comps = send(composite_symbol).select do |comp| comp.send(mthd) == matcher end acc += comps if comps.any? acc end end |