Part of the app I’m creating for Messiah College is a News Release screen, that pulls all the news releases for the college from their website. Luckily they have an RSS feed for this, so we’ll exploit that and built a 2-screener model for my app.
The first thing I did was investigate, or do some Free-App-Investigative-Research. I’m a Redskins fan and I use a free app called Skins Radar. This has the perfect implementation of a news type feature. More importantly – it utilizes a great feature for offline reading, so if you don’t have a connection, the page doesn’t error out. So we’ll use that idea as well.
Our Newsreader model will have two screens – the first a summary listing the Title and small 125 character summary block. When you touch the block, it’ll load the full post on a 2nd screen. We’ll use the index method to check to see if the file is there yet, and if not, we’ll call the method to grab it. If the file is there (we’ve pulled it already) we’ll parse and display the list.
Here’s your index method -
def index
#build filename with proper location path
@@file_name = File.join(Rho::RhoApplication::get_base_app_path(), 'messiah_press_releases.rss')
#check for file first (uncomment to log the check):
if File.exist? @@file_name
#puts "\n\n\nITS HERE !!! \n ------------------------------\n\n\n"
WebView.navigate ( url_for :action => :feed_display_static )
else
#puts "\n\n\nGO GET IT !!! \n ------------------------------\n\n\n"
WebView.navigate ( url_for :action => :feed_refresh )
end
end
Now then we’ll create this method to fetch the file (or refresh it if its already there). Since this doesn’t care if the file is there before it pulls it down, it’ll overwrite it with the new one (refreshing it), thus the name “feed_refresh”
def feed_refresh
#Refresh our feed to local file
Rho::AsyncHttp.download_file(
:url => 'http://blogs.messiah.edu/news_releases/feed/rss/',
:filename => @@file_name,
:headers => {},
:callback => (url_for :action => :feed_display_static),
:callback_param => ""
)
render :action => :wait
end
Since we’re using AsyncHttp.download_file – it will well, download the file and name the local copy whatever you named it in the index method.
If the file is already there (we’re returning to this screen from somewhere else) we’ll parse it with the method : feed_display_static
def feed_display_static
#open the file and read it in :
file = File.new(@@file_name)
begin
require 'rexml/document'
doc = REXML::Document.new(file)
@@get_result = "Success"
rescue Exception => e
puts "Error: #{e}"
@@get_result = "Error: #{e}"
end
@@xml = doc
WebView.navigate ( url_for :action => :show_result )
end
Here’s where my ruby / Rhodes experience lacks. This doesn’t really do the displaying as the method name states, because when I did the parsing of the document here, I had problems sending that parsed information back to the view, so I just parse the returned feed using REXML. There has to be a better way, but this works for me, so that’s what I’m doing.
I also have this method so we set the @@xml variable and call that from the view
def get_res
@@xml
end
Now we need to make our index.erb file, this is how I did it -
<% xml = get_res() %>
{snip out the toolbar and header stuff}
One part we won’t snip out is the refresh button :
<div id='rightItem'><a href="feed_refresh"><img src="/public/images/bar/refresh2.png" /></a></div>
put this in the toolbar div and it’ll create a nice right justified refresh icon area. Just add your own icon.
<ul style=’margin-left:10px;margin-right:10px;’>
<%
counter = “0″
data = {}
data['title'] = xml.root.elements['channel/title'].text
data['home_url'] = xml.root.elements['channel/link'].text
data['rss_url'] = @url
data['items'] = []
xml.elements.each(‘//item’) do |item|
it = {}
it['id'] = counter.next
it['title'] = item.elements['title'].text
it['link'] = item.elements['link'].text
it['description'] = item.elements['description'].text
if item.elements['content:encoded']
it['content'] = item.elements['content:encoded'].text
end
if item.elements['dc:creator']
it['author'] = item.elements['dc:creator'].text
end
if item.elements['dc:date']
it['publication_date'] = item.elements['dc:date'].text
elsif item.elements['pubDate']
it['publication_date'] = item.elements['pubDate'].text
end
data['items'] << it
long_desc = it['description'];
brief_description = long_desc[0,125] + “…”;
%>
<li class=’li_detail_disclosure’>
<a href=”<%= url_for :action => :show, :query => {:title => it['title'],:description => it['description'], :link => it['link']} %>”>
<div class=’rss_summary’ style=’width:250px;’>
<span class=’rss_title’><%=it['title']%></span>
<span class=’rss_description’><%= brief_description%></span>
</div>
</a>
</li>
<% end %>
</ul>
Now, I know you’re supposed to limit the ruby you place in your .erb files, and this is a prime example of my inexperience. I know this should go into the controller, and maybe in the display method we created above, but I wouldn’t get it to pass to the view.
Now all you need is the show method we call when you tap a summary block. And here it is pulling the parameters from our query string in the block link -
def show
@title = @params['title']
@description = @params['description']
@website = @params['link']
render :action => :show
end
And our show.erb file
{snip out the toolbar and header stuff}
<ul><li>
<span class='rss_detail_title'><%= @title%></span><br/>
<span class='rss_detail_description'><%= @description %></span><br/>
<div class='rss_website' align='center'><a href='<%=@website%>'>Read it on the web</a></div>
</li></ul>
Depending on the classes you play with in the css files, you can get this to display quite nicely.
So there you have it in a nutshell. The basics of an RSS reader.
You can download the entire model here – just expand it to your app directory, and link to it like this from the main index.erb file in your app -
<li>
<a href="Newsrelease">
<span class="title">Messiah News Releases</span>
<span class="disclosure_indicator"></span>
</a>
</li>
| iPhone App Screenies of NewsReader Model
|
 RSS List |
|
RSS Article Detail
|
ISSUES / IMPROVEMENTS / CALL FOR HELP
So – Please let me know how I can improve this – I mentioned how the rendering should get moved to the controller.
I also uncovered an issue with the renderer in index.erb. When I leave off the “rss/” portion of my url, it will pull FULL articles, and the entire format changes. The full feed allows for embedded HTML which causes a problem with this parser. I’m not familiar enough to know how to fix it, so if you do know, I’d appreciate a comment about it. I’ll list you in the app credits