Ruby Sinatra textarea displays variable string instead of variable value - html

I'm trying to set up a webapp using Sinatra, and I've got it working currently where the user can enter a list of URLs into a textarea, click submit, and then some code is ran on the URLs and the user is redirected to a second page to view the result. I'd like to remove the redirection and display the results in another textarea on the same page(or even re-use the same text area) but I've so far been unsuccessful in this venture. Instead of displaying the result, the second textarea just displays the <%=res%> and the submitted URLs disappear.
ERB page
<h1>Put URLs Here</h1>
<form method="POST" action="">
<p><textarea id="urls" name="urls" rows="20" cols="60">
</textarea></p>
<input type="submit">
</form>
<br />
<br />
<h1>Results</h1>
<p><textarea id="results" name="results" rows="20" cols="60">
<%=res%>
</textarea></p>
app.rb
require 'sinatra'
get '/ip' do
erb :ip
end
post '/ip' do
res = Hash.new("")
u = params[:urls].lines("\n")
list = Ipcheck.new()
res = list.check(u)
erb :ip, :locals => {'res' => res}
end
What am I doing wrong? I've searched and have not been able to find a solution to this specific problem.

Use global variable instead of local.
<%= #res %>
and
#res = Hash.new("")
u = params[:urls].lines("\n")
list = Ipcheck.new()
#res = list.check(u)
erb :ip

Related

How to search for all posts containing keyword using Sinatra and Datamapper?

I am fairly new to full stack development and I am trying to get a simple search form to work. The webpage is supposed to redirect the user to a page with a list of all videos containing the keyword. Whenever I type in a title that exists, I get :NoMethodError at /posts/:title/search
I've tried using a query but have failed.
This is my app.rb. I query all videos that contain :title.
get "/posts/:title/search" do
# authenticate!
#results = Video.all(title: params[:title])
if #results
erb :search_success
else
flash[:error] = "Video not found."
erb :search_success
end
end
This is search_success.erb where I want to have a list of the videos that contains the keyword in the title.
<div class="container">
<% #results.each do |r| %>
<h1><%= r.title %></h1>
<% end %>
</div>
This is navigation.erb where the search form lives.
<form action="/posts/:title/search" method="get">
<input type="text" type="text" placeholder="Search" aria-label="Search">
<button type="submit">Search</button>
</form>
Try changing
#results = Video.all(title: params[:title])
to
#results = Video.all(:title.like => "%#{params[:title])}%")
to get answers that don't need to match completely (i.e. match case etc.)
Also in your search form, you have two type attributes. You should change one of them to
name="title"

How do I submit more than one checkbox in an HTML form?

This is a project for school, and so far I only know Ruby, Sinatra, HTML & CSS. I've looked online but only came across PHP and Javascript insturctions (which I'm not supposed to use yet).
I have a form for checkboxes, and although I can check off more than one, only one of the checkbox values gets posted. How do I get it so all of the checked off ones are passed?
Also, 'abbreviation' comes out nil for each state. Am I doing this wrong in my form? And if anything it just uses ONE of the abbreviations and adds it to every state. Finally, how do I make it so the checkboxes remain checked for the states users have already added in the past?
Here's some code:
<form method="POST" action="/states">
<h3>Northeast:</h3> <br>
<input type="checkbox" name="state_name" value="Connecticut" name="abbreviation" value="CT"> Connecticut<br>
<input type="checkbox" name="state_name" value="Deleware" name="abbreviation" value="DE"> Deleware <br>
<input type="checkbox" name="state_name" value="Maine" name="abbreviation" value="ME"> Maine<br>
<input type="checkbox" name="state_name" value="Maryland" name="abbreviation" value="MD"> Maryland<br>
require 'pry'
class StatesController < ApplicationController
get '/states' do
if logged_in?
#user = current_user
#states = current_user.states
erb :'states/states'
else
redirect to '/login'
end
end
get '/states/new' do
if logged_in?
erb :'/states/create'
else
redirect to '/login'
end
end
post '/states' do
if logged_in? && params[:state_name] != ""
#state = State.create(:state_name => params[:state_name], :abbreviation => params[:abbreviation])
# binding.pry
#state.users << current_user
if #state.errors.any?
"Error, try again"
else
redirect "/states"
end
else
redirect to "/states/new"
end
end
get '/states/:id' do
if logged_in?
#state = State.find_by_id(params[:id])
if #state != nil
erb :'/states/show'
else
redirect to '/states'
end
else
redirect to '/login'
end
end
get '/states/:id/edit' do
if logged_in?
#state = State.find_by_id(params[:id])
if #state && current_user
erb :'states/edit'
else
redirect to '/states'
end
else
redirect to '/login'
end
end
patch '/states/:id' do
#state = State.find_by_id(params[:id])
if params[:state_name] != "" && #state.update(:state_name => params[:state][:state_name])
#state.update(:state_name => params[:state][:state_name])
redirect to "/states/#{#state.id}"
else
redirect to "/states/#{#state.id}/edit"
end
end
delete '/states/:id/delete' do
if logged_in?
#state = State.find_by_id(params[:id])
if #state && current_user
#state.destroy
end
redirect to '/states'
else
redirect to '/login'
end
end
end
You need to append [] to your name attribute to support array value i.e. more than one checked values:
<input type="checkbox" name="state_name[]" value="Connecticut"> Connecticut<br>
<input type="checkbox" name="state_name[]" value="Deleware"> Deleware<br>
<input type="checkbox" name="state_name[]" value="Maine"> Maine<br>
<input type="checkbox" name="state_name[]" value="Maryland"> Maryland<br>
Now on your server, you will see the checked values as state_name: ['Connecticut', 'Maine', ...].
Note: You have specified the name and value attributes twice for each checkbox. I am using the first one.
I have always known that in html's forms the ids and names must be unique, unless you are working with radio buttons or in this case checkboxes. Your code seems to be a bit overmade, meaning, you have 2 names and 2 values on each checkbox, and just the last one of both of them will work, so instead of this:
<input type="checkbox" name="state_name" value="Connecticut" name="abbreviation" value="CT"> Connecticut<br>
Try just having one of those attributes:
<input type="checkbox" name="abbreviation" value="CT"> Connecticut<br />
Usually, in for php we would append a '[]' at the end of the name, and you will recieve an array of the values that were checked. But since you are using ruby, which I am a bit familiar to, I've seen the ruby developers like to be a bit more expressive in their code, and sometimes they do things like this:
<input type="checkbox" name="abbreviation[city_1]" value="CT">Connecticut<br />
<input type="checkbox" name="abbreviation[city_2]" value="DE">Delaware<br />
And so on.
You can see an example of it, here, even though I believe you can do it with the empty '[]', but just so you know I've been told that's the php-ish way to do it.
Cheers!
Use only one name and value per input, like:
<input type="checkbox" name="state_name" value="CT"> Connecticut<br><input type="checkbox" name="state_name" value="DE"> Deleware <br><input type="checkbox" name="state_name" value="ME"> Maine<br><input type="checkbox" name="state_name" value="MD"> Maryland
Check your POST array for state_name and their should be an array of all check-boxes selected.

MeteorJS: How to get id to load from collection

I'm trying to load an array (with simple text) and trying to load it up on the template whenever it is called. How do I get the ID from that specific item to get the array that I stored in it?
HTML Template:
<template name="commentMarker">
<div id="viewMarker">
<h3 id="markerTitle">{{markerName}}</h3>
<h6 id="markerCategory">{{markerCategory}}</h6>
<br>
<fieldset>
<legend>Description</legend>
<p>{{markerDescription}}</p>
</fieldset>
<form id="commentForm">
<fieldset>
<legend>Comments</legend>
<input type="text" id="markerId" name="idForComment" value={{markerId}}>
<textarea rows="3" cols="19" name="comment" id="commentArea" placeholder="Insert your comment here..."></textarea>
{{#each comments}}
<p id="oneComment">{{this}}</p>
{{/each}}
</fieldset>
<input type="submit" value="Comment" class="commentButton">
<input type="submit" value="Close" class="exitButton">
</form>
</div>
</template>
JS:
Template.commentMarker.helpers({
comments(){
alert(template.find("#markerId").value);
if(commentArray.length===0) return;
else return commentArray;
}});
This is where I insert the comment into the collection's item and it's working fine
Template.commentMarker.events({
'click .commentButton': function(e, template){
e.preventDefault();
var id = template.find("#markerId").value;
var comment = template.find("#commentArea").value;
Points.update(id, { $push: { comments: comment }});
commentArray = Points.findOne(id).comments;
template.find("#commentArea").value = ' ';
}
I tried with commentArray as a global variable which still is. But I'm at loss how I can get the Id from that specific item, I even put it's Id (with hidden display) in the form to actually be able to insert the comment. But it doesn't help me with showing the comments because I cannot seem to get to this field in the Template.helpers ...
Not entirely sure what you are trying to do. It's almost like as if you are displaying the comments right after you updated in to the collection. It looks like you are doing this entirely on local and not a online collection.
However, storing it as a session would work...or reactive var. Might not be the best solution tho. Basically replace commentArray = Points.findOne(id).comments; with:
Session.set('comments', Points.findOne(id).comments)
Then to get it out in helpers:
let commentArray = Session.get('comments')
It's not safe to use it all the time tho for sensitive data. Also try catch the findOne(id).comments because it does produce errors if it happen to not find it.
NOTE: If you are going to use Meteor.Methods, you cannot use Session. You have to return the id and find it in your helpers.

ejs string variable with space is not displayed properly

I am trying to display the search query in the search bar in HTML.
But if the variable includes a space, the webpage is only going to display the first word.
Here is the code
app.get('/search', function(req, res) {
console.log(req.originalUrl,'oro')
console.log(req.query['search_query'],'aaaaaaa')
res.render('search.ejs', {
user : req.user,
query : req.query['search_query']
});
});
Here is the html code
<form action="/search" method="get">
<div class="form-group">
<input type="submit" class="btn btn-warning btn-lg" value = "search" style = "float: right"/>
<div style="overflow: hidden; padding-right: .5em;">
<input type="text" value = <%= query %> class="form-control" name="search_query" style = "width:100%;"/>
</div>
</div>
</form>
query is the variable collected from the last webpage and passed to /search.
If I type in "I want to find xx", the webpage will only display "I" in the search box. However, in the console, the printout result is the full query " I want to find xx". The corresponding url is also correct "/search?search_query=I+want+to+find+xx".
Anyone has an idea? Thanks a lot!
Let's start with correcting your HTML, by using quotes in value:
<input type="text" value = "<%= query %>" class="form-control" name="search_query" style = "width:100%;"/>
Here under IE you should see a large error, on FF and Chrome browser will try to save the situation and catch only the first word.
Prolably rest of your words are used as attributes and ignored in this input.
Change <%= query %> to <%- query %> .
To add a new line or space while working with ejs, you will have to replace string parameters with HTML tags.
For example, here, I am replacing \n => < br/> to add a new line
<% var testVar = 'Line1\nLine2' %> <%- testVar.replace(/\n/g, '<br/>') %>
Change <%= query %> to <%- query.replace(/ /g, " ") %>
I struggled for hours to render text with spaces
Adding quotes seems to be the easiest solution to this
value = "<%= query %>"
to solve partial content change:
<%= to <%-
use: `` with "" inside
JS example:
let txt = "some text"
console.log(`"${txt}"`)

Sending <input type="image"> to a folder on the server

I have this code
<%= form_for(:img, url: {action: "postodb"}) do |f| %>
<div id="image-preview">image here!</div>
<%= f.submit "Send to database" %>
<%end%>
Here <input type="image"> is added from a js file
var imageDiv = $("#image-preview");
imageDiv.html('<input type="image" name="img1" style="margin-left:146px"id="spiro-img" src="'+img+'"/>');
This all works fine..
Next I want to send this to the folder but it doesnt work
This is the code I have in the controller(referred from this site http://rohitrox.github.io/2013/07/19/canvas-images-and-rails/)
def postodb
data = params[:data_uri]
image_data = Base64.decode64(data['data:image/png;base64,'.length .. -1])
File.open("/public/uploads/somefilename.png", 'wb') do |f|
f.write image_data
end
end
This is the error I get
Plz help.
Using carrierwave gem for loading images.
First what your should to do is read a docs: http://www.w3schools.com/Tags/att_input_type.asp
image - Defines an image as the submit button.
Second what your should learn to read is logs. At screenshot you have section with params, and there is no data_uri key.
And finaly use the <input type='file' ... /> for upload. If you want beauty async upload with preview, you should look on jquery-file-upload gem instead.
P.S.: type='image' is a submit button with image.