A4e2fea57f511d697f1de55198996f23

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?

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 !

008059ed6b16d4c2a8793bbb24508ba7

Jordan Glasner

May 31, 2008, May 31, 2008 01:51, permalink

No rating. Login to rate!

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
008059ed6b16d4c2a8793bbb24508ba7

Jordan Glasner

May 31, 2008, May 31, 2008 02:01, permalink

No rating. Login to rate!

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
A4e2fea57f511d697f1de55198996f23

Jason

May 31, 2008, May 31, 2008 13:03, permalink

No rating. Login to rate!

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.

008059ed6b16d4c2a8793bbb24508ba7

jordan Glasner

May 31, 2008, May 31, 2008 14:47, permalink

No rating. Login to rate!

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

Your refactoring





Format Copy from initial code

or Cancel