23 Jul
duccio

duccio il 23 July 2007 parla di Rails Snippet

RSS e ATOM feed in Rails

Avete mai provato a generare Feed RSS e ATOM validati in rails? Per risolvere il problema ho creato due metodi che estendono la classe object che si chiamano to_rss() e to_atom(). Usandoli su una collezione di oggetti sarà semplice generare il feed. Per includerli nel progetto ho creato un plugin con una libreria chiamata object_extend.rb:

    1 class Object
    2 def to_rss(options)
    3      # Render the feed using an RXML template
    4      xml_string = <<-XML_END
    5      xml.instruct!
    6      xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
    7         xml.channel do
    8            xml.title   "#{options[:blog_title] || "My Blog"}"
    9            xml.link    "#{options[:blog_link]}"
   10            xml.pubDate     "#{CGI.rfc1123_date(Time.now())}"
   11            xml.description  "#{options[:blog_description] || "Latest Post"}"
   12      XML_END
   13      
   14      self.collect do |item| 
   15      
   16      xml_string += <<-XML_END  
   17          xml.item do
   18             xml.title       "#{item.title}"
   19             xml.link        "#{item.post_link}"
   20             xml.pubDate     "#{CGI.rfc1123_date(item.published_at)}"
   21             xml.guid        "#{item.post_link}"
   22             xml.author      "#{item.author_email}"
   23             xml.description do
   24                xml << "#{item.body}"
   25             end
   26          end
   27       XML_END
   28       end
   29       
   30       xml_string += <<-XML_END 
   31          end
   32       end
   33      XML_END
   34         return xml_string
   35      end
   36 
   37      def to_atom(options)
   38           # Render the feed using an RXML template
   39           xml_string = <<-XML_END
   40           xml.instruct!
   41           xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
   42                 xml.title   "#{options[:blog_title] || "My Blog"}"
   43                 xml.link(:rel => "self", :href => "#{options[:blog_link]}")
   44                 xml.updated     "#{Time.now().to_s(:rfc3319_date)}"
   45                 xml.author do
   46                    xml.name "me"
   47                end
   48                 xml.id  "#{options[:blog_link]}"
   49           XML_END
   50 
   51           self.collect do |item| 
   52 
   53           xml_string += <<-XML_END  
   54               xml.entry do
   55                  xml.title       "#{item.title}"
   56                  xml.link(:href => "#{item.post_link}")
   57                  xml.updated     "#{item.published_at.to_s(:rfc3319_date)}"
   58                  xml.id        "#{item.post_link}"
   59                  xml.summary do
   60                     xml << "#{item.body}"
   61                  end
   62               end
   63            XML_END
   64            end
   65 
   66            xml_string += <<-XML_END 
   67               end
   68           XML_END
   69              return xml_string
   70           end
   71 end
   72 
   73 class Time
   74   def to_s(format = :default)
   75     case DATE_FORMATS[format]
   76     when Proc   then DATE_FORMATS[format].call(self)
   77       
   78     when String then strftime(DATE_FORMATS[format]).strip
   79     else to_default_s
   80     end
   81   end
   82 end
   83 Time::DATE_FORMATS[:rfc3319_date] = '%Y-%m-%dT%H:%M:%SZ'

Potete scegliere se inserire la libreria in un plugin oppure metterla nella cartella lib del vostro progetto e includerla nell’environment.

Come si utilizzano to_rss() e to_atom()?

Per generare il feed (supponiamo l’atom) potete fare così:

    1       @blog = Blog.find(params[:blog_id])
    2       render(:inline => @blog.posts.to_atom(:blog_title => "Mio blog", 
    3                                            :blog_link => url_for(:controller => "blog", :action => "blog", :username => @blog.bloggable.login.to_url, :blogname => "my-blog", :keyword => @blog.title.to_url, :blog_id => @blog.id), 
    4                                            :blog_description => "Ultimi post"), 
    5       :type => :rxml)

In questo caso genero il feed atom di una collezione di post di un blog; per farlo dovete renderizzare un file di tipo :rxml. I valori che passo al metodo .to_atom() servono per dare il titolo, la descrizione e il link al blog.

Il singolo post deve avere gli attributi author_email per specificare la mail dell’autore e post_link per memorizzare il link al post.

Perchè definire to_s(:rfc3319_date) per la classe Time?

    1 class Time
    2   def to_s(format = :default)
    3     case DATE_FORMATS[format]
    4     when Proc   then DATE_FORMATS[format].call(self)
    5       
    6     when String then strftime(DATE_FORMATS[format]).strip
    7     else to_default_s
    8     end
    9   end
   10 end
   11 Time::DATE_FORMATS[:rfc3319_date] = '%Y-%m-%dT%H:%M:%SZ'

Poichè le regole di sintassi del feed Atom impongono che la data sia espressa nel formato rfc3319 ho definito un metodo tos(:rfc3319date) che la formatti nel modo corretto.

Se il feed non è validato potreste avere problemi con alcuni lettori; per controllare il vostro feed potete usare feed validator per ATOM, RSS e KML.

1 Commento a “RSS e ATOM feed in Rails”

  1. Generare feed RSS in Rails « Kisin Kommer il 16 September 2008 alle 16:32 dice:

    [...] on Rails, To do Come sopra, avendo una memoria davvero pessima, mi devo segnare da qualche parte questo metodo per creare feed RSS con Rails! Gran [...]

Scrivi un commento