Giter VIP home page Giter VIP logo

sinatra-logging-in-and-out's Introduction

Sinatra Sessions Lab - User Logins

Introduction

You've been contracted by Flatiron Bank to consult on their online banking application. Specifically, they've asked you to build out their user login process. Based on your knowledge of sessions, build out the log in and log out features, and ensure that users that log in can only see their own balance.

Helper Methods

MVC architecture relies heavily on the principle of separation of concerns. We make sure that we have a different model for every class we build, that we only have one .erb file per view, etc. This even extends to the purposes each of these files has. A model handles our Ruby logic, our controllers handle the HTTP requests and connect to our models, and our views either take in or display data to our users.

This means that we want to minimize the amount of logic our views contain. Our views should never directly pull from the database (eg. User.all). All of that should be taken care of in the controller actions, and the data should be passed to the view via a specific controller action.

But if you think about most web applications you use, there is information on most pages that is dependent on being logged in. You can see a lot of information if you are logged in and practically none if you're not. So how can you handle that sort of application flow without logic?

Instead of writing that type of logic directly into a view, we use helper methods. Helper methods are methods that are written in the controller, are accessible in the views, and provide some logical support. But a helper method is just a regular method, defined using def and end just like you've always done.

In the app/helpers directory, we're going to define a separate class specifically designed to control logic in our views. This Helpers class will have two class methods, current_user and is_logged_in?.

These two methods will only ever be called in views, particularly account.erb, in order to add double protection to this view so that only the current user, when they are logged in, can see their bank account balance.

It's important to note that helper methods can be used for a lot more than just tracking whether a user is logged in and who the current user is. Helpers are methods that make it cleaner to add logic to our views.

Instructions

  • You'll want to create a User class and a table to store users. Users should have a username, password, and balance (a decimal storing their bank account balance). In the db folder is a seeds.rb file containing some basic users to practice logging in with. Run rake db:migrate and rake db:seed once your User migration and model are in place.

  • You'll need to create a login form on the index page that accepts a username and password and sends a POST request with an action of /login.

  • In the controller action that processes the POST request, you'll want to find the user in the database based on their username.

  • If there is a match, set the session to the user's ID, redirect them to the /account route (using redirect to), and use ERB to display the user's data on the page.

  • If there is no match, render the error page.

  • On the /account page, set up a link called 'Log Out' that clears the session.

  • In app/helpers/helpers.rb, you'll notice a predefined Helpers class. In this class, you'll want to define two class methods, current_user and is_logged_in?.

  • current_user should accept the session hash as an argument. This method should use the user_id from the session hash to find the user in the database and return that user.

  • is_logged_in? should also accept the session hash as an argument. This method should return true if the user_id is in the session hash and false if not. The Ruby !! operator will come in handy here.

  • In account.erb, you'll want to use the is_logged_in? helper method to only display the username and account balance if the user is logged in. Otherwise, it should contain a link to the home page. You'll also want to use current_user to display the username and balance.

sinatra-logging-in-and-out's People

Contributors

annjohn avatar aturkewi avatar bhollan avatar dependabot[bot] avatar dfenjves avatar genericlady avatar ihollander avatar jakebrady5 avatar lizbur10 avatar maxwellbenton avatar peterbell avatar pletcher avatar ritchey0713 avatar ruchiramani avatar victhevenot avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sinatra-logging-in-and-out's Issues

Continually getting a "could not find table 'users'"

Migration is
ruby class CreateUsersTable def change create_tables :users do |t| t.string :username t.string :password t.decimal :balance end end end
then rake db:migrate > rake db:seed > learn
Most of the tests fail w/ "ActiveRecord::StatementInvalid : could not find table 'users'", making it impossible to move beyond this portion of the testing.

Helper Methods

Hi all,

I'm actually working through this lab right now and am about halfway through it. The problem that I'm facing isn't a Ruby/coding issue, it's a documentation issue. I may be out of line here, but I really think the Helper Methods section is due for an expansion.

I haven't had time to take a look yet, but a fellow student in my cohort informed me that Sinatra's docs have extensive details about helper methods. I didn't find any links to that in this lab's README - I know a lot of Learn's READMEs have links to Sinatra's docs, but I guess it wasn't clear that this was a (specifically) Sinatra concept, so I wouldn't have thought to go there to begin with.

I wasn't (and I guess still am not at the time of this writing) clear on what helper methods are, and why I should use them over what we've been doing up to this lab. I know there are RSpec tests for this, but extra documentation would be nice - especially seeing as this was just introduced.

If I get the time to, I may revisit this and contribute the documentation myself - but as of right now I am in no position to, and probably won't be for some time.

--Gage

Helpers method tests mislabeled

Both helper methods are class methods, not instance methods. Should be named as such in tests.
Instead of #current_user use .current_user and instead of #is_logged_in? use .is_logged_in?

log in will not work unless you enter " rake db:seed"

I spoke to another student who experienced the same issue yesterday. This may or may not cause tests to fail but it does present an obstacle that poses as a distraction to the lesson itself. Maybe we can add it to the lesson so that others can focus on getting the tests to pass.

Undefined method "needs_migration?" / "migration_context"

Hey, I had a hard time getting learn to run when I first opened this lab. I got a message about migration_context and needs_migration? being undefined methods. I ended up getting a coach to help me with it, but I think the directions need to be really explicit about how to get the tests to run from the start. I understand now that you have to create a User class and create a migration, but I tried to restart this lab from scratch, and I still couldn't get learn to run on my own. Maybe walk through it and write the directions explicitly in the README. Like I said, no idea why I had so much trouble with this lab but it was a mess to start. I think we ended up deleting the Gemfile.lock once again.

Add in the concept of helper methods

So I want to try and introduce eeeeeeever so lightly the concept of helper methods to this lab. The helper methods that students will see in Rails/Devise are things like current_user and logged_in?. Can we add those into this lab. I'm not sure how helpers should actually work in Sinatra do be honest. There is like an official helpers thing, but I don't want to have to explain all that. Let's make a new class called like SessionHelpers and ask them to define current_user and logged_in?

Default ActiveRecord Migration Test Broken

The ActiveRecord migration test included in this project results in an error:

../sinatra-logging-in-and-out-online-web-pt-041519/spec/spec_helper.rb:12:in <top (required)>': undefined method migration_context' for #ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x00007fa51656dcf0 (NoMethodError)
Did you mean? migration_keys

Problem code
ActiveRecord::Base.connection.migration_context.needs_migration? in spec/spec_helper.rb AND in config.ru

Correct code
In the solution codebase, we have the code below. Once I replaced my config.ru and spec_helper.rb files with the following code, it all worked perfectly:

if ActiveRecord::Migrator.needs_migration?
raise 'Migrations are pending. Run rake db:migrate SINATRA_ENV=test to resolve the issue.'
end

bundler: failed to load command: rspec (/usr/local/rvm/gems/ruby-2.3.1/bin/rspec) NoMethodError: undefined method `needs_migration?' for ActiveRecord::Migrator:Class

bundler: failed to load command: rspec (/usr/local/rvm/gems/ruby-2.3.1/bin/rspec)
NoMethodError: undefined method needs_migration?' for ActiveRecord::Migrator:Class /home/shlokjoshi/sinatra-user-auth-cb-gh-000/spec/spec_helper.rb:8:in <top (required)>'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in require' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in block in requires='
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in each' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455:in requires='
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:112:in block in process_options_into' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in each'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:111:in process_options_into' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration_options.rb:21:in configure'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:99:in setup' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:86:in run'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:71:in run' /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/runner.rb:45:in invoke'
/usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/exe/rspec:4:in <top (required)>' /usr/local/rvm/gems/ruby-2.3.1/bin/rspec:23:in load'
/usr/local/rvm/gems/ruby-2.3.1/bin/rspec:23:in `<top (required)>'

test passes with no code in '/logout' route

track: full stack web dev
summary: test expectations are met without any code in the get '/logout' route. test expects user_id key in session to be nil, but is nil to start out with
files: spec/sinatra_logging_in_and_out_spec.rb line 93
solution: something like expect(session).to eq({})
but that gets error expected: {} got: {}
or something like:
session ={"session_id"=>"f2f60294a7b150ade7c58d35eec2b0bc2100ffbd0723044563223c24a3cd7ea1", "csrf"=>"df2575b28dda861838a627ec335c163a", "tracking"=>{"HTTP_USER_AGENT"=>"da39a3ee5e6b4b0d3255bfef95601890afd80709", "HTTP_ACCEPT_LANGUAGE"=>"da39a3ee5e6b4b0d3255bfef95601890afd80709"}, "user_id"=>2} get '/logout', session
but sessions hash is still does not have user_id key when i put a pry in the route
mention: @aturkewi

screen shot 2017-01-07 at 12 51 47 am

Rakefile is broken

terminal commands like rake -T or rake db:create_migration... were unsuccessful, raising the error:

LoadError: cannot load such file -- active_record/railties/databases.rake

I was able to resolve it simply by switching lines 3 & 4 of the Rakefile, so that it required config/environment before requiring sinatra/activerecord/rake

Sinatra_logging_in_and_out.spec.rb: 68

On line 68 of the 'logging_in_and_out' spec file, the test reads:

expect(last_response.body).to include('You Must Log In to View Your Balance')

The required text is in the '/views/error.erb' file. The problem is that it has a link in it. It reads:

"You Must Log In to View Your Balance"

When I linked to the 'error.erb' file, the test failed. However, I don't think it's so bad to have the link in there. The test could just read like this on line 68:

expect(last_response.body).to include('You Must <a href="/">Log In</a> to View Your Balance')

Missing instruction or error to set Sinatra environment

The lab instructions ask you to run a plain rake db:migrate and rake db:seed.

When I tried to run tests, I received an error stating that there was a pending migration. It did not include any information about Sinatra environment.

I finally determined, by viewing Gemfile, that I needed to run rake db:migrate SINATRA_NV=test to get the lab working. Once I did, I was able to run tests.

Database Cleaner issues

A student was receiving errors around the gem database cleaner being deprecated. We made the proper migrations, but when we ran learn we received the errors.

We commented out line 17 in the gemFile
gem 'database_cleaner', git: 'https://github.com/bmabey/database_cleaner.git'

And we commented out lines 19-27 in the spec_helper that referenced the gem:

DatabaseCleaner.strategy = :truncation

  config.before do
    DatabaseCleaner.clean
  end

  config.after do
    DatabaseCleaner.clean
  end

After we did this, he was able to see the proper tests and errors.

Spec is testing white space causing fail when things should be passing.

The original spec has problems passing. It's testing a lot of whitespace. Instead just use two expect statements.

Fail

Failures:

  1) ApplicationController GET '/account' displays the account information if a user is logged in
     Failure/Error: expect(last_response.body).to include("<h1>Welcome skittles123</h1>\n      <h3>Your Balance: 1000.0</h3>")

       expected "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>title</title>\n    <link rel=\"stylesheet\" href=\"stylesheets/bootstrap.css\" type=\"text/css\">\n  </head>\n  <body id=\"page-top\">\n    \n    <h1>Welcome skittles123</h1>      \n\n    <h3>Your Balance: 1000.0</h3>\n    <a href=\"/logout\">Log Out</a>\n    \n\n  </body>\n</html>\n" to include "<h1>Welcome skittles123</h1>\n      <h3>Your Balance: 1000.0</h3>"
       Diff:
       @@ -1,2 +1,18 @@
       -<h1>Welcome skittles123</h1>\n      <h3>Your Balance: 1000.0</h3>
       +<!DOCTYPE html>
       +<html>
       +  <head>
       +    <meta charset="UTF-8">
       +    <title>title</title>
       +    <link rel="stylesheet" href="stylesheets/bootstrap.css" type="text/css">
       +  </head>
       +  <body id="page-top">
       +    
       +    <h1>Welcome skittles123</h1>      
       +
       +    <h3>Your Balance: 1000.0</h3>
       +    <a href="/logout">Log Out</a>
       +    
       +
       +  </body>
       +</html>

     # ./spec/sinatra_logging_in_and_out_spec.rb:85:in `block (3 levels) in <top (required)>'

Finished in 0.26202 seconds (files took 1.01 seconds to load)
12 examples, 1 failure

Failed examples:

rspec ./spec/sinatra_logging_in_and_out_spec.rb:78 # ApplicationController GET '/account' displays the account information if a user is logged in

[19:20:15] (master) sinatra-logging-in-and-out-v-000

Original

it 'displays the account information if a user is logged in' do
  @user1 = User.create(:username => "skittles123", :password => "iluvskittles", :balance => 1000)
  params = {
    "username"=> "skittles123", "password" => "iluvskittles"
  }
  post '/login', params
  get '/account'
  expect(last_response.body).to include("<h1>Welcome skittles123</h1>\n      <h3>Your Balance: 1000.0</h3>")
end

Suggested edit

    it 'displays the account information if a user is logged in' do
      @user1 = User.create(:username => "skittles123", :password => "iluvskittles", :balance => 1000)
      params = {
        "username"=> "skittles123", "password" => "iluvskittles"
      }
      post '/login', params
      get '/account'
      expect(last_response.body).to include("<h1>Welcome skittles123</h1>")
      expect(last_response.body).to include("<h3>Your Balance: 1000.0</h3>")
    end

Error Appearing before I add any code

Hello -- when I repo this lab I immediately get the following error.

bundler: failed to load command: rspec (/usr/local/rvm/gems/ruby-2.3.1/bin/rspec) TypeError: ActiveRecord::Base is not a symbol nor a string /usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1560:in method_def
/usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1560:in block in d /usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1559:in class_eval
/usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1559:in define_sin /usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1251:in set'
/usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1925:in block (2 l /home/OkayAtay/sinatra-logging-in-and-out-v-000/config/environment.rb:12:in block in <to
/usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1425:in configure' /usr/local/rvm/gems/ruby-2.3.1/gems/sinatra-2.0.1/lib/sinatra/base.rb:1925:in block (2 l
/home/OkayAtay/sinatra-logging-in-and-out-v-000/config/environment.rb:11:in <top (requir /home/OkayAtay/sinatra-logging-in-and-out-v-000/spec/spec_helper.rb:3:in require_relativ
/home/OkayAtay/sinatra-logging-in-and-out-v-000/spec/spec_helper.rb:3:in <top (required) /usr/local/rvm/gems/ruby-2.3.1/gems/rspec-core-3.7.1/lib/rspec/core/configuration.rb:1455

I tried bundle update and bundle install and no one seems to know why the code is not working.

Discrepency with Instructions and test

In the instructions

Instructions

  • If there is a match, set the session to the user's id and redirect them to the /account route (using redirect to) and use ERB to display the user's data on the page.
  • If not, redirect the user to the error page.

Redirect the user to the error page implies to use the method redirect rather then erb :error. If you program a redirect you will get a spec to fail. The simplest solution is to reword redirect to render the err template. I'll suggest an edit for that separate from this.

# ./spec/sinatra_logging_in_and_out_spec.rb

    it "shows the error page if username and ID do not match available users" do
      post '/login', {
        "username"=> "joe", "password" => "nopassword"
      }
      expect(last_response.body).to include('You Must <a href="/">Log In</a> to View Your Balance')
    end

last_response.body will be an empty array since the capystrano helper follow_redirect! is not being called in the spec. If the route is using redirect to then follow_redirect! needs to be called.

it "shows the error page if username and ID do not match available users" do
  post '/login', {
    "username"=> "joe", "password" => "nopassword"
     follow_redirect!
  }
  expect(last_response.body).to include('You Must <a href="/">Log In</a> to View Your Balance')
end

RSpec Config Deprecation Warning

the configuration declaration on line 15 of ./spec/spechelper.rb #treat_symbols_as_metadata_keys_with_true_values= is deprecated. You can remove this without breaking the lab.

Deprecation Warnings:

RSpec::Core::Configuration#treat_symbols_as_metadata_keys_with_true_values= is deprecated, it is now set to true as default and setting it to false has no effect.


If you need more of the backtrace for any of these deprecations to
identify where to make the necessary changes, you can configure
`config.raise_errors_for_deprecations!`, and it will turn the
deprecation warnings into errors, giving you the full backtrace.

1 deprecation warning total

error in spec file before I write any code.

This is the error:
sinatra-logging-in-and-out-online-web-ft-021119/spec/spec_helper.rb:8:in `<top (required)>': undefined method `migration_context' for #<ActiveRecord::ConnectionAdapters::SQLite3Adapter:0x00007fb74d9ccc80> (NoMethodError)

To get any tests to run, I commented out the following code:

  raise 'Migrations are pending. Run `rake db:migrate SINATRA_ENV=test` to resolve the issue.'
end```

in spec_helper.rb (lines 8-10)
and config.ru (lines 3-5)

The bottom bullet point of the README need to be re-written

Hi. Here is the bullet point in question:

"In account.erb, you'll want to use the is_logged_in? helper method to only display the username and account balance if the user is logged in. Otherwise, it should contain a link to the home page. You'll also want to use current_user to display the username and balance."

That threw me for a loop for a while. The tests don't check to see whether the account.erb page contains a link to the homepage if the user is not logged in. Also, the tests want you to redirect to the error page from within the get '/account' route if the user goes directly to /account without logging in. The README does not mention this at all.

It's possible that they meant to say "Otherwise, it should redirect to the error page" instead of "...contain a link to the home page". But if that's the case, that should be the job of the get '/account' route, not the account.erb file, as I discovered; this will also pass the test that I mentioned above.

Thanks for checking this out!

---Sdcrouse

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.