From: Josh Cheek Date: 2011-01-20T12:17:18+09:00 Subject: Re: edit xml file. --001636283594dc4b31049a3e9138 Content-Type: text/plain; charset=ISO-8859-1 On Wed, Jan 19, 2011 at 6:54 PM, Dan Thomas wrote: > I actually got it all working, except that I am modifying the xml > explicitly (in a post block), using REXML like this: > > Good job! I know that can be frustrating to try to figure out :) Though, you should know that Nokogiri is widely considered the best Ruby XML library there is, it is fastest, most reliable, most consistent, and has a pretty nice interface. Even Martin Fowler uses it for his own site. So, if you wind up refactoring that code, you might consider using Nokogiri over REXML. > newSound = params[:newsound] > > # open the xml > File.open("public/script2.xml", "r") do |aFile| > config = REXML::Document.new(aFile) > rootVar = config.root.elements['object'] > > > #drill down to the sound node, assign the new value to it > > rootVar.elements['property[2]'].elements['array'].elements['object'].elements['property[2]'].elements['array'].elements['object'].elements['property[2]'].attributes["value"] > = newSound > This looks fragile to me. I don't understand xpaths, I always use CSS selectors, but it looks like you are telling it what to set, based on its position within the document. You'll want to be careful to check if an element is added or removed, or if the order is changed, will that break this query? It seems like a Law of Demeter violation. You might put an id on the sound node so you don't have to drill down to it, but can just say to get the one with the given id, and edit it that way. Then it would probably be more robust, easier to read, and faster. > > # reopen the file for writing, which will erase it, and copy all the > data into it > formatter = REXML::Formatters::Default.new > File.open('public/script2.xml', 'w') do |result| > > formatter.write(config, result) > end > end > # re-read in the xml file, and then load index again > $script_post = File.read("public/script2.xml") > @xml = Nokogiri::XML($script_post) > erb:index > > I guess I typically store my data in a database, but if the XML file is working, then that seems like a fine solution. Sounds like its in the spirit of YAGNI, so I suppose the XPers would be proud :) > > The part I need to fix for my boss is: the part where I'm drilling down > to assign the new value should be somehow connected to index.erb, which > is doing all kinds of looping and variable assignments related to the > xml. I don't know what it is called or where to start. Hell I don't > even know how to explain it. Sorry for the long post, any help, search > words to look-up, or examples greatly appreciated. > > Hmm, sorry, its not very clear to me what you want to do differently. I don't think it is a good idea to modify your template (the erb file). I got the impression you were storing your data in an XML file on your file system, which seems fine, and seems like your solution is congruent with. I'm a little confused by the use of global variables (the ones that begin with the dollar signs), I was kind of thinking maybe the guy before you read in the xml to there, then stored that in memory. And then you could just edit the Nokogiri document, and save that to a file without having to do lots of writing and reading and redoing the same work. But since its inside the root get request, I'm less sure. I suppose I'd need to see more code, that seems nonstandard. Regarding the looping and variable assignments, you are right, that probably shouldn't be in the template, it could probably be refactored to use helpers (methods that handle responsibilities, you call them from your template so the template doesn't have to do the work right there inside it) and partials (other erb templates that you can render into the one you are working on), If you decide you want to do that, the Sinatra code below should talk about both of those. I think the best I can do is give you links to where you can find more info on some of the tools you are using. * It looks like you are using the Sinatra web framework http://www.sinatrarb.com/ Very simple and elegant, you could probably learn enough about it to understand everything in your script with just a few hours There is a Sinatra book, which is comprehensive http://sinatra-book.gittr.com/ I personally got a lot out of the Sinatra Peepcode http://peepcode.com/products/sinatra though it goes beyond what you are using it for * For XML, you have Nokogiri http://nokogiri.org/ Check out the tutorials section to see how to use it to modify your xml * For templating, you are using ERB http://ruby-doc.org/stdlib/libdoc/erb/rdoc/classes/ERB.html It's really straightforward, anything with <%= ... %> will treat the inside as Ruby, convert it to a string, and stick it in the document Anything with <% ... %> will treat the inside as Ruby, but won't have output (ie a control structure like a loop) Here are a couple of simple examples https://github.com/JoshCheek/JoshsRubyKickstart/blob/master/cheatsheets/erb-embedded_ruby.rb * I also see you are using andand http://andand.rubyforge.org/ It can be summarized as: a.andand(b) is equivalent to a && a.b which doesn't seem that impressive, until you realize a could be anything, including a really long or expensive method call, where you would otherwise have to store the result in a temporary variable. There is also a fascinating, though probably not particularly relevant for you video by the author of andand, about how it works, and how he perceives Ruby vs purely functional languages, what he sees as issues, and why he wrote andand http://www.infoq.com/presentations/braithwaite-rewrite-ruby --001636283594dc4b31049a3e9138--