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}
Related
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.
I'm using PDFKit (along with the Gem render_anywhere and wkhtmltopdf-binary) to create a button for creating PDF's from HTML in Rails. I've followed a couple tutorials that both use 'invoices' as an example. My app uses 'audits'. I thought I'd followed everything to the tee but getting an error on the ActionView::LookupContext object: undefined method 'view_paths=' for #<ActionView::LookupContext:0x00007fdb191d6cc0> Did you mean? view_path. It has something to do with the wrong path and using a service class in Rails but can't seem to find a solution. Here's my code to make the PDF:
The PDFKit Gem: https://github.com/pdfkit/pdfkit
The tutorial I'm using: https://code.tutsplus.com/tutorials/generating-pdfs-from-html-with-rails--cms-22918
The downloads_controller:
class DownloadsController < ApplicationController
def show
respond_to do |format|
format.pdf { send_audit_pdf }
end
end
private
def audit_pdf
audit = params[:incoming]
AuditPdf.new(audit)
end
def send_audit_pdf
send_file audit_pdf.to_pdf,
filename: audit_pdf.filename,
type: "application/pdf",
disposition: "inline"
end
end
The Download Model:
require "render_anywhere"
class Download
include RenderAnywhere
def initialize(audit)
#audit = audit
end
def to_pdf
kit = PDFKit.new(as_html, page_size: 'A4')
kit.to_file("#{Rails.root}/public/audit.pdf")
end
def filename
"audit #{audit.id}.pdf"
end
private
attr_reader :audit
def as_html
render template: "audits/pdf", layout: "audit_pdf", locals: { audit: audit }
end
end
My views/layout/audit_pdf.html.erb looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Audit PDF</title>
<style>
<%= Rails.application.assets.find_asset('audit.pdf').to_s %>
</style>
</head>
<body>
<%= yield %>
</body>
</html>
Since you are using rails api only, you are facing this issue.
You need to change
def as_html
render template: "audits/pdf", layout: "audit_pdf", locals: { audit: audit }
end
to:
def pdf_html
ActionController::Base.new.render_to_string(template: 'audits/pdf.html.erb', layout: 'audit_pdf.erb')
end
This question already has answers here:
Rails 3.2 `link_to` (in email) with `method: :put` still producing GET request
(2 answers)
Closed 6 years ago.
I have a rails 5 app (API mode). I'm bootstrapping a flag comment feature. I've added a flagged attribute and a disabled attribute to my comment table (because I don't want to completely destroy comments, just to hide them on the front when disabled is true).
When a comment is flagged, I send an email (through ActionMailer) to myself with the comment, some meta data about it, and a link to update the disabled attribute to true.
My problem is that when I click this link on my mail, it doesn't update the attribute.
Here is the code to make it clear:
routes.rb:
resources :comments, only: [:create, :update] do
member do
post 'flag'
end
end
controllers/api/v1/comments_controller.rb:
def update
#comment = Comment.find(params[:id])
new_status = #comment.disabled ? false : true
# binding.pry => I'm not even reaching that method
if #comment.update(disabled: new_status)
CommentDisabledMailer.send_comment_disabled_confirmation(#comment).deliver_now
redirect_to "https://media.giphy.com/media/YfGkjrnVIk3jq/giphy.gif" # a funny gif url
else
render json: { errors: #comment.errors.messages }, status: :unprocessable_entity
end
end
def flag
#comment.update(flagged: #comment.flagged + 1)
render json: #comment, serializer: Api::V1::CommentSerializer, status: 201, root: nil
FlagMailer.send_flag_mail(#comment).deliver_now
end
views/flag_mailer/send_flag_mail.html.erb:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<!-- some meta data about my comment -->
<h2> <%= link_to "Disabled this comment", api_v1_comment_url(#comment), method: :put, action: :update %> </h2>
</body>
</html>
I receive the mail when I flag the comment through postman, the flagged attribute is updated, but when I click on "Disable this comment" on the mail, it opens a new window with a rails error:
No route matches [GET] "/api/v1/comments/5", the disabled attribute of the comment is not updated and I obviously don't receive the mail that should confirm that the comment has been disabled (cf the update method in the controller).
Am I missing something ?
You can try this
Disabled this comment
I am stuck at what I think is a very simple/common usecase in a Rails web application. I want to use "caches_action, layout:false" and display, from the layout, dynamic tags that will be set by the action (either from the view or the controller).
I could not find any standard rails way to do this as content_for does not work with caches_action, instance variables are not cached (?), and the metatags helper gems that I have tried (metamagic and meta-tags) do not support this usecase.
Is there any way to do this ?
Example
I am using caches_action, layout:false on a SandboxController#show method
#app/controllers/sandbox_controller.rb
class SandboxController < ApplicationController
caches_action :show, layout: false, expires_in: 1.minute
def show
#meta_title = "Best page ever"
do_some_expensive_operation
end
end
The view
#app/views/sandbox/show.html.erb
We are in show action.
The layout
#app/views/layouts/application.html.erb
<title><%= #meta_title %></title>
Debug: <%= #meta_title %> <br/>
<%= yield %>
Thanks !
I found a way to make it work, it's not as pretty as I would like it to be but it helps using caches_action and setting HTML meta tags from the view.
Also, for the record, it seems that this was forgotten and buried deep down in the pipeline, as I did not find any recent mentions of this problem, only that caches_action and content_for together are not expected to work.
Solution: I simply add a before_action to set the meta tags by using as less computation as possible.
#app/controllers/sandbox_controller.rb
class SandboxController < ApplicationController
caches_action :show, layout: false, expires_in: 1.minute
before_action :seo_show, only: :show
def seo_show
#meta_title = "Best page ever"
end
def show
do_some_expensive_operation
end
end
It's worth noting that it can be used in combination with metamagic gem too.
Layout:
#app/views/layouts/application.html.erb
<%= default_meta_tags && metamagic %>
<%= yield %>
And helper:
#app/helpers/application_helper.rb
module ApplicationHelper
def default_meta_tags
meta title: #meta_title || "Default meta-title of my website"
end
end
Hope this helps someone out there !
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.