Rails 3 Atom Feed - ruby-on-rails

Trying to create an Atom feed in Rails 3. When I refresh my browser, I see basic XML, not the Atom feed I'm looking for.
class PostsController < ApplicationController
# GET /posts
# GET /posts.xml
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #posts }
format.atom
end
end
index.atom.builder
atom_feed do |feed|
feed.title "twoconsortium feed"
#posts.each do |post|
feed.entry(post) do |entry|
entry.title post.title
entry.content post.text
end
end
end
localhost:3000/posts.atom looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,2005:/posts</id>
<link rel="alternate" type="text/html" href="http://localhost:3000"/>
<link rel="self" type="application/atom+xml" href="http://localhost:3000/posts.atom"/>
<title>my feed</title>
<entry>
<id>tag:localhost,2005:Post/1</id>
<published>2012-03-27T18:26:13Z</published>
<updated>2012-03-27T18:26:13Z</updated>
<link rel="alternate" type="text/html" href="http://localhost:3000/posts/1"/>
<title>First post</title>
<content>good stuff</content>
</entry>
<entry>
<id>tag:localhost,2005:Post/2</id>
<published>2012-03-27T19:51:18Z</published>
<updated>2012-03-27T19:51:18Z</updated>
<link rel="alternate" type="text/html" href="http://localhost:3000/posts/2"/>
<title>Second post</title>
<content>its that second post type stuff</content>
</entry>
</feed>

I ran into this same problem.
First make sure the XML that was generated by your .builder file is a valid Atom XML. You can paste it to the W3c feed validator which will tell you if something is wrong with it. I pasted the XML above and there were some issues, it seems. Once you edit .builder file and make the resulting XML pass. Refresh your page with the valid atom feed.
If you still see plain XML, check in your browser's debugger to see what Response headers you get for the feed. Specifically are you getting Content-Type header? The browser needs it to be some xmlish mime type like 'application/xml' or better yet, 'application/atom+xml'. If you're not getting that Content-Type, or getting the wrong one for some reason, you can override the response header from the headers hash directly in the format call in your controller. Simply add a code block with a typical Atom mime type string:
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #posts }
format.atom { headers["Content-Type"] = 'application/atom+xml; charset=utf-8'}
end

This might help with formatting the feed in XHTML.

Related

Rails: render HTML from Nokogiri without template

I'm trying to write a controller method (show) which renders HTML without using a template (to preview an email without styles, etc):
class EmailDownloadsController < ApplicationController
before_action :set_email_download, only: %i[create show]
def create
send_data(#html, filename: "#{#document.safe_title}.html")
end
def show
render #html.to_s
end
private
def set_email_download
#document = Document.find(params[:id])
#document.parse_email_vars
#html = Nokogiri::HTML(#document.email_campaign_version)
end
end
I can't figure out how to render it without referring to a view (which comes with its own <html> and <head> tags). Anyone have any experience here?
The above code returns this error:
Missing template <!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" style="min-height: 100%; background-color: #f3f3f3;">
...
Ah, it's render inline:.
The render method can do without a view completely, if you're willing to use the :inline option to supply ERB as part of the method call. This is perfectly valid:
render inline: "<% products.each do |p| %><p><%= p.name %></p><% end %>"
Docs.

Convert html response to json

I am trying to implement SMS API in rails, when I hit the API url I get following html response:
<!DOCTYPE RESULT SYSTEM "http: api_link ">
<html><body>
<result reqid="57469">
<mid submitdate="2015-12-02 00:51:55" id="1" tag="null" tid="103335">
</mid>
</result>
</body></html>
How can I convert this to json?
Unfortunately at this time you cannot convert html straight to json, but you can convert html to a hash and then the hash to json.
YOUR_HTML_CODE = '<!DOCTYPE RESULT SYSTEM "http: api_link "><html><body> <result reqid="57469"> <mid submitdate="2015-12-02 00:51:55" id="1" tag="null" tid="103335"> </mid></result></body></html>'
#data = Hash.from_xml(YOUR_HTML_CODE).to_json
Returns:
=> "{\"html\":{\"body\":{\"result\":{\"reqid\":\"57469\",\"mid\":{\"submitdate\":\"2015-12-02 00:51:55\",\"id\":\"1\",\"tag\":\"null\",\"tid\":\"103335\",\"__content__\":\"\\n\\n \"}}}}}"
To find more ways to do what you want, search for rails xml to json, you will find more answers on this question. Crack gem seems to be excellent for this.
Note that if you are using rails you should be handling this on the backend, but that was not as helpful of an answer by itself, thus my answer above.
If your api only returns json you can set format resource.
Example:
config/routes.rb
Rails.application.routes.draw do
resources :posts, defaults: { format: :json }
end
If your api returns html, xml,and json you can set in your controller(remove defaults: { format: :json } in config/routes.rb):
app/controller/posts_controller.rb
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #post }
format.json { render :json => #post }
end

AngularJS Callbacks on Rails

I have noticed that AngularJS requires the results in javascript from the back-end server.
The current server in the example returns angular.callbacks._0({"key": "value"}); with javascript headers. How to make the returns in the same format on Rails? Thanks!
AngularJS generates http://echo.jsontest.com/key/value?callback=angular.callbacks._0 link from that request by default
Here is my working example:
<!DOCTYPE html>
<html ng-app="Simple">
<body>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular-resource.min.js"></script>
<div ng-controller="SimpleController">
{{some_item.key}}
</div>
<script>
angular.module('Simple', ['ngResource']);
function SimpleController($scope, $resource) {
$scope.simple = $resource('http://echo.jsontest.com/key/value',
{callback:'JSON_CALLBACK'},
{get:{method:'JSONP'}}
);
$scope.some_item = $scope.simple.get();
console.log($scope.some_item.key);
}
</script>
</body>
</html>
As long as you have a RESTful controller responding to JSON it will work fine.
class ArticlesController < ApplicationController
respond_to :json
def index
articles = Article.all
respond_with articles
end
def get
article = Article.find(params[:id])
respond_with article
end
# etc.
end
You can limit the attributes returned using respond_with article, include: {:id, :title, :description}

Creating XML with Haml

I'm trying to make a dynamic sitemap for my CMS-style rails app, but I am having trouble creating a sitemap in XML using Haml. I looked at the docs and they say that I should be able to use !!! XML to insert the <?xml version="1.0" encoding="UTF-8"?> tag at the beginning of the document. When I try to do this, it does not render anything at all and I am forced to use a literal meta-xml tag. What am I doing wrong?
content_controller.rb
=====================
class ContentController < ApplicationController
# other methods
def sitemap
#sections = Section.all :include => :pages
respond_to do |format|
format.xml
end
end
end
sitemap.xml.haml
================
<?xml version="1.0" encoding="UTF-8"?>
-# !!! XML
-# the above tag does not work
%urlset{:xmlns => 'http://www.sitemaps.org/schemas/sitemap/0.9'}
%url
%loc= root_url
- #sections.each do |section|
- section.pages.each do |page|
%url
%loc= "#{root_url}#{section.url}/#{page.url}"
%lastmod= page.updated_at
You'll need to set :format => :xhtml in order for this to work.
In your environment.rb
Haml::Template.options[:format] = :xhtml
More info here http://www.mail-archive.com/haml#googlegroups.com/msg06984.html

How to render sitemap.xml in rails app

I have added /views/sitemap/index.xml and want it displayed when i go to the relevant url.
class SitemapController < ApplicationController
def index
respond_to do |format|
format.html
format.xml
end
end
end
And in routes.rb
match "sitemap/" => "sitemap#index"
Using Rails 3
When I go to mydomain.com/sitemap/ I just get a white page. Any ideas?
index.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>http://www.mydomain.com/</loc>
<changefreq>weekly</changefreq>
</url>
</urlset>
Problem is that you are using your index action to render xml and it will render "index.xml"
file not "sitemap.xml" which is what you have created in your views
While your routes are correct, you are using the wrong filename in views
Try renaming sitemap.xml file to index.xml ( in the views/sitemap folder)
If you define name routes, you need to define :format with it
match "/sitemap/sitemap.[:format]", :to => "sitemap#index"
it will pickup your format from there. Also you can define a default format in the routes
match "sitemap/sitemap.xml", :to => "sitemap#index", :defaults => {:format => :xml}
I may be wrong , but I see 2 reasons:
index action doesn't actually do anything judging by this code sample, it just responds back with no info.
you need to render your object as xml - if you don't rails, doesn't know you want xml - it just treats it as another file extension. It actually lets you do little tricks - like sending json to an xml request ( thou I have no idea why would anyone try to do that). Thou one useful application is that you can make rails send custom rendering of an object to a common format or render regular data in common format for an unusual extension ( we had a client who wanted csv data for a .dat request)
Here is a short example, from a sample home controller:
class HomeController < ApplicationController
def index
#m = {
:color => "yellow",
:total => "20"
}
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #m}
end
end
end
this returns this object as xml:
<hash>
<total>20</total>
<color>yellow</color>
</hash>

Resources