Simple search form for my blog with ruby and sinatra - ruby

I'm using sequel.
In my app.rb, I wrote
get '/search' do
#post = Post.find(:Title => "%#{params[:query]}%")
erb :'layout'
end
Layout.erb
<form action="/search" method="get">
<input type="text" name="query"/><br />
<input type="submit" />
</form>
<% if #results %>
<table>
<%#results.each do |r|%>
<tr valign="top">
<td><%=r.title%></td>
</tr>
<%end%>
</table>
<% end %>
And to the blog_model.rb in post class this:
def self.search(query)
#where(:title, query) -> This would return an exact match of the query
where("title like ?", "%#{query}%")
end
And I'm getting this :LocalJumpError at /search
no block given (yield).
So what to do or have I done this code correctly ? Thanks in advance.

I guess the problem is the name of erb file, layout.erb.
Sinatra always search for a layout.erb, if you not explicit indicate other layout file, that will handle the page template. This file has the form:
<!doctype html>
<html>
<head>
...
<body>
...
<%= yield %> insert the content here
...
</html>
There are two solutions:
Rename the layout.erb file.
Replace the erb call by: erb :layout, layout: false

Related

How to print to web page using Ruby and Sinatra

I'm calling a ruby function in a post method and I'm trying to output the contents from the function to the web page but it prints the output in my console instead. How do I get it to print to the page?
I've tried
<%=rsg(params[:grammar_file])%> inside an erb file
and
rsg(params[:grammar_file])
inside of the post method and both just print to the console
require 'sinatra'
require 'sinatra/reloader' if development? #gem install sinatra-contrib
require './rsg.rb'
enable :sessions
get '/' do
erb :index
end
post '/' do
rsg(params[:grammar_file])
erb :index
end
<% title = "RANDOM SENTENCE GENERATOR" %>
<!doctype html>
<html lang="en">
<head>
<title><%= #title || "RSG" %></title>
<meta charset="UTF8">
</head>
<body>
<h1>RubyRSG Demo</h1>
<p>Select grammar file to create randomly generated sentence</p>
<form action="/" method="post">
<select name="grammar_file">
<option value="Select" hidden>Select</option>
<option value="Poem">Poem</option>
<option value="Insult">Insult</option>
<option value="Extension-request">Extension-request</option>
<option value="Bond-movie">Bond-movie</option>
</select>
<br><br>
<input type="submit" value="submit">
</form>
<section>
<p>Here</p>
<p><%= rsg(params[:grammar_file])%></p>
</section>
</body>
</html>
You need to tell your template what to do with the params.
This is what is happening:
post '/' do
rsg(params[:grammar_file])
# your rsg method produces some output. I guess you have a line the `puts` your params to stdout somewhere. Instead you should redirect the output into the template.
erb :index
end
Like this:
post '/' do
erb :index, :locals => {:rsg => rsg(params[:grammar_file])}
end
Then, in your :index template you have a line like:
<%=rsg%>
To output the generated String.
The problem might also be that you're tryng to return a puts statement instead of the plain string:
def rsg(p)
puts "I love my daily #{p}. Good luck to you"
end
This will just print to the console and nothing else (true to be precise)
Better:
def rsg(p)
"I love my daily #{p}. Good luck to you"
end
Here you will just return the String from your method and calling rsg("sandwich") will return:
# => "I love my daily sandwich. Good luck to you"

Sinatra / Rails : How to pass user input between views

I've been looking for a bit and can't find or rather very well understand what to do, I'm sure its quite simple I'm just very new to Ruby and web apps, this one is in Sinatra for simplicity. I'd like to pass the #multiplication_table variable as well as the things the user puts into the inputs to the next results page so I can see if they put in the answers correctly but dont know how to, I think I know how to do this with a form_for but I dont know how to do that with already having a for loop.
This is my web.rb file
# web.rb
require 'sinatra'
def create_table(number)
possibles = [1,2,3,4,5,6,7,8,9,10,11,12]
int_set = possibles.shuffle
result = []
#answer_list = []
while int_set.length > 0
random_int = int_set[0]
string = (number.to_s + " x " + random_int.to_s)
int_set.delete(random_int)
if (random_int.to_s).length == 1
string += " = ______"
else
string += " = ______"
end
result << string
#answer_list << random_int.to_i * number.to_i
end
return result
end
get '/' do
#greeting = "Hi! Enter a number to generate a quick test."
erb :index
end
post '/results' do
erb :results
#multiplication_table
end
post '/' do
#multiplication_table = create_table(params[:int_to_generate])
#answers = #answer_list
erb :multiplication_table_page
end
and this is my multiplication_table_page.erb
<!-- multiplication_table_page.erb -->
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.3/css/bootstrap.min.css">
</head>
<style>
h1 {text-align:center;}
p {text-align:center;}
.form-group {float: right; width: 100%;}
input {float: right;}
#submitall{width:100%;}
</style>
<body>
<div class="container">
<h1>Here is your table! Good luck.</h1>
<form action ="/results" method="POST" class="form-inline">
<% counter = 0 %>
<% #multiplication_table.each do |equation| %>
<input type="text" name = <%= "user_answer" + counter.to_s %> class="form-control">
<h2> <%= equation %> </h2>
<% counter += 1 %>
<% end %>
<p> </p>
<input id=submitall type="submit" class = "btn btn-primary">
</form>
<p> </p>
<p>Put another number in for another table</p>
<form action ="/" method="POST" class="form-inline">
<div class = "form-group">
<input type="submit" class = "btn btn-primary">
<input type="text" name ="int_to_generate" class="form-control">
</div>
</form>
<% #answers.each do |answer| %>
<p> <%= answer %> </p>
<% end %>
</div>
</body>
</html>

Sinatra redirect to show params

Im building a simple practice Sinatra app which allows users to enter urls via a form, and once submitted the app will open each of these urls in a new table (similar to urlopener.com)
My app.rb file
require 'sinatra'
get '/' do
erb :'index.html'
end
post '/' do
urls = params[:urls]
end
My View file
<h1>Enter URLs Below </h1>
<form action="/" method="post">
<textarea rows="40" cols="50" id="urls" name="urls" ></textarea>
<br/>
<input type= "submit" value="Open 'em up!">
</form>
I am able to print the urls to the console in the post action, but am unsure how to redirect back to the index, and display each of the urls before opening them in new tabs (which I plan on using JS to do).
You don't have to redirect back to the original page (in fact, the URL hasn't changed, so redirecting doesn't make sense). Instead, you render the same template. Simply insert erb :'index.html' in the second block (post '/') as well, and put the URLs in a class variable, so that they will be available to the template:
#urls=params[:urls].split
(The split is there so you get an array of strings, rather than one long string with linebreaks.)
Finally, you add some logic to the template to check whether there are any URLs to display, and if so render them as a list:
<% if #urls && !#urls.empty? %>
<h1>URLs</h1>
<ul>
<% for #url in #urls %>
<li>
<%= #url %>
</li>
<% end %>
</ul>
<% end %>
<h1>Enter URLs Below </h1>
...etc...

How do I create a search form for my posts with Sinatra and Sequel?

I am new to Ruby, and am using Sinatra and Sequel. I'm trying to implement a form to search through the title of my posts.
I'm doing this in my controller:
post '/search' do
#post = Post.all(:Title.like => "%#{params[:query]}%")
erb :layout
end
And I'm doing this in my layout.erb:
<form action="/search" method="get">
<input type="text" name="query"/><br />
<input type="submit" />
</form>
<% if #results %>
<table>
<%#results.each do |r|%>
<tr valign="top">
<td><%=r.Title%></td>
</tr>
<%end%>
</table>
<% end %>
When I submit, this is the URL I get directed to:
http://localhost:4567/search?query=post
but it displays the "Sinatra doesn't know this ditty." screen.
What am I missing here?
Your form is doing a HTTP GET
<form action="/search" method="get">
but your Sinatra action is defined to receive HTTP POST requests.
post '/search' do
I think what is confusing you is that you have a class named Post. The get and post in the actions are not class names, but REST actions. Review routing.

Sinatra to-do list tutorial problems

So, I'm new to Ruby/Sinatra, did a bunch of codecademy lessons and the like. I decided until I actually built something, I wouldn't really understand some core concepts.
I found a tutorial for building a to-do list app in Sinatra, and all was fine and good until I got to the edit and delete functionality. I can read and write to/from the database, but whenever I try to edit or delete, it skips straight to "Note not found".
I couldn't figure this out myself, so I asked a developer friend of mine. When I sent him the code, everything worked absolutely fine for him! We tried a couple of different possible fixes, but to no end. I even downloaded the code from the guy's github, just in case there was a random mistake somewhere in my own code, to no avail.
So, I come here asking for some help! Why won't this work!
Clarification: Here's some of the code, where I think the problem may lie. In edit.erb and delete.erb, no matter what it is going to the else statement and sending me to "note not found". It's reading properly from the database, as my homepage can add and show notes.
recall.rb
get '/:id' do
#note = Note.get params[:id]
#title = "Edit note ##{params[:id]}"
erb :edit
end
put '/:id' do
n = Note.get params[:id]
n.content = params[:content]
n.complete = params[:complete] ? 1 : 0
n.updated_at = Time.now
n.save
redirect '/'
end
get '/:id/delete' do
#note = Note.get params[:id]
#title = "Confirm deletion of note ##{params[:id]}"
erb :delete
end
delete '/:id' do
n = Note.get params[:id]
n.destroy!
redirect '/'
end
edit.erb
<% if #note %>
<form action="/<%= #note.id %>" method="post" id="edit">
<input type="hidden" name="_method" value="put">
<textarea name="content"><%= #note.content %></textarea>
<input type="checkbox" name="complete" <%= "checked" if #note.complete %>>
<input type="submit">
</form>
<p>Delete</p>
<% else %>
<p>Note not found.</p>
<% end %>
delete.erb
<% if #note %>
<p>Are you sure you want to delete the following note: <em>"<%= #note.content %>"</em>?</p>
<form action="/<%= #note.id %>" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="Yes, Delete It!">
Cancel
</form>
<% else %>
<p>Note not found.</p>
<% end %>
Moving the delete-route above the other routes seemed to work for me, which would suggest that the /:id -part in the route definition catches the /delete-part as well. You can see the generated regexps with Sinatra::Application.routes.
Here's a minimal:
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'dm-migrations'
require 'dm-sweatshop'
# Models
DataMapper.setup(:default, 'sqlite::memory:')
class Note
include DataMapper::Resource
property :id, Serial
property :content, Text, :required => true
property :complete, Boolean, :default => false
property :created_at, DateTime, :default => lambda {Time.now}
property :updated_at, DateTime
before(:save) { attribute_set(:updated_at, Time.now) }
end
DataMapper.finalize.auto_migrate!
# Fixtures
Note.fix {{
:content => /\w+/.gen
}}
100.of { Note.gen }
# Routes
before("/:id") {|id| #note = Note.get id }
get("/:id/delete") {|id| #note = Note.get id; erb :delete }
get("/:id") { erb :edit }
put "/:id" do
#note.attributes = params["note"]
#note.save ? redirect(to("/")) : erb(:edit)
end
delete("/:id") { #note.destroy; redirect(to("/")) }
# Templates
template :layout do
'<!DOCTYPE html>
<html>
<body><%= yield %></body>
</html>'
end
template :edit do
'<% if #note %>
<form action="/<%= #note.id %>" method="POST">
<input type="hidden" name="_method" value="PUT">
<textarea name="note[content]"><%= #note.content %></textarea>
<input type="checkbox" name="note[complete]"
<%= #note.complete? && "checked" %> >
<input type="submit">
</form>
<p>Delete</p>
<% else %>
<p>Note not found.</p>
<% end %>'
end
template :delete do
'<% if #note %>
<p>Are you sure you want to delete the following note:
<em>"<%= #note.content %>"</em>?</p>
<form action="/<%= #note.id %>" method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="submit" value="Yes, Delete it!">
Cancel
</form>
<% else %>
<p>Note not found</p>
<% end %>'
end
I don't know if this is still interesting someone, but a simple
params[:id].to_i
fixed it for me.

Resources