Validating a PIN entered by users - ruby

How would you refactor this code that checks if users have added a 4+ digit PIN so the code will be as short as possible?
def has_pin?
return self.pin.to_i > 1000 rescue nil
false
end
Ideally without using AR validation on user creation time as they're created with no PIN at first, but may choose to add them later in some specific cases.
PS: the PIN is stored as string for some reason.

I would go with:
def pin_valid?
pin.present? && pin.match?(/\A\d{4,}\z/)
end
Why do you aim to have your code as short as possible? I would always aim to have my code as easy to understand as possible.

Related

What is the best way to get keyboard events (input without press 'enter') in a Ruby console application?

I've been looking for this answer in the internet for a while and have found other people asking the same thing, even here. So this post will be a presentation of my case and a response to the "solutions" that I have found.
I am such new in Ruby, but for learning purposes I decided to create a gem, here.
I am trying to implement a keyboard navigation to this program, that will allow the user use short-cuts to select what kind of request he want to see. And in the future, arrow navigations, etc.
My problem: I can't find a consistent way to get the keyboard events from the user's console with Ruby.
Solutions that I have tried:
Highline gem: Seems do not support this feature anymore. Anyway it uses the STDIN, keep reading.
STDIN.getch: I need to run it in a parallel loop, because at the same time that the user can use a short-cut, more data can be created and the program needs to show it. And well, I display formated text in the console, (Rails log). When this loop is running, my text lost the all the format.
Curses: Cool but I need to set position(x,y) to display my text every time? It will get confusing.
Here is where I am trying to do it.
You may note that I am using "stty -raw echo" (turns raw off) before show my text and "stty raw -echo" (turns raw on) after. That keeps my text formated.
But my key listener loop is not working. I mean, It works in sometimes but is not consistent. If a press a key twice it don't work anymore and sometimes it stops alone too.
Let me put one part of the code here:
def run
# Two loops run in parallel using Threads.
# stream_log loops like a normal stream in the file, but it also parser the text.
# break it into requests and store in #requests_queue.
# stream_parsed_log stream inside the #requests_queue and shows it in the screen.
#requests_queue = Queue.new
#all_requests = Array.new
# It's not working yet.
Thread.new { listen_keyboard }
Thread.new { stream_log }
stream_parsed_log
end
def listen_keyboard
# not finished
loop do
char = STDIN.getch
case char
when 'q'
puts "Exiting."
exit
when 'a'
#types_to_show = ['GET', 'POST', 'PUT', 'DELETE', 'ASSET']
requests_to_show = filter_to_show(#all_requests)
command = true
when 'p'
#types_to_show = ['POST']
requests_to_show = filter_to_show(#all_requests)
command = true
end
clear_screen if command
#requests_queue += requests_to_show if command
command = false
end
end
I need a light in my path, what should I do?
That one was my mistake.
It's just a logic error in another part of code that was running in another thread so the ruby don't shows the error by default. I used ruby -d and realized what was wrong. This mistake was messing my keyboard input.
So now it's fixed and I am using STDIN.getch with no problem.
I just turn the raw mode off before show any string. And everything is ok.
You can check here, or in the gem itself.
That's it.

Reading user input without halting execution

I'm trying to read user input in a console interface in a Lua application.
However, I do not want to halt program execution as the title suggests. Using read() would interfere with the normal handling of ongoing events, and interface updates, while the user's typing.
The best solution I could come up with was maintaining a temporary variable I apply any user input to that isn't a function key. However, my event handler returns scancodes, and I know of no way to map these to ASCII codes short of maintaining a table for each key, which is something I really want to avoid.
Any ideas?
Edit
To give an example of what I mean:
function read_input()
local input = read()
do_something_with(input)
end
while true do
e,param1,param2,param3 = os.pullEvent()
if (e=='key' and param1=='201') then
read_input()
elseif (e=='something_else') then
do_something_else()
end
end
As you can see, the user can at some point land in a function demanding user input. While this input is taken, I can't have any other (event-based) functions of the program being impeded by this.
You would need to read the keys continuously from the os.pullEvent()
local input
while true do
e,param1,param2,param3 = os.pullEvent()
if (e=='key') then
-- do some fancy stuff for checking which key has pressed and append it to input
-- additionally if it's enter do something other fancy
else
-- blah blah
end
end
I'm not sure but I thought the character of which key was pressed is in one of the params of the pullEvent, I might be mistaken tho.
Additionally if you want to do something every second or so, start a timer which also fires the pullEvent.

Watir: How to verify text is NOT present in web page

I'm writing a test where I delete a record, and I need to verify that the record is no longer present after I've deleted it. I know how to verify the record text is present in a page, with "browser.text.include?", but is there a way that I can verify that the text is not present instead? I need the test to fail if the text is still present after it's supposedly been deleted.
I've searched but the only hits I get on search tell me how to verify text is present - which is the opposite of what I need.
Thank you very much.
browser.text.include? returns a boolean value (actually a truetype or a falsetype, but this isn't the time for that discussion), so negating it will inverse your search.
do_a_faily_thing if not browser.text.include? "badgers are eating my face"
Feel free to customise for your own needs. PS. This is basically ry's answer, only with face-eating badgers.
Added for historical interest, from Chuck's suggestion:
do_a_faily_thing unless browser.text.include? "face-eating-badger-eating-badgers are eating my face-eating badgers"
Added to show an "else" example:
if browser.text.include? "badgers are eating my face"
do_a_thing
else
phew_no_badgers
end
How about:
!browser.text.include?("my string")
or depending on what testing framework you are using
# RSpec and/or Cucumber
browser.text.include?("my string").should != true
# TestUnit
assert(browser.text.include?("my string") != true)
If the record is wrapped HTML element, using exist? method is the another way to verify existence.
deleted record (sample)
<p class='foo'>bar</p>
check script
p(:class,'foo').exist?

Creating thousands of records in Rails

Let me set the stage: My application deals with gift cards. When we create cards they have to have a unique string that the user can use to redeem it with. So when someone orders our gift cards, like a retailer, we need to make a lot of new card objects and store them in the DB.
With that in mind, I'm trying to see how quickly I can have my application generate 100,000 Cards. Database expert, I am not, so I need someone to explain this little phenomena: When I create 1000 Cards, it takes 5 seconds. When I create 100,000 cards it should take 500 seconds right?
Now I know what you're wanting to see, the card creation method I'm using, because the first assumption would be that it's getting slower because it's checking the uniqueness of a bunch of cards, more as it goes along. But I can show you my rake task
desc "Creates cards for a retailer"
task :order_cards, [:number_of_cards, :value, :retailer_name] => :environment do |t, args|
t = Time.now
puts "Searching for retailer"
#retailer = Retailer.find_by_name(args[:retailer_name])
puts "Retailer found"
puts "Generating codes"
value = args[:value].to_i
number_of_cards = args[:number_of_cards].to_i
codes = []
top_off_codes(codes, number_of_cards)
while codes != codes.uniq
codes.uniq!
top_off_codes(codes, number_of_cards)
end
stored_codes = Card.all.collect do |c|
c.code
end
while codes != (codes - stored_codes)
codes -= stored_codes
top_off_codes(codes, number_of_cards)
end
puts "Codes are unique and generated"
puts "Creating bundle"
#bundle = #retailer.bundles.create!(:value => value)
puts "Bundle created"
puts "Creating cards"
#bundle.transaction do
codes.each do |code|
#bundle.cards.create!(:code => code)
end
end
puts "Cards generated in #{Time.now - t}s"
end
def top_off_codes(codes, intended_number)
(intended_number - codes.size).times do
codes << ReadableRandom.get(CODE_LENGTH)
end
end
I'm using a gem called readable_random for the unique code. So if you read through all of that code, you'll see that it does all of it's uniqueness testing before it ever starts creating cards. It also writes status updates to the screen while it's running, and it always sits for a while at creating. Meanwhile it flies through the uniqueness tests. So my question to the stackoverflow community is: Why is my database slowing down as I add more cards? Why is this not a linear function in regards to time per card? I'm sure the answer is simple and I'm just a moron who knows nothing about data storage. And if anyone has any suggestions, how would you optimize this method, and how fast do you think you could get it to create 100,000 cards?
(When I plotted out my times on a graph and did a quick curve fit to get my line formula, I calculated how long it would take to create 100,000 cards with my current code and it says 5.5 hours. That maybe completely wrong, I'm not sure. But if it stays on the line I curve fitted, it would be right around there.)
Not an answer to your question, but a couple of suggestions on how to make the insert faster:
Use Ruby's Hash to eliminate duplicates - using your card codes as hash keys, adding them to a hash until your hash grows to the desired size. You can also use class Set instead (but I doubt it's any faster than Hash).
Use bulk insert into the database, instead of series of INSERT queries. Most DBMS's offer the possibility: create text file with new records, and tell database to import it. Here are links for MySQL and PostgreSQL.
My first thoughts would be around transactions - if you have 100,000 pending changes waiting to be committed in the transaction that would slow things down a little, but any decent DB should be able to handle that.
What DB are you using?
What indexes are in place?
Any DB optimisations, eg clustered tables/indexes.
Not sure of the Ruby transaction support - is the #bundle.transaction line something from ActiveModel or another library you are using?

Guess A Number - Ruby Online

I have been trying to create a Ruby program that will be running online where a user can guess a number, and it will say higher or lower. I know it will take a random number store in a variable, then run a loop? With conditionals to check?
Im not asking for full code, the basic structure for I can use this to get me going.
Any idea how i would do this? I found info to create a random number like this:
x = rand(20)
UPDATE: My code I am going to be working with is something like this: http://pastie.org/461976
I would say to do something like this:
x = rand(20)
loop {
# get the number from the user somehow, store it in num
if num == x
# they got it right
break
elsif num > x
# the guess was too high
else
# the guess was too low
end
}
If you're running it online, this structure may not be feasible. You may need to store the guess in the user's session and have a textbox for the guess, and submit it to a controller which would have the above code without the loop construct, and just redirect them to the same page with a message if they didn't get it right.

Resources