While creating an application using ActiveRecord with sinatra, I encountered such an error.
ActiveRecord::ConnectionTimeoutError at / could not obtain a database
connection within 5.000 seconds (waited 5.005 seconds)
What I was about to do was to "get a profile image from Twitter API, save it in a database, and embed it in index.erb". I stopped here.
The code is below.
main.rb
require "sinatra"
require "sinatra/reloader"
require "twitter"
require "active_record"
ActiveRecord::Base.establish_connection(
adapter: "sqlite3",
database: "./image.db"
)
class Src < ActiveRecord::Base
end
def get_profile_image
#srcs = Src.order("id desc").all
end
def add_profile_image(twitter_id)
client = Twitter::REST::Client.new(
consumer_key: "[CONSUMER_KEY]",
consumer_secret: "[CONSUMER_SECRET]",
access_token: "[ACCESS_TOMEN]",
access_token_secret: "[ACCESS_TOKEN_SECRET]"
)
user = client.user(twitter_id)
url = user.profile_image_url
src = Src.new(account: twitter_id, url: url)
src.save
end
def delete_img(twitter_id)
Src.find_by(account: twitter_id).delete
end
get "/" do
get_profile_image
erb :index
end
post "/" do
add_profile_image(params[:id])
get_profile_image
erb :index
end
get "/delete" do
delete_img(params[:id])
get_profile_image
erb :index
end
index.erb
<form method="post" action="/">
<input type="text" name="id">
<input type="submit" value="enter">
</form>
<form method="get" action="/delete">
<input type="text" name="id">
<input type="submit" value="delete">
</form>
<% #srcs.each do |src| %>
<div id="images-space" style="float: left;" class="imgs">
<img data-id="<%= src.id %>" src="<%= src.url %>">
</div>
<% end %>
DB table name is "srcs" and column is
id integer primary key
account text
url text
This kind of error is the first time for me, but where is the problem?
Decouple the connection to your database from your code in a separate script to test and publish that with the error produced so that we can reproduce the problem, something like
require "active_record"
ActiveRecord::Base.establish_connection(
adapter: "sqlite3",
database: "./image.db"
)
if !ActiveRecord::Base.connection.table_exists?('SRCS')
ActiveRecord::Schema.define do
create_table 'SRCS' do |table|
table.column :account, :string
table.column :url, :string
end
end
end
class Src < ActiveRecord::Base
self.table_name = 'SRCS'
end
p Src.first
Related
I'm making a fake twitter app for a project and I have this issue with Capybara not recognizing my :username element. Is there something that I'm missing in my code or perhaps a process that I haven't done? I'm still pretty new to coding so I could definitely be missing something relatively simple. I'm including my ApplicationController, UserController, and TweetController. Thanks in advance!
require './config/environment'
class ApplicationController < Sinatra::Base
configure do
set :public_folder, 'public'
set :views, 'app/views'
enable :sessions
set :session_secret, 'secret'
end
get '/' do
erb ':index'
end
helpers do
def current_user
#user ||= User.find_by(id: session[:user_id]) if session[:user_id]
end
def logged_in?
!!current_user
end
end
end
class UsersController < ApplicationController
get '/users/:slug' do
#user = User.find_by_slug(params[:slug])
erb :"users/show"
end
get '/signup' do
if !logged_in?
erb ":users/signup"
else
redirect to "/tweets"
end
end
post '/signup' do
if params[:username] == "" || params[:email] == "" || params[:password] == ""
redirect to "/signup"
else
#user = User.new(username: params[:username], email: params[:email], password: params[:password])
#user.save
session[:user_id] = #user.id
redirect to "/tweets"
end
end
get '/login' do
if !logged_in?
erb :"users/login"
else
redirect to "/tweets"
end
end
post '/login' do
a = User.find_by(username: params[:username])
if a && a.authenticate(params[:password])
session[:user_id] = #user
redirect to "/tweets"
else
redirect to "/signup"
end
end
get '/logout' do
if logged_in?
session.destroy
redirect to "/login"
else
redirect to "/"
end
end
end
class TweetsController < ApplicationController
get '/tweets' do
if logged_in?
#tweets = Tweet.all
erb 'tweets/tweets'
else
redirect to '/login'
end
end
get '/tweets/new' do
if logged_in?
erb 'tweets/create_tweet'
else
redirect to 'login'
end
end
post '/tweets' do
if logged_in?
erb 'tweets/create_tweet'
else
redirect to '/login', 200
end
end
get '/tweets/:id' do
if logged_in?
#tweet = Tweet.find_by_id(params[:id])
erb 'tweets/show_tweet'
else
redirect to '/login'
end
end
patch '/tweets/:id' do
#tweet = Tweet.find_by_id(params[:id])
if !params[:content].empty?
#tweet.update(content: params[:content])
#tweet.save
redirect 'tweets/#{params[:id]}'
else
redirect 'tweets/#{params[:id]}/edit'
end
end
post '/tweets/:id/delete' do
#tweets = Tweet.find_by_id(params[:id])
if current_user == #tweet.user
#tweet.delete
redirect to '/tweets'
else
redirect to '/tweets/#{params[:id]}'
end
end
end
Failure/Error: fill_in(:username, :with => "becky567")
Capybara::ElementNotFound:
Unable to find field :username that is not disabled
Test code:
describe 'index action' do
context 'logged in' do
it 'lets a user view the tweets index if logged in' do
user1 = User.create(:username => "becky567", :email => "starz#aol.com", :password => "kittens")
tweet1 = Tweet.create(:content => "tweeting!", :user_id => user1.id)
user2 = User.create(:username => "silverstallion", :email => "silver#aol.com", :password => "horses")
tweet2 = Tweet.create(:content => "look at this tweet", :user_id => user2.id)
visit '/login'
fill_in(:username, :with => "becky567")
fill_in(:password, :with => "kittens")
click_button 'submit'
visit "/tweets"
expect(page.body).to include(tweet1.content)
expect(page.body).to include(tweet2.content)
end
end
Show tweets HTML:
<p><%= #tweet.content %></p>
<form action="/tweets/<%= #tweet.id %>" method="post">
<input type="hidden" name="_method" value="delete">
<input type="submit" value="Delete Tweet">
</form>
Edit Tweet
Tweets HTML:
<h1> Welcome, <%=#user.username %></h1>
<% #tweets.each do |tweet| %>
<p><%tweets.content %></p>
<% end %>
Show user HTML:
<h1><%=#user.username%></h1>
New Tweet
<% #user.tweets.each do |tweet|%>
<%= tweet.content %>EDIT
<% end %>
Log Out
Login HTML:
<h1>Login to Fwitter</h1>
<form action="/login" method="post">
<label>Username: </label><input type="username" name="username">
<label>Password: </label><input type="password" name="pasword">
<input type="submit" value="submit">
</form>
Signup HTML:
<h1> Sign Up for Fwitter</h1>
<form action="/signup" method="post">
<label for="username">Username</label>
<input type="text" id="username" name="username">
<label for="email">Email</label>
<input type="text" id="email" name="email">
<label for="password">Password</label>
<input type="text" id="password" name="password">
<button type="submit" value="submit">Sign Up</button>
</form>
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.
This was my first Sinatra project - link shortener but I am stuck with some errors and to be honest sinatra's built-in debugger tells me literally nothing. I would like you to give me a clue or suggest a solution to problem.
http://min.us/mkBIVTh7p - screenshot, this happen when I submit my form with url: http://google.com and word google
require 'sinatra'
require 'shotgun'
require 'data_mapper'
require 'dm-migrations'
require 'dm-sqlite-adapter'
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/form.db")
class Url
include DataMapper::Resource
property :id, Serial
property :url, String
property :suggestion, String
end
get '/' do
erb :index
end
post '/' do
Url.create(:url => params[:url], :suggestion=> params[:suggestion])
end
get '/Url.suggestion' do
query = request_path.slice!(0)
redirection = Url.first(:suggestion => query)
redirect redirection.url
end
index.rb
<!doctype html>
<html>
<head>
<title>Skracanie linków</title>
</head>
<body>
<form name="form" method="post" action="#">
<fieldset>
<legend>Wpisz co trzeba</legend>
<p><label> <input type="text" name="post[url]"/>Url:</label></p>
<p><label> <input type="text" name="post[suggestion]"/>Suggested name:</label></p>
</fieldset>
<p class="center">
<input type="reset" value="Wyczyść formularz"/>
<input type="submit" value="Wyślij"/>
</p>
</form>
</body>
</html>
This is because you need to finalize your models. See http://datamapper.org/getting-started.html under the heading "Finalize Models".
Add the finalize command after defining your models:
class Url
include DataMapper::Resource
property :id, Serial
property :url, String
property :suggestion, String
end
# add this line
DataMapper.finalize
This is an example from a book, a bit modified. It seems like sessions don't work. Every time I get a new session.
#reporter.rb
require 'sinatra/base'
class LoginScreen < Sinatra::Base
#configure(:development) { set :session_secret, "something" }
enable :sessions
get('/login') { erb :login }
post('/login') do
if params[:user][:login] == 'admin' && params[:user][:password] == 'admin'
session['user_name'] = params[:user][:login]
redirect '/'
else
session[:notice] = "notice!"
redirect '/login'
end
end
end
class Reporter < Sinatra::Base
# "прослойка" будет запущена перед фильтрами
# enable :sessions
# use Rack::Session::Pool, :expire_after => 2592000
#configure(:development) { set :session_secret, "something" }
use LoginScreen
before do
unless session[:user_name]
halt "Access denied, please <a href='/login'>login</a>."
end
end
get('/') { "Hello #{session['user_name']}." }
end
config.ru
require './reporter'
run Reporter
login.erb
<h1>Main User</h1>
<h1>Welccome to reporter</h1>
<p>You must log in with your credentials or as "newcomer" </p>
<form action="/login" method="post" id="user">
<p>
<label>login:</label><br />
<input type="text" name="user[login]" id="login" />
</p>
<p>
<label>Password:</label><br />
<input type="text" name="user[password]" id="password" />
</p>
<p>
<input type="submit" value="Log in">
</p>
</form>
I'm using
ruby 1.9.2
sinatra 1.3.2
shotgun -s thin -p 4567 - how I start server
I just can't understand why sessions don't save data?
Why did you comment
set :session_secret, "something"
in your examples?
If you use shotgun for reloading server it can help you.
My super-simple Sinatra app is a list of notes, and each note has an attached image.
I've got a 'put' route set up that lets me update notes, but unless I re-upload the image, I lose it (note.image is set to 'nil' when I submit the form).
Thanks in advance for your help!
Here's my uploader:
class MyUploader < CarrierWave::Uploader::Base
include CarrierWave::MimeTypes
process :set_content_type
storage :fog
end
Here's my Note class:
class Note
include DataMapper::Resource
property :id, Serial
property :image, String, :auto_validation => false
property :content, Text, :required => true
property :created_at, Date
property :updated_at, Date
mount_uploader :image, MyUploader
end
Here's my 'put' route:
put '/:id' do
n = Note.get params[:id]
unless n
redirect '/', :error => "Can't find that note."
end
n.image = params[:image]
n.credit = params[:content]
n.date = params[:date]
n.updated_at = Time.now
if n.save
redirect '/', :notice => 'Note updated successfully.'
else
redirect '/', :error => 'Error updating note.'
end
end
And here's the form I'm using to update notes:
<% if #note %>
<form action="/<%= #note.id %>" method="post" id="edit" enctype="multipart/form-data">
<input type="hidden" name="_method" value="put">
<p><input type="text" name="credit" value="<%=h #note.content %>"></p>
<p><input type="file" name="image" /></p>
<br><br>
<input type="submit">
</form>
<% else %>
<p>Note not found.</p>
<% end %>
A simple if check is what you need: if params[image] is nil you skip the n.image = params[:image]
n.image = params[:image] if params[:image]
I use similar approach to create a custom Rails validation check when I work with ActiveRecord models that contain CarrierWave images. Probably it won't be a bad idea to check whether or not n.image isn't nil as well - if it's nil I guess it should be mandatory to upload an image.