I tried to create a RSS feed with image for each article and eventually a banner for Feedly and a logo but I struggle to do that.
Here is the preview of what I get :
Here is my RSS Builder:
#encoding: UTF-8
xml.instruct! :xml, :version => "1.0"
xml.rss :version => '2.0', 'xmlns:atom' => 'http://www.w3.org/2005/Atom', 'xmlns:media' => 'http://search.yahoo.com/mrss/' do
xml.channel do
xml.title "My RSS feed"
xml.description "Super description"
xml.link "MY_URL"
xml.language "en"
xml.tag! 'atom:link', :rel => 'self', :type => 'application/rss+xml', :href => "MY_URL/feed"
for article in #articles
xml.item do
xml.title article.name
xml.pubDate article.created_at.to_s(:rfc822)
xml.link "MY_URL"
xml.guid "MY_URL"
xml.media(:content, :url => article.image.url(:medium))
xml.media(:thumbnail, :url => article.image.url(:thumbnail))
xml.description "<p>" + article.description + "</p>"
end
end
end
end
And here is the result:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>My RSS feed</title>
<description>Super description</description>
<link>MY_URL</link>
<language>en</language>
<atom:link rel="self" type="application/rss+xml" href="MY_URL/feed"/>
<item>
<title>Dojo</title>
<pubDate>Mon, 23 Nov 2015 16:58:41 +0000</pubDate>
<link>MY_URL</link>
<guid>MY_URL</guid>
<media:content url="MY_URL"/>
<media:thumbnail url="MY_URL"/>
<description><p>Your security & privacy advisor.</p></description>
</item>
</channel>
</rss>
Thanks for your help with that!
I've checked out how it works in blog.feedly.com and here is example:
<item>
<title>POST_TITLE</title>
<link>URL_TO_POST</link>
<comments>URL_TO_COMMENTS</comments>
<pubDate>ISODate</pubDate>
<dc:creator>CDATA_AUTHOR_METATAG</dc:creator>
<category><![CDATA[All]]></category>
<guid isPermaLink="false">URL_WITHOUT_SLUG</guid>
<description>CDATA_DESCRIPTION</description>
<content:encoded>CDATA_POST_CONTENT</content:encoded>
<wfw:commentRss>URL_TO_COMMENTS_RSS</wfw:commentRss>
<slash:comments>NUMBER_OF_COMMENTS</slash:comments>
<media:content url="IMG_URL" medium="image">
<media:title type="html">Author</media:title>
</media:content>
<media:content url="IMG_URL" medium="image">
<media:title type="html">img_short_description</media:title>
</media:content>
</item>
Try to implement your feed items like I described above and if it will not work, check out item parent tags too. You need to do your rss feed just like at blog.feedly.com
Related
Given the following XML, I want to get the value "0123456" for Name="Cat":
xml.xpath '//Custom[Name="Cat"]'
Gives me the first custom, which is correct, but I only want the "Value" not the entire Custom node.
<body>
<Custom>
<count>1</count>
<Name>Cat</Name>
<Value>0123456</Value>
</Custom>
<Custom>
<count>2</count>
<Name>Dog</Name>
<Value>9876543</Value>
</Custom>
<body>
I only want the "Value" not the entire Custom node.
So just go on writing the path:
//Custom[Name="Cat"]/Value
I prefer to use CSS selectors over XPath, for readability, as usually CSS contains less visual noise:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<body>
<Custom>
<count>1</count>
<Name>Cat</Name>
<Value>0123456</Value>
</Custom>
<Custom>
<count>2</count>
<Name>Dog</Name>
<Value>9876543</Value>
</Custom>
<body>
EOT
foo = doc.search('name:contains("Cat")').map{ |node|
node.next_element.text
}
foo # => ["0123456"]
This works because Nokogiri contains some of the jQuery CSS extensions, resulting in some useful additions.
To get the value element text you need to set the xpath as below:
doc = Nokogiri::HTML(<<EOT)
<body>
<Custom>
<count>1</count>
<Name>Cat</Name>
<Value>0123456</Value>
</Custom>
<Custom>
<count>2</count>
<Name>Dog</Name>
<Value>9876543</Value>
</Custom>
<body>
EOT
val=doc.xpath("//Custom[Name='Cat']/Value").text()
val => "0123456"
I need to create an HTML fragment to embed in a page (a simple js gallery). This is the HTML:
<div id="gallery-1" class="royalSlider rsDefault">
<a class="rsImg" data-rsw="632" data-rsh="500" data-rsbigimg="../img/paintings/2.jpg" href="../img/paintings/700x500/2.jpg">
Vincent van Gogh - The Starry Night
<img width="96" height="72" class="rsTmb" src="../img/paintings/t/2.jpg">
</a>
</div>
I can create this using string interpolation, but someone suggest me to use Nokogiri. I do not know how I can nest the nodes.
#doc = Nokogiri::HTML::DocumentFragment.parse ""
Nokogiri::HTML::Builder.with(#doc) do |doc|
g.pictures.each do |picture|
doc.create_element "a", :class => "rsImg"
end
end
Is it better to use Nokogiri, or can I also proceed with the easy way (string)? How can I create the nested structure I need?
Update
Done with Nokogiri
#doc = Nokogiri::HTML::DocumentFragment.parse ""
Nokogiri::HTML::Builder.with(#doc) do |doc|
doc.div(:id => 'content-gallery', :class => 'royalSlider rsDefault') {
g.pictures.each do |picture|
doc.a(:src => picture.image_url(:gallery), :class => 'rsImg') {
doc.img(:src => picture.image_url(:widget), :class => 'rsTmb')
}
end
}
end
#doc.to_html
I need to parse an XML file to Ruby objects.
Is there a tool to read attributes from XML like this
report.system_slots.items to return an array of item properties,
or report.system_slots.current_usage to return 'Available'?
Is it possible to do this with Nokogiri?
<page Title="System Slots" H1="Property" H2="Value" __type__="2">
<item Property="System Slot 1">
<item Property="Name" Value="PCI1"/>
<item Property="Type" Value="PCI"/>
<item Property="Data Bus Width" Value="32 bits"/>
<item Property="Current Usage" Value="Available"/>
<item Property="Characteristics">
<item Property="Vcc voltage supported" Value="3.3 V, 5.0 V"/>
<item Property="Shared" Value="No"/>
<item Property="PME Signal" Value="Yes"/>
<item Property="Support Hot Plug" Value="No"/>
<item Property="PCI slot supports SMBus signal" Value="Yes"/>
</item>
</item>
Look at Ox. It reads XML and returns a reasonable Ruby object facsimile of the XML.
require 'ox'
hash = {'foo' => { 'bar' => 'hello world'}}
puts Ox.dump(hash)
pp Ox.parse_obj(Ox.dump(hash))
Dumping that into IRB gives me:
require 'ox'
> hash = {'foo' => { 'bar' => 'hello world'}}
{
"foo" => {
"bar" => "hello world"
}
}
> puts Ox.dump(hash)
<h>
<s>foo</s>
<h>
<s>bar</s>
<s>hello world</s>
</h>
</h>
nil
> pp Ox.parse_obj(Ox.dump(hash))
{"foo"=>{"bar"=>"hello world"}}
{
"foo" => {
"bar" => "hello world"
}
}
That said, your XML sample is broken and won't work with OX. It WILL work with Nokogiri, though there are errors reported, which would hint that you wouldn't be able to parse the DOM correctly.
My question is, why do you want to convert the XML to an object? It is SO much easier to handle XML using a parser like Nokogiri. Using a fixed version of your XML:
require 'nokogiri'
xml = '
<xml>
<page Title="System Slots" H1="Property" H2="Value" __type__="2">
<item Property="System Slot 1"/>
<item Property="Name" Value="PCI1"/>
<item Property="Type" Value="PCI"/>
<item Property="Data Bus Width" Value="32 bits"/>
<item Property="Current Usage" Value="Available"/>
<item Property="Characteristics">
<item Property="Vcc voltage supported" Value="3.3 V, 5.0 V"/>
<item Property="Shared" Value="No"/>
<item Property="PME Signal" Value="Yes"/>
<item Property="Support Hot Plug" Value="No"/>
<item Property="PCI slot supports SMBus signal" Value="Yes"/>
</item>
</page>
</xml>'
doc = Nokogiri::XML(xml)
page = doc.at('page')
page['Title'] # => "System Slots"
page.at('item[#Property="Current Usage"]')['Value'] # => "Available"
item_properties = page.at('item[#Property="Characteristics"]')
item_properties.at('item[#Property="PCI slot supports SMBus signal"]')['Value'] # => "Yes"
Parsing a big XML document into memory can return a labyrinth of arrays and hashes that still have to be peeled apart to access the values you want. Using Nokogiri, you have CSS and XPath accessors which are easy to learn and read; I used CSS above but could easily have used XPath to accomplish the same things.
I have a simple Sinatra app that is configured using the modular style. When I start the app using rackup -p 4567 as recommended in the readme file, the static assets in the public folder are not served. But when I start it using shotgun ./config.ru -p 4567 then they are served. Why does this happen? Could this happen in production?
Here is my code:
# config.ru
require 'rubygems'
require 'bundler'
require 'sinatra'
require 'jammit'
Bundler.require
Jammit.package!
require File.expand_path('./stick.rb')
run Stick
and this is the app ruby file
require 'sinatra/base'
class Stick < Sinatra::Base
get '/' do
haml :index
end
end
Looks like there are two good answers to this one (neither of the existing ones worked for me).
First off, in your config.ru file, you can include the following:
# Replace the directory names to taste
use Rack::Static, :urls => ['/stylesheets', '/javascripts'], :root => 'public'
Alternatively, if you're running your app via rackup, the :static option is set to false by default. You can remedy this by the following incantation:
class MyApp < Sinatra::Base
set :static, true
# ...
end
I had the same problem and i solved like this.
I have added this line in my config.ru .
map "/public" do
run Rack::Directory.new("./public")
end
And i use the static files in my views like this
%link{:type => 'text/css', :rel => 'stylesheet', :href => '/public/css/reset.css'}
%link{:type => 'text/css', :rel => 'stylesheet', :href => '/public/css/text.css'}
%link{:type => 'text/css', :rel => 'stylesheet', :href => '/public/css/960.css'}
%link{:type => 'text/css', :rel => 'stylesheet', :href => '/public/css/app.css'}
Not positive, but you may need to set :root, Stick.root?
(Based on How to deploy a modular Sinatra app to Heroku?)
In order for me to get this working on a new Sinatra app launched via config.ru, I had to do two of the things suggested in the other answers:
class MyApp < Sinatra::Base
set :static, true
set :root, File.dirname(__FILE__)
end
First create a folder named "public" in your sinatra project, then add a couple of folders
stylesheets
javascripts
images
Add your CSS, JS and or JPG,PNG (images) to each folder
Finally as #sirfilip says add below lines to config.ru file
map "/public" do
run Rack::Directory.new("./public")
end
If generic Sinatra (no framework default)
views/layout.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
...
<link rel="stylesheet" href="stylesheets/your_file.css">
<link rel="icon" type="image/ico" href="images/your_image.ico" />
</head>
<body>
<%= yield %>
...
<script src="javascripts/your_js.js"></script>
views/index.erb
<div class="margin-bottom-30">
<div class="row">
<div class="col-md-12">
<ul class="nav nav-pills">
<li class="active">Home <span class="badge">42</span></li>
<li>...</li>
</ul>
</div>
</div>
</div>
All of you images, stylesheets and javascripts will be available for any url registered in your Sinatra app , problem solved!
I'm trying to generate an XML file. I've got some tags that repeat numerically like so:
# necessary XML namespace and metadata stuff...
%img{:src => "Foo002.jpg#full"}/
%img{:src => "Foo003.jpg#full"}/
%img{:src => "Foo004.jpg#full"}/
%img{:src => "Foo005.jpg#full"}/
# and so on for a few hundred lines
%img{:src => "Foo435.jpg#full"}/
I'm given "Foo" and the ending number (435 in this case) as parameters. How do I go about telling HAML to do this?
Thanks
EDIT: Forgot to mention, the leading zeros are important.
- 2.upto(435) do |n|
%img{:src => "Foo%03d.jpg#full" % n}
or
- (2..435).each do |n|
%img{:src => "Foo%03d.jpg#full" % n}
Proof:
phrogz$ haml
!!! XML
%root
- 2.upto(10) do |n|
%img{ src:"Foo%03d.jpg" % n }
^D
<?xml version='1.0' encoding='utf-8' ?>
<root>
<img src='Foo002.jpg' />
<img src='Foo003.jpg' />
<img src='Foo004.jpg' />
<img src='Foo005.jpg' />
<img src='Foo006.jpg' />
<img src='Foo007.jpg' />
<img src='Foo008.jpg' />
<img src='Foo009.jpg' />
<img src='Foo010.jpg' />
</root>