Phoenix.Template.UndefinedError at GET /api/todos Could not render "index.json" - phoenix-framework

Problem
localhost:4000/api/todos shows an error
Phoenix.Template.UndefinedError at GET /api/todos
Could not render "index.json"
Code
todo_view.ex
defmodule TodoApiWeb.TodoView do
use TodoApiWeb, :view
alias TodoApiWeb.TodoView
def render('index.json', %{todos: todos}) do
render_many(todos, TodoView, "todo.json")
end
def render('todo.json', %{todo: todo}) do
%{
id: todo.id,
}
end
end

To fix the above issue convert the single quotes to double quotes.
Reload the localhost:4000/api/todos to see the json correctly load.

Related

How to insert data in the table without substituting the variable?

I have a rake file that create a lot of items.
namespace :db do
namespace :seed do
desc "items table"
task :items=> :environment do
Item.create(name: "first_name", process: "clean the item #{test} then pack and send to #{location}")
................................................
end
end
end
when i do rake db:seed:items I am not able to insert this data in the table without substituting the variable. Is there a way to insert this data without variable substitution so that i can substitute the variable later?
If you want to defer interpolation to a later time and still use the Ruby string interpolation notation, you can do this:
string = 'clean the item #{test} then pack and send to #{location}'
values = {
test: "paperclip",
location: "head office"
}
string.gsub(/\#\{([^}]+)\}/) do
values[$1.to_sym]
end
# => "clean the item paperclip then pack and send to head office"
You can even wrap this up into a simple method:
def interpolate(string, values)
string.gsub(/\#\{([^}]+)\}/) do
values[$1.to_sym]
end
end
Which, if you wanted to be a bit bold, you could patch into String:
class String
def interpolate(values)
self.gsub(/\#\{([^}]+)\}/) do
values[$1.to_sym]
end
end
end
Note that this only does the most basic interpolation of things like #{x} and not #{x.method_call} or #{x+1} or even #{x[y]}. For that you may need to go with a more arbitrary code evaluation method, but that road is paved with danger.

Insert HAML into a Sinatra helper

I'm writing a helper for a small Sinatra app that prints some gaming cards stored as hash in an array.
Every card has this structure:
{ card: 'Ace', suit: :spades, value: 11 }
and the filename of the card image is "spades_11.jpg".
I'm writing a helper to display the cards in my view:
def view(hand)
hand.each do |card|
#print the card
end
end
I need an output like this:
.span2
%img(src="/images/#{card[:suite]}_#{card[:value]}")
How can I insert my Haml code inside the helper block keeping the indentation?
The simplest solution would be to just return the HTML directly from your helper as a string:
def view(hand)
hand.map do |card|
"<div class='span2'><img src='/images/#{card[:suite]}_#{card[:value]}'></div>"
end.join
end
The call it from your Haml with something like:
= view(#the_hand)
You could make use of the haml_tag helper which would let you write something like:
def view(hand)
hand.each do |card|
haml_tag '.span2' do
haml_tag :img, 'src' => "/images/#{card[:suite]}_#{card[:value]}"
end
end
end
Note that haml_tag writes directly to the output rather than returning a string, so you would have to use it with - rather than =:
- view(#the_hand)
or use capture_haml.
This method means your helper depends on Haml. The first method would be usable whatever template language you used, but wouldn’t respect settings like format for whether to end the img tag with />.
If you want to use pure Haml for the markup for each card (this example is simple enough to get away with helpers, but you would certainly want to do this for more complex sections) you could use a partial. Add you Haml code to a file named e.g. view.haml, then you can render it from the containing template, passing in the hand as a local variable:
view.haml:
- hand.each do |card|
.span2
%img(src="/images/#{card[:suite]}_#{card[:value]}")
Parent template:
= haml :view, :locals => {:hand => #the_hand}
You should be able to use a here doc
def view(hand)
hand.each do |card|
<<-HAML
.span2
%img(src="/images/#{card[:suite]}_#{card[:value]}")
HAML
end
end
but note that here docs take the whitespace from the start of the line the are on, so unfortunately this will make your indentation somewhat ugly.
For anything more complicated it probably makes sense to write your haml in a separate .haml file.

How to handle NILs with Anemone / Nokogiri web scraper?

def scrape!(url)
Anemone.crawl(url) do |anemone|
anemone.on_pages_like %[/events/detail/.*] do |page|
show = {
headliner: page.doc.at_css('h1.summary').text,
openers: page.doc.at_css('.details h2').text
}
puts show
end
end
end
Writing a scraper in Anemone, which uses Nokogiri under the hood..
Sometime the selector .details h2'returns nothing because its not in the HTML, and calling text on it throws an exception.
I'd like to avoid if/elses all over the place...
if page.doc.at_css('.details h2').empty?
openers: page.doc.at_css('.details h2').text
end
Is there any more eloquent way of handling errors produced by inconsistant mark up? For instance CoffeeScript has the existentional operator person.name?.first(). If the HTML has the element, great make the object and call text on it. If not, move on and dont add it to the hash.
You just need do:
anemone.on_pages_like %[/events/detail/.*] do |page|
if not page.nil?
...#your code
end
end

How do I post/upload multiple files at once using HttpClient?

def test_post_with_file filename = 'test01.xml'
File.open(filename) do |file|
response = #http_client.post(url, {'documents'=>file})
end
end
How do I modify the above method to handle a multi-file-array post/upload?
file_array = ['test01.xml', 'test02.xml']
You mean like this?
def test_post_with_file(file_array=[])
file_array.each do |filename|
File.open(filename) do |file|
response = #http_client.post(url, {'documents'=>file})
end
end
end
I was having the same problem and finally figured out how to do it:
def test_post_with_file(file_array)
form = file_array.map { |n| ['documents[]', File.open(n)] }
response = #http_client.post(#url, form)
end
You can see in the docs how to pass multiple values: http://rubydoc.info/gems/httpclient/HTTPClient#post_content-instance_method .
In the "body" row, I tried without success to use the 4th example. Somehow HttpClient just decides to apply .to_s to each hash in the array.
Then I tried the 2nd solution and it wouldn't work either because only the last value is kept by the server. But I discovered after some tinkering that the second solution works if the parameter name includes the square brackets to indicate there are mutiple values as an array.
Maybe this is a bug in Sinatra (that's what I'm using), maybe the handling of such data is implementation-dependent, maybe the HttpClient doc is outdated/wrong. Or a combination of these.

Rails 3 and html_safe confusion (allow pictures (smiles) in chat but deny everything else)

I have here is a module that replaces the smilies (like ":-)") as icons:
module Smileize
PATH = "/images/smiles"
SMILES = [/\;\-?p/i, /\$\-?\)/, /8\-?\)/, /\>\:\-?\(/, /\:\-?\*/, /\:\-?o/i, /\:\-?c/i, /\;\-?\)/,
/\:\-?s/i, /\:\-?\|/, /\:\-?p/i, /\:\-?D/i, /\:\-?\?/, /\:\-?\(/, /\:\-?\)/]
def to_icon(key)
return "<img class='smiley' src='#{PATH}/smile#{SMILES.index(key) + 1}.png'/>"
end
module_function :to_icon
end
class String
def to_smile
Smileize::SMILES.each do |smile|
if self =~ smile
self.gsub!(smile, Smileize.to_icon(smile))
end
end
self
end
end
So pictures show that I'm using html_safe, like this:
<%= #message.text.to_smile.html_safe %>
But it does not suit me, because but pictures will be displayed and other tags, too.
My question is: how to display only my smile, ignoring the other tags?
I think you'll need to do it like this:
HTML encode the string.
Perform your substitution.
Mark the final result as HTML safe.
Add a helper something like this:
def expand_smilies(s)
s = ERB::Util::html_escape(s)
Smileize::SMILES.each do |smile|
s.gsub!(smile, Smileize.to_icon(smile))
end
s.html_safe
end
And then in your ERB:
<%= expand_smilies some_text %>
ERB uses ERB::Util::html_escape to encode HTML so using it yourself makes sense if you're targeting ERB. Calling html_safe on a string returns you something that ERB will leave alone when it is HTML encoding things.
Note that there is no usable html_safe! on strings and html_safe returns an ActiveSupport::SafeBuffer rather than a String so you'll have to use a helper rather than monkey patching a new method into String. ActiveSupport does patch an html_safe! method into String but all it does is raise an exception saying "don't do that":
def html_safe!
raise "You can't call html_safe! on a String"
end

Resources