Hey there, I''ve been playing a lot with Vpim lately, putting it in various Rails apps and getting it to do my bidding. I have an app I made a while back that acts as a web interface for an LDAP address book, and right now I''m experimenting with Vpim to make it so users can import and export vCards directly to and from the LDAP database. In the process of this, I''ve found that the "[]" method of the Vpim::Vcard class (http://vpim.rubyforge.org/classes/Vpim/ Vcard.html#M000129) is rather cumbersome and not well-suited to my needs. What I''d like to do is turn an entire vCard into an object whose data can be accessed through methods such as @card.name, @card.org, etc. In short, to make it more like ActiveRecord. (Actually, the library I am using to interface with LDAP is called "Ruby-ActiveLDAP" and did just that for the Ruby/LDAP library: http:// dataspill.org/posts/show/4) I''m writing because I''m trying to build this sort of functionality into my own app, but I think it would be a great thing to contribute back to the Vpim project. I noticed in the rDoc for Vpim::Vcard that the developer has been toying with the idea of doing something like this. I''d like to help make it happen, but I should note I''m still somewhat of a novice when it comes to building rich-OO Ruby libraries. Let me know if you have any tips for how to write my class, and what your thoughts are on the idea. Thanks. -Ian Westcott application developer/ support specialist the barbarian group, llc 338 newbury street, 3rd floor boston, ma 02115-2700 ianw at barbariangroup.com 617-424-8887
On Mon, Dec 05, 2005 at 05:44:38PM -0500, Ian Westcott wrote:> From: Ian Westcott <ianw at barbariangroup.com> > To: vpim-talk at rubyforge.org > Subject: [Vpim-talk] ways to make vpim more "active" > Date: Mon, 5 Dec 2005 17:44:38 -0500 > X-Mailer: Apple Mail (2.746.2) > > Hey there, > > I''ve been playing a lot with Vpim lately, putting it in various Rails > apps and getting it to do my bidding. I have an app I made a while > back that acts as a web interface for an LDAP address book, and right > now I''m experimenting with Vpim to make it so users can import and > export vCards directly to and from the LDAP database. > > In the process of this, I''ve found that the "[]" method of the > Vpim::Vcard class (http://vpim.rubyforge.org/classes/Vpim/ > Vcard.html#M000129) is rather cumbersome and not well-suited to my > needs. What I''d like to do is turn an entire vCard into an object > whose data can be accessed through methods such as @card.name, > @card.org, etc. In short, to make it more like ActiveRecord.No comment on ActiveRecord, since I''ve never used it. There are already convenience methods for birthday, nickname, and version, but just attr readers. They exist because I''ve needed them, I''m happy to add to the list on request. Version must be read-only, but I could add birthday=(), nickname=(), etc. Is this what you are looking for? And have you looked at Maker::Vcard? You need to know when you assign to a vCard element what type structure can be assigned. Also, you should not carefully that many fields can occur multiple times, postal addresses, email addresses, telephone numbers, etc. How would you like to select which one you are interested in? For example, from your examples, what field in a vCard would Vcard#name correspond to? N? FN? One is a String, the other is an array in a specified order (see below). I could force this, by making a Vcard#name,Vcard#name= method pair that takes a Vpim::Vcard::Name object, or maybe some kind of hash, or maybe... so many possibilities. All probably trivial to implement. The ORG field is an array of strings, going from most encompassing to least encompassing: ORG:ABC\, Inc.;North American Division;Marketing I guess you would want a Vcard#org= that takes an Array of String? Anyhow, if you post some example code showing how you would like to call these methods (and what the call should do, if it isn''t obvious), I''ll see what I can do about implementing them. Or maybe, post the code you have currently that creates Vcards and that is to cumbersome, it might be obvious to me from that what kind of Vcard API would make your code flow better. Cheers, Sam 3.1.1 FN Type Definition Type name:FN Type purpose: To specify the formatted text corresponding to the name of the object the vCard represents. Type encoding: 8bit Type value: A single text value. Type special notes: This type is based on the semantics of the X.520 Common Name attribute. The property MUST be present in the vCard object. Type example: FN:Mr. John Q. Public\, Esq. 3.1.2 N Type Definition Type name: N Type purpose: To specify the components of the name of the object the vCard represents. Type encoding: 8bit Type value: A single structured text value. Each component can have multiple values. Type special note: The structured type value corresponds, in sequence, to the Family Name, Given Name, Additional Names, Honorific Prefixes, and Honorific Suffixes. The text components are separated by the SEMI-COLON character (ASCII decimal 59). Individual text components can include multiple text values (e.g., multiple Additional Names) separated by the COMMA character (ASCII decimal 44). This type is based on the semantics of the X.520 individual name attributes. The property MUST be present in the vCard object. Type example: N:Public;John;Quinlan;Mr.;Esq. N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P.
On Dec 5, 2005, at 9:44 PM, Sam Roberts wrote:> No comment on ActiveRecord, since I''ve never used it. > > There are already convenience methods for birthday, nickname, and > version, but > just attr readers. They exist because I''ve needed them, I''m happy > to add to > the list on request. Version must be read-only, but I could add > birthday=(), > nickname=(), etc. > > Is this what you are looking for? And have you looked at Maker::Vcard?Not really. I''m not trying to write vCards this way, just read them. The part of my app that prompted my first email was the "import" portion. So far I''ve got a file upload form where a user can drop in a .vcf file, and I''d like the script to parse it and pull out EVERYTHING in a format where I can then iterate over multiples within each attribute if/where they exist. Since Maker::Vcard already handles the writing, this could stay read-only. For example: Say I''m importing a vCard with multiple addresses. If I use card[]("ADR"), I get just the primary address, and in order to extract any of the other addresses I need to know what type they are, which is usually an arbitrary name, IIRC. What I''d like to do is say "give me all the addresses" and then say "for each address, do this", but also be able to ask each address what its type is, and whether it''s the preferred address. Same for telephone numbers, email addresses, et al.> For example, from your examples, what field in a vCard would > Vcard#name > correspond to? N? FN? One is a String, the other is an array in a > specified > order (see below).Ideally, both. For instance, calling card.name would retun the array of N, but calling card.name.last would just give you the first element of that array, etc. I see what you mean about this being potentially trivial and monotonous to code. It''s something I''ll probably have to do anyway for my app, though, so I don''t mind slogging through it, as long as I know I''m doing it "right".> I could force this, by making a Vcard#name,Vcard#name= method pair > that takes a > Vpim::Vcard::Name object, or maybe some kind of hash, or maybe... > so many > possibilities. All probably trivial to implement. > > The ORG field is an array of strings, going from most encompassing > to least > encompassing: > > ORG:ABC\, Inc.;North American Division;MarketingHmm, I''m not sure how this would be best object-ified, at least without assigning potentially arbitrary names to each element of the ORG array, i.e. "name", "division", "department", which may not apply for all values in all vCards...> Anyhow, if you post some example code showing how you would like to > call these > methods (and what the call should do, if it isn''t obvious), I''ll > see what I can > do about implementing them. > > Or maybe, post the code you have currently that creates Vcards and > that is to > cumbersome, it might be obvious to me from that what kind of Vcard > API would > make your code flow better.I''m still in the process of writing it while I think this through, but I''ll keep you posted. I hope this gives you more of a jist of what I''m going for. Let me know your thoughts.> Cheers, > Sam > > > 3.1.1 FN Type Definition > > Type name:FN > > Type purpose: To specify the formatted text corresponding to the > name > of the object the vCard represents. > > Type encoding: 8bit > > Type value: A single text value. > > Type special notes: This type is based on the semantics of the X. > 520 > Common Name attribute. The property MUST be present in the vCard > object. > > Type example: > > FN:Mr. John Q. Public\, Esq. > > > 3.1.2 N Type Definition > > Type name: N > > Type purpose: To specify the components of the name of the > object the > vCard represents. > > Type encoding: 8bit > > Type value: A single structured text value. Each component can have > multiple values. > > Type special note: The structured type value corresponds, in > sequence, to the Family Name, Given Name, Additional Names, > Honorific > Prefixes, and Honorific Suffixes. The text components are separated > by the SEMI-COLON character (ASCII decimal 59). Individual text > components can include multiple text values (e.g., multiple > Additional Names) separated by the COMMA character (ASCII decimal > 44). This type is based on the semantics of the X.520 individual > name > attributes. The property MUST be present in the vCard object. > > Type example: > > N:Public;John;Quinlan;Mr.;Esq. > > N:Stevenson;John;Philip,Paul;Dr.;Jr.,M.D.,A.C.P. > > On Mon, Dec 05, 2005 at 05:44:38PM -0500, Ian Westcott wrote: >> From: Ian Westcott <ianw at barbariangroup.com> >> To: vpim-talk at rubyforge.org >> Subject: [Vpim-talk] ways to make vpim more "active" >> Date: Mon, 5 Dec 2005 17:44:38 -0500 >> X-Mailer: Apple Mail (2.746.2) >> >> Hey there, >> >> I''ve been playing a lot with Vpim lately, putting it in various Rails >> apps and getting it to do my bidding. I have an app I made a while >> back that acts as a web interface for an LDAP address book, and right >> now I''m experimenting with Vpim to make it so users can import and >> export vCards directly to and from the LDAP database. >> >> In the process of this, I''ve found that the "[]" method of the >> Vpim::Vcard class (http://vpim.rubyforge.org/classes/Vpim/ >> Vcard.html#M000129) is rather cumbersome and not well-suited to my >> needs. What I''d like to do is turn an entire vCard into an object >> whose data can be accessed through methods such as @card.name, >> @card.org, etc. In short, to make it more like ActiveRecord. >>-Ian Westcott application developer/ support specialist the barbarian group, llc 338 newbury street, 3rd floor boston, ma 02115-2700 ianw at barbariangroup.com 617-424-8887
(whoops, I forgot to copy the list on this)> How successful is VPIM with rails?It works great! All you have to do is drop Vpim into your app''s "lib" folder, then include whatever elements your app needs in config/ environment.rb. Then you can just call its methods with the standard syntax, i.e. "@cards = Vpim::Vcard.decode(@params[:vcard].read)". -Ian Westcott application developer/ support specialist the barbarian group, llc 338 newbury street, 3rd floor boston, ma 02115-2700 ianw at barbariangroup.com 617-424-8887 On Dec 5, 2005, at 5:41 PM, Ben Schwarz wrote:> Hi, > > How successful is VPIM with rails? > I looked into this not too long ago... but never got to take it > further. > > Any little things I should know about? > > Cheers, > > Ben > > > -- > > On 06/12/2005, at 9:44 AM, Ian Westcott wrote: > >> Hey there, >> >> I''ve been playing a lot with Vpim lately, putting it in various Rails >> apps and getting it to do my bidding. I have an app I made a while >> back that acts as a web interface for an LDAP address book, and right >> now I''m experimenting with Vpim to make it so users can import and >> export vCards directly to and from the LDAP database. >> >> In the process of this, I''ve found that the "[]" method of the >> Vpim::Vcard class (http://vpim.rubyforge.org/classes/Vpim/ >> Vcard.html#M000129) is rather cumbersome and not well-suited to my >> needs. What I''d like to do is turn an entire vCard into an object >> whose data can be accessed through methods such as @card.name, >> @card.org, etc. In short, to make it more like ActiveRecord. >> >> (Actually, the library I am using to interface with LDAP is called >> "Ruby-ActiveLDAP" and did just that for the Ruby/LDAP library: >> http:// >> dataspill.org/posts/show/4) >> >> I''m writing because I''m trying to build this sort of functionality >> into my own app, but I think it would be a great thing to contribute >> back to the Vpim project. I noticed in the rDoc for Vpim::Vcard that >> the developer has been toying with the idea of doing something like >> this. I''d like to help make it happen, but I should note I''m still >> somewhat of a novice when it comes to building rich-OO Ruby >> libraries. >> >> Let me know if you have any tips for how to write my class, and what >> your thoughts are on the idea. >> >> Thanks. >> >> -Ian Westcott >> >> application developer/ >> support specialist >> the barbarian group, llc >> 338 newbury street, 3rd floor >> boston, ma 02115-2700 >> ianw at barbariangroup.com >> 617-424-8887 >> >> >> _______________________________________________ >> Vpim-talk mailing list >> Vpim-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/vpim-talk >> >> > >
On Tue, Dec 06, 2005 at 02:36:16PM -0500, Ian Westcott wrote:> Not really. I''m not trying to write vCards this way, just read them. > The part of my app that prompted my first email was the "import" > portion. So far I''ve got a file upload form where a user can drop in > a .vcf file, and I''d like the script to parse it and pull out > EVERYTHING in a format where I can then iterate over multiples within > each attribute if/where they exist. Since Maker::Vcard already > handles the writing, this could stay read-only. > > For example: Say I''m importing a vCard with multiple addresses. If I > use card[]("ADR"), I get just the primary address, and in order to > extract any of the other addresses I need to know what type they are, > which is usually an arbitrary name, IIRC. What I''d like to do is say > "give me all the addresses" and then say "for each address, do this", > but also be able to ask each address what its type is, and whether > it''s the preferred address. Same for telephone numbers, email > addresses, et al.Ok, then what you need is already there, maybe it didn''t leap out at you from the docs. Look at DirectoryInfo#enum_by_name: enum_by_name(name) Returns an Enumerator for each Field for which name?(name) is true. For example, to get an Array of all the email addresses in the card, you could do: card.enum_by_name(''email'').collect { |f| f.value } Perhaps the doc''s example is too clever. I''m trying to show that the enumerator returned supports everything in Enumerable, like #collect, but that also includes #each, which is what you want, it sounds like. Check out vcf-to-mutt.txt for an example of this: cards.each do |vcard| vcard.enum_by_name("email").each do |f| # ...access f.params, f.value, f.pref?, .... end end Would this be more useful?> >For example, from your examples, what field in a vCard would > >Vcard#name correspond to? N? FN? One is a String, the other is an > >array in a specified order (see below). > > Ideally, both. For instance, calling card.name would retun the array > of N, but calling card.name.last would just give you the first > element of that array, etc. I see what you mean about this being > potentially trivial and monotonous to code. It''s something I''ll > probably have to do anyway for my app, though, so I don''t mind > slogging through it, as long as I know I''m doing it "right".Well, in this specific case, the problem is that its not trivial. I have no idea why there are two standard ways to include the same information in a vCard. FN is freeform text, it looks like a concatenation of the elements of N, but I''m not sure if it always is. Both are mandatory fields. Maybe a really intelligent routine could try and decompose names into the X.520 parts used in the N field. What do the vCards you see look like? How are you planning on dealing with these two name representations in the same card? Thowing one away and using just one, ...? If you find a plan that works for you, it might work for others. Cheers, Sam