Passing in an existing variable into a Ruby method - ruby

I'm trying to write a test to make sure existing users can't register (Using Cucumber, Watir-Webdriver and Page Objects)
I have the following code:
text_field(:email, :id => "user_email")
text_field(:password, :id => "user_password")
text_field(:password_confirmation, :id => "user_password_confirmation")
checkbox(:terms_privacy, :id => "user_accepts_terms")
button(:sign_up_button, :text => "Sign Up")
def unique_username
#username = "qa_automation"+"#{rand(6 ** 6)}"+"#gmail.com"
end
def sign_up
unique_username
self.email = #username
self.password = USERS['PASSWORD']
self.password_confirmation = USERS['PASSWORD']
self.check_terms_privacy
self.sign_up_button
puts "username: #{#username}"
#existing = #username
end
def sign_up_with_existing_account
puts "exisiting username: #{#existing}"
self.email = #exisiting
self.password = USERS['PASSWORD']
self.password_confirmation = USERS['PASSWORD']
self.check_terms_privacy
self.sign_up_button
puts "username: #{#existing}"
end
But the #existing variable is returning nothing. These two lines are giving me back nothing:
puts "exisiting username: #{#existing}"
self.email = #exisiting
So I guess I'm trying to figure out how to pass the #existing variable from the 'sign_up' method to the 'sign_up_with_existing_account' method? Thoughts?

You can't and should not want to do that. Testing would be a tangled mess if running one test could affect the result of another. You should set up the existing user ahead of time (using e.g. Before) so that any test that needs an existing user can take advantage of it.

Related

When Running Rspec and Sinatra, I keep getting ArgumentError: wrong number of arguments (given 2, expected 0)

I've got a class method called authenticate, which works on the User class.
def self.authenticate(email:, password:)
result = DatabaseConnection.query("SELECT * FROM users WHERE email = '#{email}'")
User.new(result[0]['id'], result[0]['email'])
end
I have an Rspec test;
feature 'authentication' do
it 'a user can sign in' do
User.create(email: 'test#example.com', password: 'password123')
visit 'sessions/new'
fill_in(:email, with: 'test#example.com')
fill_in(:password, with: 'password123')
click_button 'Sign In'
expect(page).to have_content 'Welcome, test#example.com'
end
end
When running Rspec, I get the following error;
1) authentication a user can sign in
Failure/Error:
def initialize(id:, email:)
#id = id
#email = email
end
ArgumentError:
wrong number of arguments (given 2, expected 0)
# ./lib/user.rb:15:in `initialize'
# ./lib/user.rb:23:in `new'
# ./lib/user.rb:23:in `authenticate'
# ./app.rb:84:in `block in <class:BookmarkManager>'
Below is my Sinatra app;
require 'sinatra/base'
require './lib/bookmark'
require './lib/user'
require './database_connection_setup.rb'
require 'uri'
require 'sinatra/flash'
require_relative './lib/tag'
require_relative './lib/bookmark_tag'
class BookmarkManager < Sinatra::Base
enable :sessions, :method_override
register Sinatra::Flash
get '/' do
"Bookmark Manager"
end
get '/bookmarks' do
#user = User.find(session[:user_id])
#bookmarks = Bookmark.all
erb :'bookmarks/index'
end
post '/bookmarks' do
flash[:notice] = "You must submit a valid URL" unless Bookmark.create(url: params[:url], title: params[:title])
redirect '/bookmarks'
end
get '/bookmarks/new' do
erb :'bookmarks/new'
end
delete '/bookmarks/:id' do
Bookmark.delete(id: params[:id])
redirect '/bookmarks'
end
patch '/bookmarks/:id' do
Bookmark.update(id: params[:id], title: params[:title], url: params[:url])
redirect('/bookmarks')
end
get '/bookmarks/:id/edit' do
#bookmark = Bookmark.find(id: params[:id])
erb :'bookmarks/edit'
end
get '/bookmarks/:id/comments/new' do
#bookmark_id = params[:id]
erb :'comments/new'
end
post '/bookmarks/:id/comments' do
Comment.create(text: params[:comment], bookmark_id: params[:id])
redirect '/bookmarks'
end
get '/bookmarks/:id/tags/new' do
#bookmark_id = params[:id]
erb :'/tags/new'
end
post '/bookmarks:id/tags' do
tag = Tag.create(content: params[:tag])
BookmarkTag.create(bookmark_id: params[:id], tag_id: tag.id)
redirect '/bookmarks'
end
get '/users/new' do
erb :'users/new'
end
post '/users' do
user = User.create(email: params[:email], password: params[:password])
session[:user_id] = user.id
redirect '/bookmarks'
end
get '/sessions/new' do
erb :'sessions/new'
end
post '/sessions' do
user = User.authenticate(email: params[:email], password: params[:password])
if user
session[:user_id] = user.id
redirect('/bookmarks')
else
flash[:notice] = 'Please check your email or password.'
redirect('/sessions/new')
end
end
run! if app_file == $0
end
Below is the full User class
require_relative './database_connection'
require 'bcrypt'
class User
def self.create(email:, password:)
encypted_password = BCrypt::Password.create(password
)
result = DatabaseConnection.query("INSERT INTO users (email, password) VALUES('#{email}', '#{encypted_password}') RETURNING id, email;")
User.new(id: result[0]['id'], email: result[0]['email'])
end
attr_reader :id, :email
def initialize(id:, email:)
#id = id
#email = email
end
def self.authenticate(email:, password:)
result = DatabaseConnection.query("SELECT * FROM users WHERE email = '#{email}'")
User.new(result[0]['id'], result[0]['email'])
end
def self.find(id)
return nil unless id
result = DatabaseConnection.query("SELECT * FROM users WHERE id = #{id}")
User.new(
id: result[0]['id'],
email: result[0]['email'])
end
end
What I don't understand is, why is Rspec saying it was expecting 0 arguments, when the initialize method clearly requires two arguments (id, and, email)?
I need to take the id and email method from authenticate and deliver it to initialize.
I thought that's what I was doing, but both Rspec and sinatra are saying otherwise.
Thanks, in advance.
Here you are passing id as sequential args (in the authenticate method).
User.new(result[0]['id'], result[0]['email'])
However your User.new expects keyword args:
def initialize(id:, email:)
Simply pass them this way:
User.new(id: result[0]['id'], email: result[0]['email'])
Also, just something I noticed, if your DatabaseConnection.query returns no results your authenticate will raise an error from result[0]['id'] (it will say "Undefined method [] for Nil:NilClass". Maybe you should fix this and add a test case for it, for example:
def self.authenticate(email:, password:)
result = DatabaseConnection.query(
"SELECT * FROM users WHERE email = '#{email}'"
)
record = result[0]
if record
User.new(id: result[0]['id'], email: result[0]['email'])
end
end
This way the method will return nil if there's no matching user, and your if user inside post '/sessions' will work properly.

active record with ruby (not rails)

I am using active record with ruby (but not rails). I am using sqlite3 which has a test.db on file (not just in-memory). When I run the following code snippet using user.create, it complains about argument error (and when I use use.save, it throws an active record exception. Any idea what I might be doing wrong? Thanks
require 'rubygems'
gem 'activerecord'
require 'sqlite3'
require 'active_record'
ActiveRecord::Base.logger = Logger.new(STDERR)
#ActiveRecord::Base.colorize_logging = false
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:host => "localhost",
:database => 'test.db'
)
class User < ActiveRecord::Base
#attr_accessible :email, :full_name
attr_accessor :email
attr_accessor :full_name
validates :email, presence: true, uniqueness: true
def initialize(email, full_name)
#email = email
#full_name = full_name
end
end
puts "full_name for user:"
full_name = gets.chomp
puts "email address:"
email = gets.chomp
user = User.new(email, full_name)
#user.save
user = User.create!(email: '', full_name: '')
Exception in first case (with User.create!):
main.rb:42:in `initialize': wrong number of arguments (1 for 2) (ArgumentError)
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:50:in `create!'
from main.rb:55:in `<main>'
It is complaining about the new method. According to the documentation: (http://api.rubyonrails.org/classes/ActiveRecord/Base.html), you don't need the initialize, because when you inherit from ActiveRecord::Base, you need to initialize your objects with a hash.
user = User.new({email: email, full_name: full_name})
# or
user = User.new(email: email, full_name: full_name)
# then
user.save
You need to drop the initialize and the attr_accessor from your code.
Try to comment User#initialize method and create new user like this:
User.create! email: 'halk#mail.com', full_name: 'Halk'
Explanation
When you declare AR model by heritage from ActiveRecord::Base class you don't need to define your own #initialize method. But you do. When you call User::create! method, you pass only one argument - Hash with two pairs (with email and full_name keys). But User#initialize define two parameters - email and full_name separately. So Ruby exception raise and talk about it:
wrong number of arguments (1 for 2) (ArgumentError)

Send an object using pry?

I am trying to send an object (user) to NotificationsMailer like this:
pry(main)>NotificationsMailer.welcome_facebook_user({:password=>'123',:email=>'as453now#gmail.com',:basic_profile=>{:name=>'Samir'}}).deliver
But I got this error:
ActionView::Template::Error: undefined method `basic_profile' for #<Hash:0x0000000786d588>
from /app/app/views/notifications_mailer/welcome_facebook_user.html.haml:2:in `block in _app_views_notifications_mailer_welcome_facebook_user_html_haml__4104442834642741128_62933320'
NotificationsMailer.welcome_facebook_user:
def welcome_facebook_user(user)
#user = user
puts "SENT welcome_facebook_user TO:"
puts user[:email]
mail(:to=>user[:email], :subject => "Welcome!")
end
My template:
=content_for :title do
Welcome, #{#user.basic_profile.name unless #user.basic_profile.nil?}
In the real world:
User.rb
class User < Refinery::Core::BaseModel
has_one :basic_profile
But, I want to test it using pry, how to send such a user object? why my attempt failed?
You are using hashes but you should be using objects to create object (I am assuming mass-assigment is turned off as by default) do:
basic_profile = BasicProfile.new
basic_profile.name = 'Samir'
user = User.new
user.password = '123'
user.email = 'aba#gmail.com'
user.basic_profile = basic_profile
NotificationsMailer.welcome_facebook_user(user).deliver
or turn mass-assign off and do
NotificationsMailer.welcome_facebook_user(User.new({:password=>'123',:email=>'as453now#gmail.com',:basic_profile=>BasicProfile.new({:name=>'Samir'})})).deliver
Try this
> #user = User.create!(password: "123", email: "abc#example.com")
> #user.basic_profile.name = "Samir"
> NotificationsMailer.welcome_facebook_user(#user).deliver

Ruby not allowing dynamic strings as an argument

I have a class already mapped out and in a database through DataMapper and now I'm trying to make my first resource into the database.
I have a class that handles the form data and file stuff. In that class, I'm creating the first resource with #variables passed in from the params. All other args passed into this resource come from #variables that have values from the form. In this case, #url, the variable in question, is set to a value only a few lines before. Now when I put in the URL:
rec = Post.new(
# more args
:filename_ogg => #url
)
rec.save
This is the killer: Every other line of code in this file is able to access #url, through a global variable ($upload = Upload.new(file)), except for this resource creator. When it comes to saving the resource, it doesn't go through. BUT, when I replace #url with a static string like "RANDOM URL.", it works perfectly. Why?
This had been tested under both MRI 1.9.3 and JRuby 1.6.7.2 (1.9 mode) under Ubuntu 12.04:
# #{user} edited out
class Upload
attr_accessor :file, :filename, :filename_ogg, :status, :title, :desc, :url
def initialize(file)
#file = file
#filename = #file[:filename].gsub(" ", "")
#filename_ogg = "#{#filename}.ogg"
##url = "http://s3.amazonaws.com/#{user}/#{#filename_ogg}"
end
def downandup
# code
end
def convert(file, file_ogg)
# code
end
def upload(file_ogg)
# code
#url = "http://s3.amazonaws.com/#{user}/#{file_ogg}"
# title and desc are accessed through $upload.title/$upload.desc
rec = Post.new(
:title => #title,
:description => #desc,
:author_id => Random.rand(5),
:time_uploaded => Time.now,
:filename_ogg => #url,
:comments_table => Random.rand(10),
)
rec.save
end
end
The file runs through fine, but when it comes for DataMapper to put it in the database, it won't go in, but when replaced with the static string, the data gets stored.

Ruby JSON issue

I know the title is a bit vague, but I dont know what to put on there.
I'm developing an API with Sinatra for our backend in Ruby. The thing is that I need to be able to pass JSON to the service representing a User. The problem I'm facing is that when I run my tests it does not work, but doing it manually against the service it does work. I'm guessing there is an issue with the JSON format.
I've updated my User model to rely on the helpers from ActiveModel for the JSON serialization. I was running in too much problems with manual conversions. This is what the base User model looks like:
class User
include ActiveModel::Serializers::JSON
attr_accessor :login, :email, :birthday, :created_at, :updated_at, :password_sha, :password_salt
# Creates a new instance of the class using the information stored
# in the hash. If data is missing then nill will be assigned to the
# corresponding property.
def initialize(params = {})
return if params.nil?
self.login = params[:login] if params.key?("login")
self.email = params[:email] if params.key?("email")
self.birthday = Time.parse(params[:birthday]) rescue Time.now
if params.key?("password_salt") && params.key?("password_sha")
self.password_salt = params["password_salt"]
self.password_sha = params["password_sha"]
elsif params.key?("password")
self.set_password(params[:password])
end
self.created_at = Time.now
end
def attributes
{:login => self.login, :email => self.email, :birthday => self.birthday, :created_at => self.created_at, :updated_at => self.updated_at, :password_sha => self.password_sha, :password_salt => self.password_salt}
end
def attributes=(params = {})
self.login = params['login']
self.email = params['email']
self.birthday = params['birthday']
self.created_at = params['created_at']
self.updated_at = params['updated_at']
self.password_sha = params['password_sha']
self.password_salt = params['password_salt']
end
end
I'm using Cucumber, Rack::Test and Capybara to test my API implementation.
The code of the API application looks like this:
# This action will respond to POST request on the /users URI,
# and is responsible for creating a User in the various systems.
post '/users' do
begin
user = User.new.from_json(request.body.read)
201
rescue
400
end
end
In the above piece I expect the json representation in the request body. For some reason the params hash is empty here, don't know why
The test section that makes the actuall post looks like this:
When /^I send a POST request to "([^\"]*)" with the following:$/ do |path, body|
post path, User.new(body.hashes.first).to_json, "CONTENT_TYPE" => "application/json"
end
The example output JSON string generated by the User.rb file looks like this:
"{"user":{"birthday":"1985-02-14T00:00:00+01:00","created_at":"2012-03-23T12:54:11+01:00","email":"arne.de.herdt#gmail.com","login":"airslash","password_salt":"x9fOmBOt","password_sha":"2d3afc55aee8d97cc63b3d4c985040d35147a4a1d312e6450ebee05edcb8e037","updated_at":null}}"
The output is copied from the Rubymine IDE, but when I submit this to the application, I cannot parse it because:
The params hash is empty when using the tests
doing it manually gives me the error about needing at least 2 octets.

Resources