I am trying to only allow a person to see the page if their name is in the database. I figured the best way to go about it was to loop through all of the entries and check if it matches, if it does then display it and stop looping. I keep getting a blank page, any help?
get '/' do
user = "john"
num = DB[:users].all
for person in num do
if person[:name].to_s == user then
File.read('index.html')
break
else
"you're not authorized"
end
end
end
If I were to remove the line that says break within the if statement, I get this error:
NoMethodError at /
undefined method `bytesize' for #<Hash:0x007fcf60970a68>
file: utils.rb location: bytesize line: 369
The problem is that a for
loop evaluates to nil
(unless you break
and supply a value to break
), so your block is returning nil
, so there's nothing to render.
But the real problem is that for
is the wrong solution here. What you're trying to do is check if the Array DB[:users].all
contains a Hash whose :name
member equals user
. You can use a loop for that, but in addition to for
being rare in idiomatic Ruby code (Enumerable#each
is preferred) it makes the intent of your code harder to understand. Instead, you could use Enumerable#find
(the Array class includes the methods in the Enumerable module) like so:
get '/' do
username = "john"
users = DB[:users].all
matching_user = users.find do |user|
user[:name] == user
end
if matching_user
return File.read('index.html')
end
"you're not authorized"
end
...but since you don't actually care about the matching user—you only care if a matching user exists—it would be clearer to use Enumerable#any?
, which just returns true
or false
:
get '/' do
username = "john"
users = DB[:users].all
if users.any? {|user| user[:name] == user }
return File.read('index.html')
end
"you're not authorized"
end
Edit: As @user846250 points out, it would be better to let the database do the work of checking if any matching users exist. Something like this:
get '/' do
username = "john"
if DB[:users].where(:name => username).empty?
return "you're not authorized"
end
File.read('index.html')
end
This is preferable because instead of loading all of the records from the database into Ruby (which is what DB[:users].all
will do)—when you don't actually care about the data in any of them—Sequel will just ask the database if there are any matching records and then return true
or false
.