What can I do to get the return value from a %def? - mako

How do I get the return value from a %def?
makoT1.py:
import mako
from mako.template import Template
from mako.lookup import TemplateLookup
print "Hi world.",
mytemplate = Template(filename='makoT1.mako')
print mytemplate.render(),
makoT1.mako
<%
index = 0
%>
<%def name="a_def(counter)"> Pre: ${counter} <% counter += 1 %> Post: ${counter} <% return counter %> </%def>
index: ${index}
${a_def(index)}
index: ${index}
dalem#QnD:~$ python makoT1.py
Hi world.
index: 0
Pre: 0 Post: 1 1
index: 0
Notice that the second "index," above is still 0? That's what I'm trying to fix. I'd like it to increment.
Perhaps something like this for makoT1.mako:
<%
index = 0
%>
<%def name="a_def(counter)">
Pre: ${counter}
<% counter += 1 %>
Post: ${counter}
<% return counter %>
</%def>
index: ${index}
<% index = ${a_def(index)} %>
index: ${index}
But that gets me this error:
dalem#QnD:~$ python makoT1.py
Hi world.
Traceback (most recent call last):
File "makoT1.py", line 5, in <module>
mytemplate = Template(filename='makoT1.mako')
File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 291, in __init__
module = self._compile_from_file(path, filename)
File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 368, in _compile_from_file
filename)
File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 615, in _compile_text
generate_magic_comment=template.disable_unicode)
File "/usr/local/lib/python2.7/dist-packages/mako/template.py", line 597, in _compile
node = lexer.parse()
File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 241, in parse
if self.match_python_block():
File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 376, in match_python_block
match.group(1)=='!', lineno=line, pos=pos)
File "/usr/local/lib/python2.7/dist-packages/mako/lexer.py", line 131, in append_node
node = nodecls(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/mako/parsetree.py", line 139, in __init__
self.code = ast.PythonCode(text, **self.exception_kwargs)
File "/usr/local/lib/python2.7/dist-packages/mako/ast.py", line 37, in __init__
expr = pyparser.parse(code.lstrip(), "exec", **exception_kwargs)
File "/usr/local/lib/python2.7/dist-packages/mako/pyparser.py", line 60, in parse
), **exception_kwargs)
mako.exceptions.SyntaxException: (SyntaxError) invalid syntax (<unknown>, line 1) (u'index = ${a_def(index)} \n') in file 'makoT1.mako' at line: 11 char: 1
It seems odd to me that line 11 would get the SyntaxError when this works fine for line 11:
<% index = 0 %>
Shouldn't ${a_def(index)} return the integer from a_def(counter)?

Use
<% index = a_def(index) %>
don't use
<% index = ${a_def(index)} %>
or
<% index = ${capture(a_def(index))} %>

Related

Select specific key from hash in Ruby

I have the following JSON which I convert to hash:
<%
json = '{
"speed": 50,
"braking": 50,
"time_on_task": 50
}'
json = JSON.parse(json)
%>
And currently I just loop through them and display them:
<ul>
<% json.each do |t| %>
<li><%= "<b>#{t.first.humanize}</b>: #{t.last}".html_safe %></li>
<% end %>
</ul>
However I'd like to build a method that can pick an particular item by its key name. e.g. show_score(json, 'speed')
I tried:
def show_score(hash, key)
hash.select { |k| k == key }
end
Which just returns: {"speed"=>50}
So I tried:
hash.select { |k, h| "<b>#{k.humanize}</b>: #{h}".html_safe if k == key }
But it returns the same...
How can I get to just return the string in the format I want if they key matches?
def show_score(hash, key)
"<b>#{key.humanize}</b>: #{hash[key]}"
end
And I'd change this
<%
json = '{
"speed": 50,
"braking": 50,
"time_on_task": 50
}'
json = JSON.parse(json)
%>
into
<%
hash = {
"speed" => 50,
"braking" => 50,
"time_on_task" => 50
}
json = hash.to_json
%>
I think you're thinking too hard, or maybe I'm not understanding your question fully.
<ul>
<% json.each do |k,v| %>
<li><%= "<b>#{k.humanize}</b>: #{v}".html_safe %></li>
<% end %>
</ul>
ps. using Enumerable#detect is so much faster than Enumerable#select.first

undefined method `[]' for nil:NilClass while importing csv file in rails

I have an application on which I want to provide the feature to import the records from CSV and Excel file formats. I am using roo gem for it, but at the time of importing it gives the error "undefined method `[]' for nil:NilClass".
Here is the code :
student.rb :
require 'roo'
def self.import(file)
spreadsheet = open_spreadsheet(file)
header = spreadsheet.row(1)
(2..spreadsheet.last_row).each do |i|
row = Hash[[header, spreadsheet.row(i)].transpose]
product = find_by_id(row["id"]) || new
product.attributes = row.to_hash.slice(*accessible_attributes)
product.save!
end
end
def self.open_spreadsheet(file)
case File.extname(file.original_filename)
when ".csv" then Roo::CSV.new(file.path, nil, :ignore)
when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
when ".xlsx" then Roo::Excelx.new(file.path, nil, :ignore)
else raise "Unknown file type: #{file.original_filename}"
end
end
student_controller.rb :
def import
Student.import(params[:file])
redirect_to students_path, notice: "Record imported Successfully."
end
new.html.erb :
<%= form_tag import_students_path, multipart: true do %>
<%= file_field_tag :file , :required=> true%> <br/>
<%= submit_tag "Import" , :class => "btn btn-primary btn-block" %>
<% end %>
Tell me what i am doing wrong?

Odd rendering of an html table in Ruby on Rails when using content_tag

I'm trying to build a table in Ruby on Rails with the help of the content_tag method.
When I run this:
def itemSemanticDifferential(method, options = {})
if options[:surveyQuestion].any? then
#template.content_tag(:tr) do
#template.content_tag(:td, options[:surveyQuestion], :colspan => 3)
end
end
#template.content_tag(:tr) do
#template.content_tag(:th, options[:argument0])
end
end
Only the second part gets rendered:
#template.content_tag(:tr) do
#template.content_tag(:th, options[:argument0])
end
Can anyone tell me why this is?
Ruby Rails returns the last variable it used if no return is explicitly called.
( example: )
def some_method(*args)
a = 12
b = "Testing a String"
# ...
3
end # This method will return the Integer 3 because it was the last "thing" used in the method
Use an Array to return all the content_tag (WARNING: this method will return an Array, not a content_tag as you expect, you'll need to loop on it):
def itemSemanticDifferential(method, options = {})
results = []
if options[:surveyQuestion].any? then
results << #template.content_tag(:tr) do
#template.content_tag(:td, options[:surveyQuestion], :colspan => 3)
end
end
results << #template.content_tag(:tr) do
#template.content_tag(:th, options[:argument0])
end
return results # you don't actually need the return word here, but it makes it more readable
end
As asked by author of the Question, You need to loop on the result because it is an array of content_tags. Also, you need to use .html_safe to output the content_tags as HTML (not strings).
<% f.itemSemanticDifferential(:method, options = {}).each do |row| %>
<%= row.html_safe %>
<% end %>

Validations for Importing CSV data into MySql database in Rails 3.1?

i implemented the task of importing data from csv into MySQL database successfully. Now, my requirement is: i need to get error message with line number, if there is any mis match of data in csv file while importing.
This is my controller code:
**require 'csv' #at the top and followed by...
def load_csv
# no code
end
def import_csv
parsed_file = CSV.foreach(params[:csv].tempfile,:headers => true) do |row|
row = row.to_hash.with_indifferent_access
Institute.create!(row.to_hash.symbolize_keys)
redirect_to :action => :index
end
In my view/ load_csv.html.erb:
<%= form_for(:institute, :url => import_csv_institutes_path, :html => {:multipart => true}) do |f| %>
<div class="field">
<%= file_field_tag :csv %>
<%= f.submit 'Import' %>
</div>
<% end %>
These are the only two steps i used for importing. Model validations are working only for form and for csv, an error page displayed..
Please try to help me out.........................
Assign an error message to the flash[:notice] variable in the import_csv method. Do it before redirect.
http://guides.rubyonrails.org/action_controller_overview.html

Ruby on Rails: a weird no method error in my controller?

Here's what I got in my logs:
Started POST "/video_votes.437?type=up" for 127.0.0.1 at Fri Mar 18 01:11:14 -0700 2011
Processing by VideoVotesController#create as
Parameters: {"authenticity_token"=>"DLyDcc4MJxK7gk4URiyyjvsLLl9hjtDChAyQRGVawKg=", "type"=>"up"}
Completed in 83ms
NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]):
app/controllers/video_votes_controller.rb:3:in `create'
I get this error when I click the button that calls on the create method.
Here's the code in my create method (note that line three is the #video = Video.find(params[:video_vote][:video_id]) line):
def create
#video = Video.find(params[:video_vote][:video_id])
#vote = #video.video_votes.new
if params[:type] = "up"
#vote.value = 1
else
#vote.value = -1
end
if #vote.save
respond_to do |format|
format.html { redirect_to #video }
format.js
end
else
respond_to do |format|
format.html { redirect_to #video }
format.js {render 'fail_create.js.erb'}
end
end
And here's my code for the button in my view that calls the create method:
<div id='voting_div'>
<%= button_to "+1", video_votes_path(video, :type=> "up"), :remote => true %>
<div id='vote_display'>
<p id='votes'><%= pluralize video.vote_sum, 'Votes' %></p>
</div>
<%= button_to "-1", video_votes_path(video, :type=> "down"), :remote => true %>
</div>
What's going on here? How do I fix this error?
You params hash is
{"authenticity_token"=>"DLyDcc4MJxK7gk4URiyyjvsLLl9hjtDChAyQRGVawKg=", "type"=>"up"}
In this hash there is no key called "video_vote" , so when you try to access params[:video_vote][:video_id], because params[:video_vote] is nil. it will throw this error.
Check your routes or if you need to "GET" more values with the button, because your params hash doesn't know about the "video_vote" key.