I'm trying the Gentle Introduction to CarrierWave-tutorial by using the web-framework Sinatra. When I run my app it starts just fine and the app asks me to upload a file and it does so without any problems. However, while uploading the file, the app throws me an "undefined method `join' for # String:0x3480d50 "-error.
I've looked around a little bit on the internet and I found this issue at github where they say that the error may be due to incompatibilities between Rack and Sinatra or for having installed duplicate versions of Sinatra.
Does anybody know what's happening?
My uploader_app:
require 'carrierwave'
require 'sinatra'
require 'sqlite3'
require 'sequel'
require 'carrierwave/sequel'
DB = Sequel.sqlite
DB.create_table :uploads do
String :file
end
# uploader
class MyUploader < CarrierWave::Uploader::Base
storage :file
end
# model
class Upload < Sequel::Model
mount_uploader :file, MyUploader
end
# sinatra app
get '/' do
#uploads = Upload.all
erb :index
end
post '/' do
upload = Upload.new
upload.file = params[:image]
upload.save
redirect to('/')
end
__END__
## index
<!DOCTYPE html>
<html>
<body>
<div>
<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit" name="submit" value="Upload" />
</form>
<% #uploads.each do |upload| %>
<img src="<%= upload.file.url %>" />
<% end %>
</div>
</body>
</html>
The error is occurring on this line in the Carrierwave Library:
path = encode_path(file.path.gsub(File.expand_path(root), ''))
It fails because root is nil, so File.expand_path(root) raises an error. I don't know why root isn't set, but the following code (that I modified from this answer) worked for me:
CarrierWave.configure do |config|
config.root = settings.root
end
I just added it to the code after declaring the Sequel class and before defining the route. Probably best to stick it in a configure block too. Note that settings.root in the code above is Sinatra's root setting.
This doesn't seem to be caused by the current problems between Rack 1.6.0 and Sinatra 1.4.5 as that's what I was running, although I'm on Ruby v2.1.2 as I mentioned in the comments above.
Depending on what you want, Sinatra's root might not be the best place to put things, as I ended up with a directory inside the project root called "uploads" which had the files in, but config.root obviously needs to be set to something.
Hope that helps.
Related
I'm new to the Sinatra. I want to use modular style in my application.
I want users input some texts, which would be stored into a model called "Tweet".
However, it keeps showing the error message "NameError - uninitialized constant MiniDemo::Tweet:" when I submit the text.
The config.ru is below:
require './app'
run MiniDemo
In the app.rb, the code is as follows:
require 'sinatra/base'
require_relative './routes/simple.rb'
class MiniDemo < Sinatra::Base
set :views, __dir__ + '/views'
set :public_folder, __dir__ + '/public'
if __FILE__ == $0
run!
end
end
The simple.rb file in routes folder is as follows:
require 'sinatra/base'
class MiniDemo < Sinatra::Base
get '/' do
# "Hello from my Mini Demo.\nNew Test."
erb :index
end
post '/tweet' do
Tweet.create(content: params[:content])
end
end
The erb file is below:
<!DOCTYPE html>
<html>
<head>
<script src='javascripts/twitter.js'></script>
</head>
<body>
<form method="POST" action="/tweet">
<p>Your Tweet: <input type="text" name="content"></p>
<input type="submit" id='btn-submit' value="Tweet">
</form>
</body>
</html>
And the tweet model is :
require 'sinatra/activerecord'
require 'sinatra/base'
class Tweet < ActiveRecord::Base
end
Could you give me some suggestion?
Thanks so much.
I found the reason. I forgot to require the model Tweet in the app.rb file. What I did is to include the below line in the app.rb file. require_relative './models/tweet.rb'
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 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 want to generate a PDF with our department logo in it. When I try to use the WickedPdf class in my controller (using the method described at https://github.com/mileszs/wicked_pdf):
def some_action
image_tag_string = image_tag('logo.jpg')
pdf = WickedPdf.new.pdf_from_string(image_tag_string)
save_path = Rails.root.join('testpdfs','logotest.pdf')
File.open(save_path, 'wb') do |file|
file << pdf
end
end
...the application saves the PDF to the target directory, but it has a blue-and-white '?' mark where the image should be.
If I do this instead:
image_tag_string = wicked_pdf_image_tag('logo.jpg')
pdf = WickedPdf.new.pdf_from_string(image_tag_string)
I get the following error:
NoMethodError:
undefined method `wicked_pdf_image_tag' for #<...
It would appear that my Rails app is also missing / not linking to a helper file belonging to the wicked-pdf gem.
Answers to similar questions on StackOverflow recommend writing a custom "image-tag" helper to locate the image or installing wkhtmltopdf. For me, image-tag shows the logo just fine when placed in a View (whatever.html.erb). "logo.jpg" is already located in both the asset pipeline and #{RailsRoot}/public/images. Finally, I am using wkhtmltopdf 0.9.9, wicked-pdf 0.11.0, and rails 4 on Ubuntu 14.04.
In a nutshell - what am I doing wrong that causes WickedPDF to fail to render the image?
First thing create a pdf template to render and use your wicked_pdf tags in that template..
for example-
app/views/layout/application.pdf.erb-
<!doctype html>
<html>
<head>
<meta charset='utf-8' />
</head>
<body onload='number_pages'>
<div id="content">
<%= yield %>
</div>
</body>
</html>
app/views/pdf/pdf_view.pdf.erb-
<div>
<%= wicked_pdf_image_tag 'logo.jpg' %>
</div>
use this template instead
def save
pdf = WickedPdf.new.pdf_from_string(
render_to_string(
template: 'example/pdf_view.pdf.erb',
layout: 'layouts/application.pdf.erb'))
send_data(pdf,
filename: 'file_name.pdf',
type: 'application/pdf',
disposition: 'attachment')
end
This might help you..
Use the wicked_pdf_image_tag helper in your view and reference the image with asset_url if your image is in public/images or use asset_pack_url if the image is in public/packs/media/images
<%= wicked_pdf_image_tag asset_url('/images/footer_logo.png') %>
or
<%= wicked_pdf_image_tag asset_pack_url('media/images/footer_logo.png') %>
I converted image url that 'http' from 'https'. Than worked.
Heroku-18
Rails 4.2
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.4)
In my case, I am using carrierwave, the solution was taken from this post
<img src="<%= root_url + "/" +file.service_url %>">
This worked on rails 5.
I attempted to use the sinatra-flash gem with my application and get an "undefined local variable or method 'flash'" error when I try to run it.
my_app:
require 'sinatra/base'
require 'sinatra/flash'
class GGInfraUserManager < Sinatra::Base
enable :sessions
register Sinatra::Flash
...(rest of app)
post '/' do
flash[:error] = "Password must be a minimum of 8 characters" unless new_password.match /.{8}/
log.info "#{Time.now} password meets policy requirements"
end
redirect '/'
end
In my erb view file (at the top):
<div id="flash" class="notice">
<a class="close" data-dismiss="alert">×</a>
<%= flash.now[:error] %>
</div>
Can someone please tell me how to correct this error so that the flash functionality will work?
While the gem seems comfortable enough to use why not implement it yourself. It's in fact just a couple of lines:
#in your app.rb:
helpers do
#a partial helper
def partial(template, locals = {})
slim template, :layout => false, :locals => locals
end
#the flash helper
def flash
#flash = session.delete(:flash)
end
end
get '/' do
session[:flash] = ["Some happy news", "alert-success"]
end
Then you can add a partial view which I called partial_flash.slim
-if flash
-message, status = #flash
.alert class=(status) = message
You call that partial usually from your layout file or any other view that needs a flash message:
==partial :partial_flash
So a route is called, the layout is loaded and checks if flash. If there is, it displays a flash message with a specified class. I use Twitter Bootstrap, so alert-success is a green message box.
You can see an example app here: https://github.com/burningTyger/farhang-app