From: Dreamcat Four on 10 Mar 2010 05:53 Hi, At the stage of implementing the interface for a new RubyGem. The main goal is to make something that is intuitive, easy to use. Its a library for manipulating apple plists. So really we are just manipulating a file, BUT its of a certain type and predifined structure. The current feature set includes: * Read, write, and edit (modify-in-place) * Can remember operations, but act later (passing in a block), then calling 'finalize', 'close' or something when the work is to be done. * Different *types* of plist. Like we can restrict our valid data if our Plist is for Launchd, or an Appbundle's Info.plist * Whether binary or xml can be autodetected on read. But want to provide an option to specify how to write. I don't really know if that should be a seperate class, method, or just an optional parameter? * Maybe a couple of global options (or not!) Like whether to override / enable the subtypes (Info,Launchd) and their validation. Another possible option is to allow users to override the default backend and specify their own "backend" to use. * Have already decided / implemented for users to manipulate their plist data through the familiar ruby block syntax. eg `plist do setter_methods.. end`. So im not going to change that part. This exercise is more about avoiding confusion and providing the neatest possible interface. In previous work, i have never felt completely comfortable passing hashes to the initializer for options. Its just something im not very experienced at doing. But that, or anything else to make life easier for my users. Guessing that some of you might yawn and think "ive seen this all before somewhere else". Well its exactly you guys i need to talk to! -- Posted via http://www.ruby-forum.com/.
From: Brian Candler on 10 Mar 2010 06:10 You did google for 'ruby plist' already? I'd suggest you try out the various plist packages already out there, see what you like and what you dislike from their APIs. Then you can implement something which you like better. As a side benefit, you can use this in your announcement. E.g. "the code to do foo takes 20 lines using that package, but only 5 lines in mine" :-) -- Posted via http://www.ruby-forum.com/.
From: Dreamcat Four on 10 Mar 2010 06:27 So i've been looking at the current API interface to my classes. To be honest, Ive been playing with examples all morning, but cannot find a way to make them user friendly enough. Hopefully at least one person here would be kind enough to suggest to me a regular object to initializer eg `.new()` with an options hash? I wonder a lot how people have done this for other kinds of files. A while ago I write a gem for manipulating yaml files called `yamldoc` which tackled the problem of reading / writing yaml settings files. http://github.com/dreamcat4/yamldoc Yamldoc uses a very different approach. So im not saying that its necessarily applicable to this problem here. Just maybe another example to draw from. How best to solve a problem like this? Can any of you point to an examples from elsewhere in the Ruby world? These are my attempts so-far. Can't stress enough how im emphatically *not at all* happy with them yet. So don't waste your time replying to say how bad they are, or whats wrong with them. I already know :) But hopefully you can get the idea of what its trying to do. # 1. First attempt (but none of the options) launchd_plist filename do label "com.github.homebrew.myprogram" program_arguments ["/usr/bin/myprogram"] run_at_load true working_directory "/var/db/myprogram" standard_out_path "/var/log/myprogram.log" sockets do sock_service_name "netbios-ssn" end sockets do sock_service_name "netbios" bonjour ['smb'] end end plist.finalize # Module to avoid namespace conflicts include ::Plist4r # 2. This is not much different to 1 except the 'w' argument # it doesnt really seem to work for me p = plist4r("/Library/LaunchDaemons/org.cups.cupsd.plist",'w') p.keys do key1 "value1" key2 true end p.finalize # 3. If a plist is just a file then maybe ::File syntax? ::Plist4r.open(plist,'w') do key1 "value1" key2 true end ::Plist4r.open(plist,'r') do |hash| puts hash.inspect end # 4. Like 3 but we are writing a binary plist? ::Plist4r.open(plist,'w', :binary =>true) do key1 "value1" key2 true end # 5. Different again plist = ::Plist4r.open(plist,'w', :delayed_write => true) do key1 "value1" key2 true end plist.format = :binary # force to binary plist.finalize # actually reads and writes the plist -- Posted via http://www.ruby-forum.com/.
From: Dreamcat Four on 10 Mar 2010 06:44 Brian Candler wrote: > You did google for 'ruby plist' already? Yes. Although none of them provide the same kind of options that I shall be providing. Actually, this gem aims to do is use those as pluggable `backends`. Eg for reading/writing a binary plist on OS-X, the gem can detect and use RubyCocoa. (which may be faster / natively supported Apply code). However for reading / writing a binary plist on Linux, it might failover to either Ben's github gist or ckruse/CFPropertyList (a ruby library). They are here: http://github.com/bleything/plist http://gist.github.com/303378 http://github.com/ckruse/CFPropertyList I also have my own xml based parser / writer which uses libxml / haml. Its not known yet which implementations are the more stable, reliable and effecient. Hence a pluggable backends strategy kindda seems to make sense to me. I've already worked with something similar in the GeoKit gem. One thing I was hoping to find out by coming here was: Maybe someone had written a ruby DSL for manipulating other kinds of files. Like .jpeg images, pdf files, or some other neat interface for writing their structured data. Then it might help this plist editing interface better by taking their lessons learned. -- Posted via http://www.ruby-forum.com/.
From: Dreamcat Four on 10 Mar 2010 11:35
Standard initializers seem better. Leaning toward b) # a) plist_opts = { :filename => "car.plist", :type => :vehicle_plist, :save_format => binary, :autoload => true, :autosave => false } car = Plist4r.new(plist_opts) { road_legal true brake_light_color "red" } car.save # b) car = Plist4r.new("car.plist") car.type = :vehicle_plist car.load # also detects plist type # not sure what to call this method # it overwrites any existing keys, # appending the new/replacement keys car << do road_legal true brake_light_color "red" end car.save(:binary => true) -- Posted via http://www.ruby-forum.com/. |