Class: Vpim::DirectoryInfo
- Inherits:
-
Object
- Object
- Vpim::DirectoryInfo
- Includes:
- Enumerable
- Defined in:
- lib/vpim/dirinfo.rb,
lib/vpim/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 = Vpim::Vcard.create
card << Vpim::DirectoryInfo::Field.create('EMAIL', '[email protected]', 'TYPE' => 'INTERNET' )
card << Vpim::DirectoryInfo::Field.create('URL', 'http://www.example.com/user' )
card << Vpim::DirectoryInfo::Field.create('FN', 'User Name' )
puts card.to_s
Don’t do it like that, use Vpim::Vcard::Maker.
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.
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/vpim/dirinfo.rb', line 41 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().
88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/vpim/dirinfo.rb', line 88 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 Vpim::DirectoryInfo::Field#create() for how to create a new Field.
TODO: I don’t believe this is ever used, maybe I can remove it.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/vpim/dirinfo.rb', line 64 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 = Vpim.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.
110 111 112 113 114 |
# File 'lib/vpim/dirinfo.rb', line 110 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.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/vpim/dirinfo.rb', line 255 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.
230 231 232 233 234 235 236 237 238 239 |
# File 'lib/vpim/dirinfo.rb', line 230 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.
193 194 195 |
# File 'lib/vpim/dirinfo.rb', line 193 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.
143 144 145 146 147 148 149 150 |
# File 'lib/vpim/dirinfo.rb', line 143 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.
243 244 245 246 247 248 |
# File 'lib/vpim/dirinfo.rb', line 243 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.
188 189 190 |
# File 'lib/vpim/dirinfo.rb', line 188 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
183 184 185 |
# File 'lib/vpim/dirinfo.rb', line 183 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? }
166 167 168 |
# File 'lib/vpim/dirinfo.rb', line 166 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.
103 104 105 106 |
# File 'lib/vpim/dirinfo.rb', line 103 def field(name) enum_by_name(name).each { |f| return f } nil end |
#fields ⇒ Object
All fields, frozen.
136 137 138 |
# File 'lib/vpim/dirinfo.rb', line 136 def fields #:nodoc: @fields.dup.freeze end |
#groups ⇒ Object
Array of all the Field#group()s.
131 132 133 |
# File 'lib/vpim/dirinfo.rb', line 131 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.
199 200 201 202 203 |
# File 'lib/vpim/dirinfo.rb', line 199 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().
217 218 219 220 |
# File 'lib/vpim/dirinfo.rb', line 217 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.
209 210 211 212 |
# File 'lib/vpim/dirinfo.rb', line 209 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?
120 121 122 123 124 125 126 127 128 |
# File 'lib/vpim/dirinfo.rb', line 120 def text(name) accum = [] each do |f| if f.name? name accum << f.to_text end end accum end |