I am following this Sinatra blog post to build my own blog in Ruby Sinatra, the only difference being my templates are in slim and not ERB.
The problem I'm having is in saving edited posts. The posts actually save but it's not redirecting me to the recently edited page and Chrome is giving me a "No data received error", Error code: ERR_EMPTY_RESPONSE.
So my question is how to deal with the No Data Received?
Sinatra Routes
get '/posts/:id/edit' do
#post = Post.find(params[:id])
#title = 'Edit Post'
slim :'posts/edit'
end
put '/posts/:id' do
#post = Post.find(params[:id])
if #post.update_attributes(params[:post])
redirect '/posts/#{#post.id}'
else
slim :'posts/edit'
end
end
Slim Template
h1 Edit Post
form action="/posts/#{#post.id}" method="post"
input type="hidden" name="_method" value="put"
label for="post_title" Title:
input id="post_title" name="post[title]" type="text" value="#{#post.title}"
label for="post_body" Body:
textarea id="post_body" name="post[body]" rows="5" #{#post.body}
input type="submit" value="Save"
I'm using sqlite3 for the blog database [as said in the blog].
Oh, here's your problem: you have #{...} in the redirect, but it's wrapped by single-quote marks: '. Ruby doesn't interpret interpolations within single-quotes, only within " double-quotes. So if you change that line to redirect "/posts/#{#post.id}" it should work.
Related
I have a Ruby program that reads a file and returns a certain output. I have to now create a web app of this program using Sinatra. I created a form with all the file options and I want to now run that Ruby code with that selected file from the form after the submit button is pressed.
Basically, I’m not sure how to get this external Ruby program to run with the the filename that was selected by the user from the HTML form.
The Ruby program (example.rb) starts with the definition def read_grammar_defs(filename).
// sinatra_main.rb
require 'sinatra'
require 'sinatra/reloader' if development? #gem install sinatra-contrib
require './rsg.rb'
get '/' do
erb :home
end
post '/p' do
//call program to read file with the parameter from form
end
// layout.erb
<!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="/p" 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>
</form>
<button type="submit">submit</button>
<section>
<%= yield %>
</section>
</body>
</html>
The easiest way is as follows:
Package the example.rb code into a class or module like so:
class FileReader
def self.read_grammar_defs(filename)
# ...
end
end
require the file from your sinatra server
Inside the post action, read the params and call the method:
post '/p' do
#result = FileReader.read_grammar_defs(params[:grammar_file])
erb :home
end
With this code, after submitting the form, it would populate the #result variable and render the :home template. Instance variables are accessible from ERB and so you could access it from therer if you wanted to display the result.
This is one potential issue with this, though - when the page is rendered the url will still say "your_host.com/p" and if the user reloads the page, they will get a 404 / "route not found" error because there is no get "/p" defined.
As a workaround, you can redirect '/' and use session as described in this StackOverflow answer or Sinatra' official FAQ to pass the result value.
I've a web page with two forms on it.
There is a general contact form and a shopping cart like response section from customers for sale people to respond to with the customer's choices.
I know nothing about Ruby and I'm having trouble assimilating on just how this is supposed to work with the routes pointing to the Sinatra email template.
Code as follows...
**** Mailer.rb ****
require 'sinatra'
require 'pony'
Pony.options = {
via: :smtp,
via_options: {
openssl_verify_mode: OpenSSL::SSL::VERIFY_NONE,
address: 'mail.myserver.com',
port: '587',
user_name: 'test#myserver.com',
password: '********',
authentication: :plain,
domain: "mail.myserver.com" # the HELO domain provided by the client to the server
}
}
class Mailer < Sinatra::Base
post '/contact' do
options = {
from: "test#myserver.com",
to: 'client#clientaddress.com',
subject: "Contact Form",
body: "#{params['name']} <#{params['email']}> \n" + params['message']
}
Pony.mail(options)
redirect '/'
end
post '/build-tool' do
options = {
from: "test#myserver.com",
to: 'client#clientaddress.com',
subject: "Custom Build Form",
body: "#{params['name']} <#{params['email']}> \n" + params['message']
}
Pony.mail(options)
redirect '/'
end
end
***** HTML Form One *****
<form class="form-horizontal" method="POST" action="/contact">
contact information inputs
</form>
***** HTML Form Two *****
<form class="form-horizontal" method="POST" action="/build-tool">
build tool inputs
</form>
***** Config.rb *****
map '/contact' do
run Mailer
end
map '/build-tool' do
run Mailer
end
Sinatra directly figures out routes, so if you make a POST request to '/contact', it will invoke the code inside the post '/contact' definition, so you don't have to do whatever you're doing in config.rb.
When you redirect '/', it means that the server expects a root route to be defined, which is missing in your class definition.
The HTML tags go into a view which gets rendered via Sinatra.
These are the three things that require changes. First we define a / route which renders the HTML form elements we need:
# mailer.rb
require 'sinatra/base' # note the addition of /base here.
require 'pony'
# pony options code same as before
class Mailer < Sinatra::Base
get '/' do
erb :index
end
# post routes same as before
end
HTML gets rendered from a view template. By default, Sinatra will look up views inside the views/ directory.
# views/index.erb
<form class="form-horizontal" method="POST" action="/contact">
contact information inputs
submit button
</form>
<form class="form-horizontal" method="POST" action="/build-tool">
build tool inputs
submit button
</form>
ERB is a templating languages that's bundled with the Ruby language, so you don't have to install any new gem. There are more languages listed in the documentation.
And the config.ru will look like:
# config.ru
# Note the file change. This is called a Rackup file. config.rb is
# a more general purpose file used by many libraries, so it's better
# to keep this separate.
require_relative 'mailer.rb'
run Mailer
The problem here is that each form corresponds to a specific route, sending the form data to that action. In other words, "form one" sends all input fields it contains in a POST request to /contact and "form two" sends all its input fields in a POSTto /build-tool.
My suggestion would be to incorporate both forms together into one form and just play with the styling of the page to make it look like two. That way you will get all input fields submitted to your Sinatra app together and you can send whatever mail best applies to what was input.
I have a vendor model and controller where I've implemented the below delete method. Whenever I click the delete button, I get the "doesn't know this ditty" error.
delete '/vendors/:id/delete' do
#vendor = Vendor.find(params[:id])
if logged_in? && #vendor.wedding.user == current_user
#vendor.destroy
redirect '/vendors'
else
redirect "/login", locals: {message: "Please log in to see that."}
end
end
My delete button:
<form action="/vendors/<%=#vendor.id%>/delete" method="post">
<input id="hidden" type="hidden" name="_method" value="delete">
<input type="submit" value="Delete Vendor">
</form>
My config.ru file already has 'use Rack::MethodOverride' and my edit/put forms are working fine so MethodOverride seems to be working.
Any idea why Sinatra is giving me the "Sinatra doesn't know this ditty" message just for deleting?
As suggested by Matt in the comments, you might want to try enabling the method override in your app via set. For example, using the modular Sinatra setup:
class Application < Base
set :method_override, true
# routes here
end
There's a nice example in this writeup as well
i have been working on this problem for hours.
I have a form, with a textarea. I use the nicEdit texteditor. It replaces the textarea and shows a nice text editor, because i want my users to add some style to their content.
I use codeIgniter (PHP), and i use the form_helper to create the form. Also i use the form_validation for ss-validation and jquery validation for cs-validation
When i click submit, the form submits seemingly fine. I say this because i use fiddler (an http logger) and i see my text with the right html tags wrapped around it by the text editor.
but when i get the #_pots data in the view, somehow some part of the tags have been removed.
How fiddler traces the HTTP call and the submitted form data (seems correct)
Hello SO, <br><br>
<span style="font-weight: bold;">the following line should be bold</span><br><br>
<span style="font-style: italic;">the following line should be italic</span><br><br>
<span style="text-decoration: underline;">the following line should be underlined</span><br>
How my html looks in my view and in my print_r result from my #_post data
Hello SO,<br><br>
<span bold;"="">the following line should be bold</span><br><br>
<span italic;"="">the following line should be italic</span><br><br>
<span underline;"="">the following line should be underlined</span><br>
It looks like somehow, when i get my data back, it removes the style="font-weight
Does $_post do anything with special characters?!?! has someone experienced similar issues with this?
all responses are greatly appreciated.
You need extend the CI_Security class from Codeigniter and comment/remove/modify this line:
/*
if(in_array($_SERVER['REQUEST_URI'],$allowed))
{
$evil_attributes = array('on\w*', 'xmlns');
}
else
{
$evil_attributes = array('on\w*', 'style', 'xmlns');
}
*/
I am trying to identify a user ID number, to grab a Student row from an ActiveRecord table, but for some reason the 'post' block won't find my :id.
For the 'get', the url is localhost:9456/update/17. It's this 17 I need to pass to the 'post' block to update the database.
I am not sure how to do this. Parse the URL? It seems like I am missing something obvious.
# update user page
get '/update/:id' do
#student = Student.find(params[:id]) #this returns ID=17
erb :update
end
#update user submit
post '/update' do
#student = Student.find(params[:id]) #this line doesn't work
#student.name = (params[:name])
#student.email = (params[:email])
#student.save
redirect '/'
end
thanks!
Are you actually passing the id back? Are you submitting a form via POST? If so, all you should need to do is add an input whose name attribute is id.
<form action='/student/update' method='post'>
<input type='hidden' name='id' value='17' />
</form>