Why is Capybara unable to find my element? - ruby

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>

Related

Timeout with ActiveRecord(ActiveRecord::ConnectionTimeoutError )

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

Header of the application not appering as per the condition in _header.html.erb

I am following ruby on rails tutorials by michael harlt. I completed my user authentication system and it also working fine but according to the code of my header file it is not supposed to show "Users" and "Accounts" link until and unless the user is logged in.But as soon as I navigate to the login page or sign up page it is showing both these links even if the user is not logged in.
I am not getting any error while launching app in my browser
Here I am posting all the relevant files. Any help would be appreciated.Thanks in advance ! For any other information please let me know.
session_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
remember user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
log_out if logged_in?
redirect_to home_path
end
end
sessions_helper.rb
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
# Remembers a user in a persistent session.
def remember(user)
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
end
# Returns the user corresponding to the remember token cookie.
def current_user
if (user_id = session[:user_id])
#current_user ||= User.find_by_id(user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by_id(user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
#current_user = user
end
end
end
# Returns true if the user is logged in, false otherwise.
def logged_in?
!current_user.nil?
end
# Forgets a persistant session
def forget(user)
user.forget
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
# Log Out Current User
def log_out
session.delete(:user_id)
#current_user = nil
end
end
_header.html.erb
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", home_path, id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", home_path %></li>
<li><%= link_to "Help", help_path %></li>
<% if logged_in? %>
<li><%= link_to "Users", '#' %></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", '#' %></li>
<li class="divider"></li>
<li>
<%= link_to "Log out", logout_path, method: "delete" %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Log in", login_path %></li>
<% end %>
</ul>
</nav>
</div>
</header>
user.rb
class User < ActiveRecord::Base
attr_accessor :remember_token
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
# Returns the hash digest of the given string.
def User.digest(string)
cost = BCrypt::Engine::MIN_COST
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token.
def User.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# Returns true if the given token matches the digest.
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
def forget
update_attribute(:remember_digest, nil)
end
end
Looking through your code path, this is my best guess at what is happening:
You've logged into your site setting the session and cookie with user_id
You log out and clear your session, however the cookie isn't cleared
When you return to the login page, you are able to authenticate via the cookie and thus your login navigation is present.
To confirm a problem like this, I'd put some puts in the two code paths for def current_user and see if that was the case that was occurring. The fix for the issue (I think) is to add forget to destroy in SessionsController:
def destroy
if logged_in?
forget(current_user)
log_out
end
redirect_to home_path
end

How to show the link inside the email in proper way

Please help to resolve this issue.Actually i want to send one confirmation link to email via ROR.The email has been sent but the url is not showing in proper way.
BELOW IS MY CODE SNIPPETS.
views/users/index.html
<h1>This is index page</h1>
<center>
<p>Enter data</p>
<div class="option">
<p><%= link_to "Click here to enter data",users_new_path %></p>
<p><%= link_to "Display data",users_show_path%></p>
</div>
</center>
views/users/edit.html.erb
<h1>Edit your data here</h1>
<center>
<%= form_for #user ,:url => {:action => "update",:id => params[:id]} do |f| %>
<div class="div_reg">
<p>
<label for="username" class="uname" data-icon="u" >username </label>
<%= f.text_field:name,placeholder:"Enter your user name" %>
</p>
<p>
<label for="username" class="uname" data-icon="u" >Email </label>
<%= f.text_field:email,placeholder:"enter your email" %>
</p>
<p>
<label for="username" class="uname" data-icon="u" >Password </label>
<%= f.password_field:password,placeholder:"Enter your password" %>
</p>
<p>
<label for="username" class="uname" data-icon="u" >Password </label>
<%= f.password_field :password_confirmation %>
</p>
<center>
<%= f.submit "Update",:class => 'btn-custom' %>
</center>
<div class="back_btn">
<button type="button" class="btn-custom " style="cursor:pointer;">Back</button>
</div>
</div>
<% end %>
</center>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li><%= message_error %></li>
<% end %>
</ul>
<% end %>
views/users/show.html.erb
<h1>Show your data</h1>
<center>
<ul>
<% #user.each do |t| %>
<li>
<%= t.name %> |
<%= t.email %> |
<%= t.password%> |
<%= t.created_at %>
<%= link_to "edit",users_edit_path(:id => t.id) %> || <%= link_to "Reset Password",users_reset_path(:id => t.id) %>
</li>
<% end %>
</ul>
<div class="back_btn">
<button type="button" class="btn-custom " style="cursor:pointer;">Back</button>
</div>
</center>
controller/users_controller.rb
class UsersController < ApplicationController
def index
end
def new
#user=User.new
end
def create
#user=User.new(users_param);
if #user.save
flash[:notice]="You signed up successfully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="You have not signed up successfully"
flash[:color]="invalid"
redirect_to :action => 'new'
end
end
def show
#user=User.all
end
def edit
#user=User.new
end
def update
flash[:notice]=params[:id]
#user=User.find(params[:id])
if #user.update_attributes(update_params)
flash[:notice]="Your data is updated succesfully"
flash[:color]="valid"
redirect_to :action => 'show'
else
flash[:alert]="Your data could not update,Please check it..!!"
flash[:color]="invalid"
redirect_to :action => 'edit'
end
end
def reset
#user=User.new
end
def emailsend
#user=User.find(params[:id])
if #user.email== params[:user][:email]
UserMailer.registration_confirmation(#user).deliver
flash[:notice]="Check your email to reset the password"
flash[:color]="valid"
redirect_to :action => 'reset'
else
flash[:notice]="Check your valid email or your email is not found"
flash[:color]="invalid"
redirect_to :action => 'show'
end
end
def resetpass
#user=User.new
end
def passres
#user=User.find_by_email(params[:user][:email])
if #user.update_attributes(updates_password)
flash[:notice]="Your password id updated succefully"
flash[:color]="valid"
redirect_to :action => 'index'
else
flash[:alert]="Your data could not update..Please check it..!!"
flash[:color]="invalid"
redirect_to :action => 'show'
end
end
private
def users_param
params.require(:user).permit(:name, :email, :password,:password_confirmation)
end
def update_params
params.require(:user).permit(:name,:email,:password,:password_confirmation)
end
def updates_password
params.require(:user).permit(:email,:password,:password_confirmation)
end
end
users_mailer/registration_confirmation.text.erb
<%= #user.name %>
Thank you for registering!
Edit Your Password <%= link_to "Click Here",users_resetpass_url( :host => "localhost:3000") %>
mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "w5call.w5rtc#gmail.com"
def registration_confirmation(user)
#user = user
mail(:to => user.email, :subject => "Registered")
end
end
config/initializer/setup_mail.rb
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:user_name => "w5call.w5rtc#gmail.com",
:password => "w5rtc123#",
:authentication => "plain",
:enable_starttls_auto => true
}
ActionMailer::Base.default_url_options[:host] = "localhost:3000"
Inside the email inbox it is showing like the below format.
bapi
Thank you for registering!
Edit Your Password Click Here
But I want only "Click Here" to be shown and when user clicks on that text it should redirect to given link(Change Password).
Please help me to edit this and run it successfully.
Thanks in advance.
You have only provided a text template for your e-mail, and text files (since they're not HTML) can't contain HTML links.
You should provide another template registration_confirmation.text.html.erb (or rename your current template)
From the documentation:
The mail method, if not passed a block, will inspect your views and
send all the views with the same name as the method, so the above
action would send the welcome.text.erb view file as well as the
welcome.text.html.erb view file in a multipart/alternative email.
From the file extension of your email template (.text.erb) you can see that you are sending a plain text email, that is why the link tag shows up in its raw form in the mail client. You should just send the plain URL in the plain text version of your email:
# users_mailer/registration_confirmation.text.erb
<%= #user.name %>
Thank you for registering!
To edit your password, please visit the following URL:
<%= users_resetpass_url( :host => "localhost:3000") %>
You can provide both a plain text and a html version of your email by using the .html.erb extension for the second template:
# users_mailer/registration_confirmation.html.erb
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<p><%= #user.name %></p>
<p>Thank you for registering!</p>
<p>Edit Your Password <%= link_to "Click Here",users_resetpass_url( :host => "localhost:3000") %></p>
</body>
</html>
Also see http://guides.rubyonrails.org/action_mailer_basics.html#walkthrough-to-generating-a-mailer

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.

Sinatra/Carrierwave: how to update a record while using an existing image?

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.

Resources