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()). - #valid? ⇒ Boolean
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 43 44 45 46 47 48 49 |
# File 'lib/vcard/dirinfo.rb', line 33 def initialize(fields, profile = nil) #:nodoc: @valid = true @fields = [] fields.each do |f| raise ArgumentError, "fields must be an array of DirectoryInfo::Field objects" unless f.kind_of? DirectoryInfo::Field if f.valid? @fields << f else @valid = false end end @string = nil # this is used as a flag to indicate that recoding will be necessary 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().
91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/vcard/dirinfo.rb', line 91 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.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/vcard/dirinfo.rb', line 67 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.
113 114 115 116 117 |
# File 'lib/vcard/dirinfo.rb', line 113 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.
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 |
# File 'lib/vcard/dirinfo.rb', line 258 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.
233 234 235 236 237 238 239 240 241 242 |
# File 'lib/vcard/dirinfo.rb', line 233 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.
196 197 198 |
# File 'lib/vcard/dirinfo.rb', line 196 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.
146 147 148 149 150 151 152 153 |
# File 'lib/vcard/dirinfo.rb', line 146 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.
246 247 248 249 250 251 |
# File 'lib/vcard/dirinfo.rb', line 246 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.
191 192 193 |
# File 'lib/vcard/dirinfo.rb', line 191 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
186 187 188 |
# File 'lib/vcard/dirinfo.rb', line 186 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? }
169 170 171 |
# File 'lib/vcard/dirinfo.rb', line 169 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.
106 107 108 109 |
# File 'lib/vcard/dirinfo.rb', line 106 def field(name) enum_by_name(name).each { |f| return f } nil end |
#fields ⇒ Object
All fields, frozen.
139 140 141 |
# File 'lib/vcard/dirinfo.rb', line 139 def fields #:nodoc: @fields.dup.freeze end |
#groups ⇒ Object
Array of all the Field#group()s.
134 135 136 |
# File 'lib/vcard/dirinfo.rb', line 134 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.
202 203 204 205 206 |
# File 'lib/vcard/dirinfo.rb', line 202 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().
220 221 222 223 |
# File 'lib/vcard/dirinfo.rb', line 220 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.
212 213 214 215 |
# File 'lib/vcard/dirinfo.rb', line 212 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?
123 124 125 126 127 128 129 130 131 |
# File 'lib/vcard/dirinfo.rb', line 123 def text(name) accum = [] each do |f| if f.name? name accum << f.to_text end end accum end |
#valid? ⇒ Boolean
51 52 53 |
# File 'lib/vcard/dirinfo.rb', line 51 def valid? @valid end |