Cannot iterate through array in Slim's logic - ruby

I am trying to iterate through an array named #items. I thought by adding it to a class variable and calling it from SLIM I might be able to output the array. What am I doing wrong?
require "rubygems"
require "sinatra"
require "slim"
set :port, 80
get "/" do
slim :index
end
get "/history" do
#items = Dir.entries(File.expand_path(File.dirname(__FILE__)) + "/history").to_a
slim :history
end
__END__
##layout
doctype html
html
head
title Web View
body
div id="main" name="main"
h1 Web View
== yield
##index
h2 Available Options
a href="/history" id="history_view" name="history_view" History
##history
h2 History
- unless items.empty?
- for item in items do
a href="#{item}/output.html" item
- else
p NO ITEMS FOUND

It seems that you've tried to call items method in your 'history' layout. Besides this look at indentation level for your else clause. Try to change your code:
h2 History
- unless #items.empty?
- for item in #items do
a href="#{item}/output.html" item
- else
p NO ITEMS FOUND

Related

Elements in array lose value

I have a strange issue. That values from elements in my array disappear.
The Sinatra part looks like this:
config do
$api = MyWrappr.new
end
get "/"
erb :view, :locals => {:elements => $api.allElements }
end
So what allElements do is first check if there already is a array or not and then it check with the time if the array need to be refreshed.
def allElements
#elements ||= getElements
if Time.now-#time > 60
#elements = getElements
#time = Time.now
end
#elements
end
And #elements is an array with element this looks like this
class Element
attr_accessor :property_1 :property_2
end
Now when I start my application which use thin as server, and I refresh the site fast enough :property_2 just disappear and become nil. Why happen this and how can I fix that?
Oh and if I describe my problem to abstract here is the full project
Well, just the short story I'm a bit stupid.
I have manipulate the object in my view like this:
<div class="title">
<b><%= "#{element.property_1.slice!(0, 24)}" %><%= "..." if (element.property_1.length > 24) %></b>
</div>
And after that there is clear why property_1 is empty.

How do I print XPath value?

I want to print the contents of an XPath node. Here is what I have:
require "mechanize"
agent = Mechanize.new
agent.get("http://store.steampowered.com/promotion/snowglobefaq")
puts agent.xpath("//*[#id='item_52b3985a70d58']/div[4]")
This returns: <main>: undefined method xpath for #<Mechanize:0x2fa18c0> (NoMethodError).
I just started using Mechanize and have no idea what I'm doing, however, I've used Watir and thought this would work but it didn't.
You an use Nokogiri to parse the page after retrieving it. Here is the example code:
m = Mechanize.new
result = m.get("http://google.com")
html = Nokogiri::HTML(result.body)
divs = html.xpath('//div').map { |div| div.content } # here you can do whatever is needed with the divs
# I've mapped their content into an array
There are two things wrong:
The ID doesn't exist on that page. Try this to see the list of tag IDs available:
require "open-uri"
require 'nokogiri'
doc = Nokogiri::HTML(open("http://store.steampowered.com/promotion/snowglobefaq"))
puts doc.search('[id*="item"]').map{ |n| n['id'] }.sort
The correct chain of methods is agent.page.xpath.
Because there is no sample HTML showing exactly which tag you want, we can't help you much.

How do I get the tag name and CSS classes from Nokogiri::HTML

I've been trying to parse these HTML files with Nokogiri. This is the code I was using
require 'nokogiri'
doc = Nokogiri::HTML File.open('usc...html', 'r')
children = doc.css('body div')
children.each do |child|
puts child.name
end
That prints div for all of the child elements even though they are almost entire p, h3 and h4 tags. Can someone explain why that is happening? Also, how do I get the CSS classes off of them?
This:
doc.css('body div')
Will select every div on the page. If you want every element you should use:
doc.css('*')
You can get at the css class with child[:class]

Selectively using yield_content in Padrino application.haml template

In a Haml based Padrino solution I have an application.haml like this:
!!!
%html
%head
%title "blah"
%body
#header
= yield_content :headcontent
#container
...
For :headcontent, in my page (e.g. index.haml) I have
- content_for :headcontent do
#headcontent
%h2= "Index header stuff"
#content
...
What I want to do is make it so that content pages like index.haml can optionally specify - content for :headcontent. That is I want application.haml to contain some default :headcontent that only is rendered if a page does not do - content for :headcontent.
How do I do this?
In your main file, you should be able to use content_for?, like this:
- if content_for?(:headcontent)
= yield_content :headcontent
- else
something else

How do I get an array of check boxes in haml?

I have an array of strings, called #theModels, in a routine implemented as part of a Sinatra server. These models are options for the user to select, and are obtained by the back end (the idea being, as new models are added, then the front end code should not change).
I'm using haml to render html.
How can I enumerate each element in the list of #theModels such that each element is a checkbox? And how can I obtain which checkboxes the user has selected?
I see that just putting
= #theModels
will give me the list of strings contained in #theModels, but without spacing or the like, and certainly not in checkboxes. I've found this question that appears to be similar, but my haml-fu isn't good enough to convert that into what I need.
UPDATE:
These are options associated with a file upload, such that now the code looks like:
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
- #theModelHash.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%input{:type=>"file",:name=>"file"}
%input{:type=>"submit",:value=>"Upload"}
Problem is, that puts a file upload button on each option, instead of at the end. I only want one submit button in the end; should I have two forms that both report their results when the 'Upload' button is pressed?
UPDATE2:
After a moment's thought, the above can be modified to:
Thanks!
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
- #theModelHash.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
%input{:type=>"file",:name=>"file"}
%input{:type=>"submit",:value=>"Upload"}
And that appears to do what I want.
I think you should send the content as an hash instead.
This will give you the opportunity to set initial values in the form.
The hash #params will give you the result.
E.g. {"oranges"=>"1"}
#app.haml
%form{:method => 'post', :action => "/"}
- #models.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%input{:type => :submit, :value => "Save"}
#app.rb
require 'sinatra'
require 'haml'
get '/' do
#models = {"oranges" => true, "bananas" => false}
haml :app
end
post '/' do
#params.inspect
end
The link you provided linked to a rails solution where you have a function returning the proper html.
You can define this function yourself:
Input: key, value
Output: %input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
def check_box(key, value)
...
end
and call it in haml with
=check_box(key,value)

Resources