Class: Vcard::DirectoryInfo
- Inherits:
-
Object
- Object
- Vcard::DirectoryInfo
- Includes:
- Enumerable
- Defined in:
- lib/vcard/dirinfo.rb,
lib/vcard/field.rb
Overview
An RFC 2425 directory info object.
A directory information object is a sequence of fields. The basic structure of the object, and the way in which it is broken into fields is common to all profiles of the directory info type.
A vCard, for example, is a specialization of a directory info object.
- RFC2425
-
the directory information framework (ftp.ietf.org/rfc/rfc2425.txt)
Here’s an example of encoding a simple vCard using the low-level APIs:
card = Vcard::Vcard.create
card << Vcard::DirectoryInfo::Field.create("EMAIL", "[email protected]", "TYPE" => "INTERNET" )
card << Vcard::DirectoryInfo::Field.create("URL", "http://www.example.com/user" )
card << Vcard::DirectoryInfo::Field.create("FN", "User Name" )
puts card.to_s
Don’t do it like that, use Vcard::Vcard::Maker.
Direct Known Subclasses
Defined Under Namespace
Classes: Field
Class Method Summary collapse
-
.create(fields = [], profile = nil) ⇒ Object
Create a new DirectoryInfo object.
-
.decode(card) ⇒ Object
Decode
card
into a DirectoryInfo object.
Instance Method Summary collapse
-
#[](name) ⇒ Object
The value of the first field named
name
, or nil if no match is found. -
#check_begin_end(profile = nil) ⇒ Object
Check that the DirectoryInfo object is correctly delimited by a BEGIN and END, that their profile values match, and if
profile
is specified, that they are the specified profile. -
#delete(field) ⇒ Object
Delete
field
. -
#dirty ⇒ Object
Force card to be reencoded from the fields.
-
#each(cond = nil) ⇒ Object
Yields for each Field for which
cond
.call(field) is true. -
#encode(width = nil) ⇒ Object
(also: #to_s)
The string encoding of the DirectoryInfo.
-
#enum_by_cond(cond) ⇒ Object
Returns an Enumerator for each Field for which
cond
.call(field) is true. -
#enum_by_group(group) ⇒ Object
Returns an Enumerator for each Field for which #group?(
group
) is true. -
#enum_by_name(name) ⇒ Object
Returns an Enumerator for each Field for which #name?(
name
) is true. -
#field(name) ⇒ Object
The first field named
name
, or nil if no match is found. -
#fields ⇒ Object
All fields, frozen.
-
#groups ⇒ Object
Array of all the Field#group()s.
-
#initialize(fields, profile = nil) ⇒ DirectoryInfo
constructor
Initialize a DirectoryInfo object from
fields
. -
#push(field) ⇒ Object
(also: #<<)
Append
field
to the fields. -
#push_end(field) ⇒ Object
Append
field
to the end of all the fields. -
#push_unique(field) ⇒ Object
Push
field
onto the fields, unless there is already a field with this name. -
#text(name) ⇒ Object
An array of all the values of fields named
name
, converted to text (using Field#to_text()).
Constructor Details
#initialize(fields, profile = nil) ⇒ DirectoryInfo
Initialize a DirectoryInfo object from fields
. If profile
is specified, check the BEGIN/END fields.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/vcard/dirinfo.rb', line 33 def initialize(fields, profile = nil) #:nodoc: if fields.detect { |f| ! f.kind_of? DirectoryInfo::Field } raise ArgumentError, "fields must be an array of DirectoryInfo::Field objects" end @string = nil # this is used as a flag to indicate that recoding will be necessary @fields = fields check_begin_end(profile) if profile end |
Class Method Details
.create(fields = [], profile = nil) ⇒ Object
Create a new DirectoryInfo object. The fields
are an optional array of DirectoryInfo::Field objects to add to the new object, between the BEGIN/END. If the profile
string is not nil, then it is the name of the directory info profile, and the BEGIN:profile
/END:profile
fields will be added.
A DirectoryInfo is mutable, you can add new fields to it using #push(), and see Field#create().
80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/vcard/dirinfo.rb', line 80 def DirectoryInfo.create(fields = [], profile = nil) if profile p = profile.to_str f = [ Field.create("BEGIN", p) ] f.concat fields f.push Field.create("END", p) fields = f end new(fields, profile) end |
.decode(card) ⇒ Object
Decode card
into a DirectoryInfo object.
card
may either be a something that is convertible to a string using #to_str or an Array of objects that can be joined into a string using #join(“n”), or an IO object (which will be read to end-of-file).
The lines in the string may be delimited using IETF (CRLF) or Unix (LF) conventions.
A DirectoryInfo is mutable, you can add new fields to it, see Vcard::DirectoryInfo::Field#create() for how to create a new Field.
TODO: I don’t believe this is ever used, maybe I can remove it.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/vcard/dirinfo.rb', line 56 def DirectoryInfo.decode(card) #:nodoc: if card.respond_to? :to_str string = card.to_str elsif card.kind_of? Array string = card.join("\n") elsif card.kind_of? IO string = card.read(nil) else raise ArgumentError, "DirectoryInfo cannot be created from a #{card.type}" end fields = ::Vcard.decode(string) new(fields) end |
Instance Method Details
#[](name) ⇒ Object
The value of the first field named name
, or nil if no match is found.
102 103 104 105 106 |
# File 'lib/vcard/dirinfo.rb', line 102 def [](name) enum_by_name(name).each { |f| return f.value if f.value != ""} enum_by_name(name).each { |f| return f.value } nil end |
#check_begin_end(profile = nil) ⇒ Object
Check that the DirectoryInfo object is correctly delimited by a BEGIN and END, that their profile values match, and if profile
is specified, that they are the specified profile.
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/vcard/dirinfo.rb', line 247 def check_begin_end(profile=nil) #:nodoc: unless @fields.first raise "No fields to check" end unless @fields.first.name? "BEGIN" raise "Needs BEGIN, found: #{@fields.first.encode nil}" end unless @fields.last.name? "END" raise "Needs END, found: #{@fields.last.encode nil}" end unless @fields.last.value? @fields.first.value raise "BEGIN/END mismatch: (#{@fields.first.value} != #{@fields.last.value}" end if profile if ! @fields.first.value? profile raise "Mismatched profile" end end true end |
#delete(field) ⇒ Object
Delete field
.
Warning: You can’t delete BEGIN: or END: fields, but other profile-specific fields can be deleted, including mandatory ones. For vCards in particular, in order to avoid destroying them, I suggest creating a new Vcard, and copying over all the fields that you still want, rather than using #delete. This is easy with Vcard::Maker#copy, see the Vcard::Maker examples.
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/vcard/dirinfo.rb', line 222 def delete(field) case when field.name?("BEGIN"), field.name?("END") raise ArgumentError, "Cannot delete BEGIN or END fields." else @fields.delete field end self end |
#dirty ⇒ Object
Force card to be reencoded from the fields.
185 186 187 |
# File 'lib/vcard/dirinfo.rb', line 185 def dirty #:nodoc: #string = nil end |
#each(cond = nil) ⇒ Object
Yields for each Field for which cond
.call(field) is true. The (default) cond
of nil is considered true for all fields, so this acts like a normal #each() when called with no arguments.
135 136 137 138 139 140 141 142 |
# File 'lib/vcard/dirinfo.rb', line 135 def each(cond = nil) # :yields: Field @fields.each do |field| if(cond == nil || cond.call(field)) yield field end end self end |
#encode(width = nil) ⇒ Object Also known as: to_s
The string encoding of the DirectoryInfo. See Field#encode for information about the width parameter.
235 236 237 238 239 240 |
# File 'lib/vcard/dirinfo.rb', line 235 def encode(width=nil) unless @string @string = @fields.collect { |f| f.encode(width) } . join "" end @string end |
#enum_by_cond(cond) ⇒ Object
Returns an Enumerator for each Field for which cond
.call(field) is true.
180 181 182 |
# File 'lib/vcard/dirinfo.rb', line 180 def enum_by_cond(cond) Enumerator.new(self, cond ) end |
#enum_by_group(group) ⇒ Object
Returns an Enumerator for each Field for which #group?(group
) is true.
For example, to print all the fields, sorted by group, you could do:
card.groups.sort.each do |group|
card.enum_by_group(group).each do |field|
puts "#{group} -> #{field.name}"
end
end
or to get an array of all the fields in group “AGROUP”, you could do:
card.enum_by_group("AGROUP").to_a
175 176 177 |
# File 'lib/vcard/dirinfo.rb', line 175 def enum_by_group(group) Enumerator.new(self, Proc.new { |field| field.group?(group) }) end |
#enum_by_name(name) ⇒ Object
Returns an Enumerator for each Field for which #name?(name
) is true.
An Enumerator supports all the methods of Enumerable, so it allows iteration, collection, mapping, etc.
Examples:
Print all the nicknames in a card:
card.enum_by_name("NICKNAME") { |f| puts f.value }
Print an Array of the preferred email addresses in the card:
pref_emails = card.enum_by_name("EMAIL").select { |f| f.pref? }
158 159 160 |
# File 'lib/vcard/dirinfo.rb', line 158 def enum_by_name(name) Enumerator.new(self, Proc.new { |field| field.name?(name) }) end |
#field(name) ⇒ Object
The first field named name
, or nil if no match is found.
95 96 97 98 |
# File 'lib/vcard/dirinfo.rb', line 95 def field(name) enum_by_name(name).each { |f| return f } nil end |
#fields ⇒ Object
All fields, frozen.
128 129 130 |
# File 'lib/vcard/dirinfo.rb', line 128 def fields #:nodoc: @fields.dup.freeze end |
#groups ⇒ Object
Array of all the Field#group()s.
123 124 125 |
# File 'lib/vcard/dirinfo.rb', line 123 def groups @fields.collect { |f| f.group } .compact.uniq end |
#push(field) ⇒ Object Also known as: <<
Append field
to the fields. Note that it won’t be literally appended to the fields, it will be inserted before the closing END field.
191 192 193 194 195 |
# File 'lib/vcard/dirinfo.rb', line 191 def push(field) dirty @fields[-1,0] = field self end |
#push_end(field) ⇒ Object
Append field
to the end of all the fields. This isn’t usually what you want to do, usually a DirectoryInfo’s first and last fields are a BEGIN/END pair, see #push().
209 210 211 212 |
# File 'lib/vcard/dirinfo.rb', line 209 def push_end(field) @fields << field self end |
#push_unique(field) ⇒ Object
Push field
onto the fields, unless there is already a field with this name.
201 202 203 204 |
# File 'lib/vcard/dirinfo.rb', line 201 def push_unique(field) push(field) unless @fields.detect { |f| f.name? field.name } self end |
#text(name) ⇒ Object
An array of all the values of fields named name
, converted to text (using Field#to_text()).
TODO - call this #texts(), as in the plural?
112 113 114 115 116 117 118 119 120 |
# File 'lib/vcard/dirinfo.rb', line 112 def text(name) accum = [] each do |f| if f.name? name accum << f.to_text end end accum end |