XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
<!-- THE XML IM TRYING TO PARSE --> <channel> <title/> <link>http://localhost/drupal/view/cyloop_mobile</link> <description>cyloop mobile</description> <language>en</language> <item> <title>Kinky</title> <link>http://localhost/drupal/node/3278</link> <description> <drupal_id>3278</drupal_id> <body></body> <image>/drupal/files/kinky_thumb_3_0.jpg</image> <publishing_site>Cyloop</publishing_site> <artist_id>23631</artist_id> </description> <authored>Tue, 19 Feb 2008 18:09:25 -0500</authored> <author>diana</author> <updated>Thu, 03 Apr 2008 15:54:16 -0400</updated> </item> <item> <title>Matchbox Twenty</title> <link>http://localhost/drupal/node/3277</link> <description> <drupal_id>3277</drupal_id> <body></body> <image>/drupal/files/mbox20_thumb_1_0.jpg</image> <publishing_site>Cyloop</publishing_site> <artist_id>29222</artist_id> </description> <authored>Tue, 19 Feb 2008 18:07:03 -0500</authored> <author>diana</author> <updated>Thu, 03 Apr 2008 15:53:43 -0400</updated> </item> </channel>
Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# MY CONTROLLER require 'hpricot' require 'open-uri' class SiteController < ApplicationController def index # Page title for index view. @title = "Cyloop Mobile" # XML url to parse. url = 'http://cm.cyloop.com/feeds/drupal/cyloop_mobile.xml' # Open XML wth hpricot and store it in page. page = Hpricot.XML(open(url)) (page/:item).each do |item| title = (item/:title).inner_html end end end
View
1 2 3 4 5
<h1>Featured</h1> <ul> <li></li> </ul>
Refactorings
No refactoring yet !
Jordan Glasner
May 31, 2008, May 31, 2008 01:51, permalink
models/channel.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
class Channel attr_accessor :url require 'hpricot' def initialize(url) @url = url end def xml require 'open-uri' @xml ||= Hpricot.XML(open(url)) end def items (xml/:item).map { |item_xml| Item.new(item_xml) } end end
models/item.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
def Item require 'hpricot' attr_accessor :xml def initialize(xml) @xml = xml end def title (xml/:title).inner_html end end
controllers/channels_controller.rb
1 2 3 4 5 6 7 8 9 10 11
class ChannelsController < ApplicationController def index @title = 'Cyloop Mobile' @channel = Channel.new('http://cm.cyloop.com/feeds/drupal/cyloop_mobile.xml') end end
views/channels/index.html.haml
1 2 3 4 5 6 7
# sorry would give you erb, but I would probably lead you astray %h1 Featured - @channel.items.each do |item| %h2= item.title
Jordan Glasner
May 31, 2008, May 31, 2008 02:01, permalink
arg.. I thought would be able to edit after submitting. Ignore the above, as it has some stupid errors and zero comments...
models/channel.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
class Channel attr_accessor :url require 'hpricot' # pass a url as a string to initialize def initialize(url) @url = url end def xml require 'open-uri' # loads the Hpricot XML object if it hasn't already been loaded @xml ||= Hpricot.XML(open(url)) end def items # map is turning the array of XML objects into an array of Items (xml/:item).map { |item_xml| Item.new(item_xml) } end end
models/item.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
class Item require 'hpricot' attr_accessor :xml # pass the item XML chunk to create a new item def initialize(xml) @xml = xml end # parses the title element from the XML chunk def title (xml/:title).inner_html end end
controllers/channels_controller.rb
1 2 3 4 5 6 7 8 9 10
class ChannelsController < ApplicationController def index @title = 'Cyloop Mobile' # create the channel @channel = Channel.new('http://cm.cyloop.com/feeds/drupal/cyloop_mobile.xml') end end
views/channels/index.html.haml
1 2 3 4 5 6 7 8
# sorry would give you erb, but I would probably lead you astray %h1 Featured # iterate through the items array - @channel.items.each do |item| %h2= item.title
Jason
May 31, 2008, May 31, 2008 13:03, permalink
Ok, trying to take all this in, I wouldn't have thought you would need a model since I'm not actually saving any data. and on the def initialize in the models/channel.rb how does the url get passed in to the initialized method? trying to learn, thats why i am asking all the questions.
jordan Glasner
May 31, 2008, May 31, 2008 14:47, permalink
Yeah, using models only for DB access is a common misconception. I think about anything that needs to be manipulated, and I turn those into models. Ideally, your controller is only taking user input and/or creating new objects based on your models. Do a search for "skinny controllers / fat models" for more info on leaving the heavy lifting to models.
As for initialize, when you call Model.new(args) args are passed to the initialize method of the Model. So for the Channel model, you would do
Channel.new('http://mysite.com/my.xml')
After a little more thought, it's probably best to change your controller to ItemsController as that's really what you're displaying.
So...
controllers/items_controller.rb instead of controllers/channels_controller
1 2 3 4 5 6 7 8 9 10
class ItemsController < ApplicationController def index @title = 'Cyloop Mobile' # create the channel and save the items to a variable @items = Channel.new('http://cm.cyloop.com/feeds/drupal/cyloop_mobile.xml').items end end
views/items/index.html.haml
1 2 3 4 5 6
%h1 Featured # iterate through the items array - @items.each do |item| %h2= item.title
I am completely new to ruby on rails and kinda new to programming. I've hacked together some php scripts but thats it.
What i am trying to do is parse through this xml and pass the title attributes to the view.
I'm not even sure if this code will work to capture the xml, I'm guessing i need the view portion to test it out. When i view the page as it is.. it doesnt error out, so i guess thats good.
I'm using Hpricot to parse the xml.
So basically how do i capture the results of this and pass it to the view?