Sinatra dynamic template name - ruby

I just started checking out sinatra for a project, and I started playing around with HAML.
However, I've run in to an issue -- I have a path with a splat that needs to point to an HAML file with a name the same as the text splatted out of the url, however, any string passed to the [haml] template method is treated as an inline template, and not a filename.
There is no documentation that would suggest there is a way to do this. The only solution I can think of is reading to full text of the necessary template file and passing it to the HAML function; however, such a solution is incredibly cumbersome.
Example
get '/stpl/*.haml' do |page|
haml page # <--- `page' is treated as an inline template
end
Whilst this functionality is expected when one reads the documentation, there is no other means, it would seem, to accomplish what I need.

If you pass a symbol to haml, it will look in views for the matching file, so you can do this instead:
get '/stpl/*.haml' do |page|
haml page.to_sym # attempts to get views/<page>.haml
end

Related

Chef - if node.name is in template list, tag server

We have an issue where we don't have admin privileges to tag servers simply with knife. How would I tell Chef to read the template and if the template includes the node.name of the server to tag it.
I know I can tag servers with tag('tagnamehere') But the code surrounding that... I don't know if that will work. Or if "Template.readlines" is a search function instead of "File.readlines".
if Template.readlines('template1.erb').grep(/#{node.name}/).any?
tag('mytag')
end
Not sure how to accomplish this feat. But trying very hard to understand as an Ops person.
If I understand it correctly reading the static template erb file and you are looking for #{node.name} variable used or not.
In this case solution would be skipping string interpolation by using \ in grep
if Template.readlines('template1.erb').grep(/\#{node.name}/).any?
tag('mytag')
end

Convert erb ruby code to slim template

Below is an erb ruby code which is want to convert in slim template
<div class="star-rating" data-score= <%= review.rating%> ></div>
In above template i am confused as there are two equals to sign
online converter is giving something like this
.star-rating data-score="<haml_loud" review.rating >
But its not working
This will work for you:
.star-rating data-score=review.rating
Since you're (apparently) using Slim, not Haml, you don't need haml_loud at all.
<%= ... > in Erb means to evaluate the expression inside, and include the result in the outer context. Thus if the rating would be 99, then data-score=99 would become part of the html. That is fine.
The generated output seems wrong. The trailing > should be inside a string, just as the opening counterpart "<haml_loud. And as jeffdill2 correctly pointed out, there is no need to use haml_loud. Just use:
.star-rating data-score=review.rating

writing a short script to process markdown links and handling multiple scans

I'd like to process just links written in markdown. I've looked at redcarpet which I'd be ok with using but I really want to support just links and it doesn't look like you can use it that way. So I think I'm going to write a little method using regex but....
assuming I have something like this:
str="here is my thing [hope](http://www.github.com) and after [hxxx](http://www.some.com)"
tmp=str.scan(/\[.*\]\(.*\)/)
or if there is some way I could just gsub in place [hope](http://www.github.com) -> <a href='http://www.github.com'>hope</a>
How would I get an array of the matched phrases? I was thinking once I get an array, I could just do a replace on the original string. Are there better / easier ways of achieving the same result?
I would actually stick with redcarpet. It includes a StripDown render class that will eliminate any markdown markup (essentially, rendering markdown as plain text). You can subclass it to reactivate the link method:
require 'redcarpet'
require 'redcarpet/render_strip'
module Redcarpet
module Render
class LinksOnly < StripDown
def link(link, title, content)
%{#{content}}
end
end
end
end
str="here is my thing [hope](http://www.github.com) and after [hxxx](http://www.some.com)"
md = Redcarpet::Markdown.new(Redcarpet::Render::LinksOnly)
puts md.render(str)
# => here is my thing hope and ...
This has the added benefits of being able to easily implement a few additional tags (say, if you decide you want paragraph tags to be inserted for line breaks).
You could just do a replace.
Match this:
\[([^[]\n]+)\]\(([^()[]\s"'<>]+)\)
Replace with:
\1
In Ruby it should be something like:
str.gsub(/\[([^[]\n]+)\]\(([^()[]\s"'<>]+)\)/, '\1')

How to build an Object from XML, modify, then write to File in Ruby

I'm having an awful time trying to use a library to parse an XML File into a hash like object, modify it, then print it back out to another XML file in Ruby. For a class I'm taking, we're supposed to use a Java JAXB like library where we convert XML into an object. We've already done SAX and DOM methods so we can't use those methods of XML de-serialization. Nokogiri helped me with both of these in Ruby.
The only problem is that besides the SIMPLE modifications I'm making to the objects, when I write to file it has drastic differences. Is there a Ruby library meant for doing just this? I've tried: ROXML, XML::Mapping, and ActiveSupport::CoreExt. The only one I can get to even run is ActiveSupport, and even then it starts putting element attributes as child elements in the output XML.
I'm willing to try out XmlSimple, but I'm curious has anyone actually had to do this before/run into the same problems? Again, I can't read in lines one at a time like SAX or build a Tree like structure like DOM, it needs to be a hash like object.
Any help is much appreciated!
You should have a look into nokogiri: http://nokogiri.org/
Then you can parse the XML like this :
xml_file = "some_path"
#xml = Nokogiri::XML(File.open xml_file)
#xml.xpath('//listing').each do |node|
style = node.search("style").text
end
With Xpath, you can perform queries in the XML :
#xml.xpath("//listing[name='John']").first(10)
OK, I got it working. After looking at ActiveSupport::CoreExt 's source code I found it just uses a gem called xml-simple. What's obnoxious is the gem, library name in the require statement, and class name are a mixture of hyphenated and non hyphenated spellings. For future reference here's what I did:
# gem install xml-simple
# ^ all lowercase, hyphenated
require 'xmlsimple'
# ^ all lowercase, not hyphenated
doc = XmlSimple.xml_in 'hw3.xml', 'KeepRoot' => true
# ^ Camel cased (it's a class), not hyphenated
# doc.class => Hash
# manipulate doc as a hash
file = File.new('HW3a.xml', 'w')
file.write("<?xml version='1.0' encoding='utf-8'?>\n")
file.write(XmlSimple.xml_out doc, 'KeepRoot' => true)
I hope this helps someone. Also make sure you pay attention to case and hyphens with this gem!!!

Issues with Sinatra and Heroku

So I've created and published a Sinatra app to Heroku without any issues. I've even tested it locally with rackup to make sure it functions fine. There are a series of API calls to various places after a zip code is consumed from the URL, but Heroku just wants to tell me there is an server error.
I've added an error page that tries to give me more description, however, it tells me it can't perform a `count' for #, which I assume means hash. Here's the code that I think it's trying to execute...
if weather_doc.root.elements["weather"].children.count > 1
curr_temp = weather_doc.root.elements["weather/current_conditions/temp_f"].attributes["data"]
else
raise error(404, "Not A Valid Zip Code!")
end
If anyone wants to bang on it, it can be reached at, http://quiet-journey-14.heroku.com/ , but there's not much to be had.
Hash doesn't have a count method. It has a length method. If # really does refer to a hash object, then the problem is that you're calling a method that doesn't exist.
That # doesn't refer to Hash, it's the first character of #<Array:0x2b2080a3e028>. The part between the < and > is not shown in browsers (hiding the tags themselves), but visible with View Source.
Your real problem is not related to Ruby though, but to your navigation in the HTML or XML document (via DOM). Your statement
weather_doc.root.elements["weather"].children.count > 1
navigates the HTML/XML document, selecting the 'weather' elements, and (tries to) count the children. The result of the children call does not have a method count. Use length instead.
BTW, are you sure that the document contains a tag <weather>? Because that's what your're trying to select.
If you want to see what's behind #, try
raise probably_hash.class.to_s

Resources