{"id":15152657,"url":"https://github.com/costineest/learn-enough-rails","last_synced_at":"2026-01-20T11:32:11.907Z","repository":{"id":41326407,"uuid":"500877989","full_name":"costinEEST/learn-enough-rails","owner":"costinEEST","description":"Book notes","archived":false,"fork":false,"pushed_at":"2022-08-18T18:02:02.000Z","size":252,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-13T13:52:58.625Z","etag":null,"topics":["book","book-exercises","michael-hartl","rails","rails-tutorial","rails7","ror","ruby","ruby-on-rails","ruby-tutorial"],"latest_commit_sha":null,"homepage":"https://www.learnenough.com/courses/downloads#ruby-on-rails-7th-edition-tutorial","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/costinEEST.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-07T14:35:30.000Z","updated_at":"2022-08-27T15:15:41.000Z","dependencies_parsed_at":"2022-08-10T01:54:20.362Z","dependency_job_id":null,"html_url":"https://github.com/costinEEST/learn-enough-rails","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/costinEEST%2Flearn-enough-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/costinEEST%2Flearn-enough-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/costinEEST%2Flearn-enough-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/costinEEST%2Flearn-enough-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/costinEEST","download_url":"https://codeload.github.com/costinEEST/learn-enough-rails/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640472,"owners_count":20971558,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["book","book-exercises","michael-hartl","rails","rails-tutorial","rails7","ror","ruby","ruby-on-rails","ruby-tutorial"],"created_at":"2024-09-26T16:20:57.499Z","updated_at":"2026-01-20T11:32:11.898Z","avatar_url":"https://github.com/costinEEST.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"- https://aws.amazon.com/cloud9\n- https://eu-south-1.console.aws.amazon.com/cloud9/home/product?ad=c\u0026cp=bn\u0026p=c9\u0026region=eu-south-1#\n- https://eu-south-1.console.aws.amazon.com/cloud9/ide/cf7e24b3df894167a884d128c4695a65\n\n```bash\nrvm get stable\n```\n\n```bash\nrvm install 3.1.2\n```\n\n```bash\nrvm --default use 3.1.2\n```\n\n```bash\necho \"gem: --no-document\" \u003e\u003e .gemrc\n```\n\n```bash\ngem install rails -v 7.0.3\n```\n\n```bash\ngem install bundler -v 2.3.15\n```\n\n```bash\nsource \u003c(curl -sL https://cdn.learnenough.com/resize)\n```\n\n```bash\nrails _7.0.3_ new hello_app --skip-bundle\n```\n\n- As of `Rails 6` and continuing in `Rails 7`, running `rails new` automatically initializes a Git repository:\n\n```bash\nrm -r hello_app/.git\n```\n\n- This would install the latest version of the `capybara` gem (which is used in testing) as long as it’s greater than or equal to version `3.26`—even if it’s, say, version `7.2`.\n\n```bash\ngem \"capybara\", \"\u003e= 3.26\"\n```\n\n- This installs the gem `sqlite3` as long as it’s version `1.4` or newer (a “minor update”) but not `2` or newer (a “major update”). In other words, the `\u003e=` notation always installs the latest gem as long as it meets the minimum version requirement, whereas the `~\u003e 1.4` notation will install `1.5` (if available) but not `2.0`.\n\n```bash\ngem \"sqlite3\", \"~\u003e 1.4\"\n```\n\n- https://github.com/learnenough/rails_tutorial_7th_edition_gemfiles\n\n```bash\ncd hello_app/ \u0026\u0026 bundle install\n```\n\n```bash\nbin/rails server\n```\n\n- To view the result of `rails server` on a native OS, paste the URL http://localhost:3000 into the address bar of your browser. On the cloud IDE, go to `Preview` and click on `Preview Running Application` and then open it in a full browser window or tab (https://cf7e24b3df894167a884d128c4695a65.vfs.cloud9.eu-south-1.amazonaws.com).\n\n- Look for all controllers available\n\n```bash\nls app/controllers/*_controller.rb\n```\n\n- Example of how to define the route root:\n\n```ruby\nroot \"controller_name#action_name\"\n```\n\n- Update Git on Cloud9:\n\n```bash\nsource \u003c(curl -sL https://cdn.learnenough.com/upgrade_git)\n```\n\n```bash\ngit config --global --list\n\ncredential.helper=!aws codecommit credential-helper $@\ncredential.usehttppath=true\ncore.editor=nano\n```\n\n- Configure the name and email fields for Git:\n\n```bash\n$ git config --global user.name \"Your Name\"\n$ git config --global user.email your.email@example.com\n```\n\n- Define the default branch's name:\n\n```bash\ngit config --global init.defaultBranch main\n```\n\n- Set up `git co` as a checkout alias:\n\n```bash\ngit config --global alias.co checkout\n```\n\n- Configure Git to remember passwords for a set length of time:\n\n```bash\ngit config --global credential.helper \"cache --timeout=86400\"\n```\n\n- Prevent the local installation of any production gems (which in this case consists of the `pg` gem):\n\n```bash\nbundle config\n```\n\n- Bundling without production gems:\n\n```bash\nbundle _2.3.14_ config set --local without 'production'\n```\n\n```bash\nbundle _2.3.14_ install\n```\n\n```bash\nbundle _2.3.14_ lock --add-platform x86_64-linux\n```\n\n- See if your system already has the Heroku command-line client installed:\n\n```bash\nheroku --version\n```\n\n- Install Heroku on the cloud IDE:\n\n```bash\nsource \u003c(curl -sL https://cdn.learnenough.com/heroku_install)\n```\n\n- https://devcenter.heroku.com/articles/heroku-cli#install-the-heroku-cli\n\n- On a native system:\n\n```bash\nheroku login\n```\n\n- On the cloud IDE:\n\n```bash\nheroku login --interactive\n\nEmail: \u003cyour email\u003e\nPassword: \u003cyour API Key, NOT your Heroku password\u003e\n```\n\n- Create and configure a new application at Heroku:\n\n```bash\nheroku create\n```\n\n- Push the main branch up to Heroku:\n\n```bash\ngit push heroku main\n```\n\n- If something goes wrong, inspect the logs:\n\n```bash\nheroku logs\n```\n\n- Get info about the Heroku app, including the Web URL:\n\n```bash\nheroku apps:info\n```\n\n- https://young-badlands-92881.herokuapp.com\n- https://www.learnenough.com/custom-domains\n\n- Generate a random subdomain with Ruby:\n\n```ruby\n('a'..'z').to_a.shuffle[0..7].join\n```\n\n- Rename the application\n\n```bash\nheroku rename learn-enough-rails_hello-app\n```\n\n- https://learn-enough-rails-hello-app.herokuapp.com\n- [David Heinemeier Hansson using scaffolding in Rails](https://youtu.be/Gzj723LkRJY)\n\n```bash\nrails new toy_app --skip-bundle\n```\n\n```bash\ncd toy_app\n```\n\n```bash\nbundle config set --local without 'production'\n```\n\n```bash\nbundle install\n```\n\n- https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig + https://stackoverflow.com/a/54696441/1904223 + https://youtu.be/_fcQDS1iTPw\n\n```bash\ntoy_app/bin/rails s\n```\n\n```bash\ngit commit -am \"Add hello\"\n```\n\n```bash\nheroku create\n```\n\n```bash\ngit push \u0026\u0026 git push heroku main\n```\n\n```bash\nheroku rename learn-enough-rails-toy-app\n```\n\n- https://learn-enough-rails-toy-app.herokuapp.com + https://dashboard.heroku.com/apps/learn-enough-rails-toy-app\n\n```bash\nrails generate scaffold User name:string email:string\n```\n\n```bash\nrails db:migrate\n```\n\n```bash\nheroku run rails db:migrate\n```\n\n- The correspondence between pages and URLs for the Users resource:\n\n| URL             | Action | Purpose                     |\n| --------------- | ------ | --------------------------- |\n| `/users`        | index  | page to list all users      |\n| `/users/1`      | show   | page to show user with id 1 |\n| `/users/new`    | new    | page to make a new user     |\n| `/users/1/edit` | edit   | page to edit user with id 1 |\n\n- RESTful routes provided by the Users resource:\n\n| HTTP request method | URL             | Action | Purpose                     |\n| ------------------- | --------------- | ------ | --------------------------- |\n| GET                 | `/users`        | index  | page to list all users      |\n| GET                 | `/users/1`      | show   | page to show user with id 1 |\n| GET                 | `/users/new`    | new    | page to make a new user     |\n| POST                | `/users`        | create | create a new user           |\n| GET                 | `/users/1/edit` | edit   | page to edit user with id 1 |\n| PATCH               | `/users/1`      | update | update user with id 1       |\n| DELETE              | `/users/1`      | delete | delete user with id 1       |\n\n```bash\nrails generate scaffold Micropost content:text user_id:integer\n```\n\n```bash\nrails db:migrate\n```\n\n- Undo a single migration step:\n\n```bash\nrails db:rollback\n```\n\n- Go all the way back to the beginning:\n\n```bash\nrails db:migrate VERSION=0\n```\n\n- Try to insert a text longer than 140 characters into the `Content` textarea at `http://127.0.0.1:3000/microposts/new` then submit the form.\n\n```bash\ncd toy_app \u0026\u0026 rails console\n```\n\n```ruby\nUser.first\n```\n\n```ruby\nUser.create!(name: 'Cos', email: 'mail@costi.com')\n```\n\n```ruby\nmicropost = User.first.microposts.first\n```\n- The inheritance hierarchy for the User and Micropost models:\n\n![The inheritance hierarchy for the User and Micropost models](https://softcover.s3.amazonaws.com/636/ruby_on_rails_tutorial_7th_edition/images/figures/demo_model_inheritance_4th_ed.png \"The inheritance hierarchy for the User and Micropost models\")\n\n- The inheritance hierarchy for the Users and Microposts controllers:\n\n![The inheritance hierarchy for the Users and Microposts controllers](https://softcover.s3.amazonaws.com/636/ruby_on_rails_tutorial_7th_edition/images/figures/demo_controller_inheritance.png \"The inheritance hierarchy for the Users and Microposts controllers\")\n\n```ruby\nrails new sample_app --skip-bundle\n```\n\n```ruby\nrm -rf sample_app/.git\n```\n- [Download from Github using curl](https://gist.github.com/jwebcat/5122366?permalink_comment_id=3404474#gistcomment-3404474)\n\n```bash\ncurl --location --remote-header-name https://raw.githubusercontent.com/learnenough/rails_tutorial_7th_edition_gemfiles/master/sample_app/Gemfile_initial --output sample_app/Gemfile\n```\n- Skip the `pg` gem for PostgreSQL in development and use SQLite for development and testing:\n\n```bash\nbundle config set --local without 'production'\n```\n\n```bash\nbundle install\n```\n\n- https://github.com/learnenough/rails_tutorial_sample_app_7th_ed/blob/main/README.md\n- [Easily include static pages in your Rails app](https://github.com/thoughtbot/high_voltage)\n\n```bash\nrails generate controller StaticPages home help\n```\n- The inheritance hierarchy for the Static Pages:\n\n![The inheritance hierarchy for the Static Pages.](https://softcover.s3.amazonaws.com/636/ruby_on_rails_tutorial_7th_edition/images/figures/static_pages_controller_inheritance.png \"The inheritance hierarchy for the Static Pages.\")\n\n- Undo the created controller:\n\n```bash\nrails destroy controller StaticPages home help\n```\n\n- Rails shortcuts:\n\n| Full command     | Shortcut  |\n| ---------------- | --------- |\n| `rails server`   | `rails s` |\n| `rails console`  | `rails c` |\n| `rails generate` | `rails g` |\n| `rails test`     | `rails t` |\n| `bundle install` | `bundle`  |\n\n- http://127.0.0.1:3000/static_pages/home\n- http://127.0.0.1:3000/static_pages/help\n- https://dhh.dk/2014/tdd-is-dead-long-live-testing.html\n\n```bash\nmv app/views/layouts/application.html.erb layout_file\n```\n\n- https://stackoverflow.com/questions/27814500/ruby-on-rails-provide-vs-content-for\n\n```bash\nmv layout_file app/views/layouts/application.html.erb\n```\n\n- https://github.com/kern/minitest-reporters\n- https://github.com/guard/guard\n- https://www.railstutorial.org/guardfile\n\n```bash\nbundle exec guard init\n```\n\n```bash\ncurl --location --remote-header-name https://raw.githubusercontent.com/learnenough/rails_tutorial_sample_app_7th_ed/main/Guardfile --output Guardfile\n```\n\n```bash\nbundle exec guard\n```\n\n- https://www.learnenough.com/ruby\n- https://en.wikipedia.org/wiki/Media_type\n- https://en.wikipedia.org/wiki/Abstraction_layer\n- [stylesheet_link_tag(*sources)](https://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-stylesheet_link_tag)\n- https://www.learnenough.com/text-editor\n\n```bash\nnano ~/.irbrc\n```\n\n```bash\ncat ~/.irbrc\n\nIRB.conf[:PROMPT_MODE] = :SIMPLE\nIRB.conf[:AUTO_INDENT_MODE] = false\n```\n\n```bash\nrails console\n```\n\n```bash\ncurl -o app/assets/images/rails.svg -L https://cdn.learnenough.com/rails.svg\n```\n\n```bash\ncurl -OL https://cdn.learnenough.com/kitten.jpg\n```\n\n```bash\ntouch app/assets/stylesheets/custom.scss\n```\n- https://github.com/rails/sprockets/blob/main/guides/how_sprockets_works.md\n- Inside of `sample_app\\app\\assets\\stylesheets\\application.css` the line `*= require_tree .` ensures that all CSS files in the `app/assets/stylesheets` directory (including the tree subdirectories) are included into the `application.css`. The line `*= require_self` specifies where in the loading sequence the CSS in `application.css` itself gets included.\n\n- Route and URL mapping for site links:\n\n| Page    | URL      | Named route  |\n| ------- | -------- | ------------ |\n| Home    | /        | root_path    |\n| About   | /about   | about_path   |\n| Help    | /help    | help_path    |\n| Contact | /contact | contact_path |\n| Sign up | /signup  | signup_path  |\n| Log in  | /login   | login_path   |\n\n-  Generate a template test, called 'site_layout':\n\n```bash\nrails generate integration_test site_layout\n```\n\n- https://www.rubydoc.info/gems/capybara/Capybara%2FNode%2FMatchers:assert_selector\n\n```bash\nrails test:integration\n```\n\n```bash\nrails generate controller Users new\n```\n\n- https://github.com/heartcombo/devise#starting-with-rails\n\n```bash\nrails generate model User name:string email:string\n```\n\n```bash\nrails db:migrate\n```\n\n- [DB Browser for SQLite](https://sqlitebrowser.org)\n\n- Explore the data models is the Rails console:\n\n```bash\nrails console --sandbox\n```\n\n```ruby\nuser = User.new\n```\n\n```ruby\nuser.valid?\n```\n\n-  Save the User object to the database:\n\n```ruby\nuser.save\n```\n\n- Find User by id:\n\n```ruby\nUser.find(1)\n```\n\n- Active Record allows to find users by specific attributes:\n\n```ruby\nUser.find_by(email: 'michael@example.com')\n```\n\n```ruby\nUser.first\n```\n\n```ruby\nUser.first\n```\n\n```ruby\nuser.email = \"mhartl@example.net\"\n```\n\n```ruby\nuser.email = \"mhartl@example.net\"\n```\n\n```ruby\nuser.save\n```\n\n```ruby\nuser.reload.email\n```\n\n\n```ruby\nuser.update(name: \"The Dude\", email: \"dude@abides.org\")\n```\n\n```bash\nrails test:models\n```\n\n```bash\nrails console --sandbox\n```\n\n```ruby\nuser = User.new(name: \"\", email: \"michael@example.com\")\n\nuser.valid?\n\nuser.errors.full_messages\n```\n\n- [Rubular: a Ruby regular expression editor](https://rubular.com)\n\n```bash\nrails generate migration add_index_to_users_email\n```\n\n```bash\nrails db:migrate\n```\n\n- https://en.wikipedia.org/wiki/Hash_function\n- https://en.wikipedia.org/wiki/Cryptographic_hash_function\n\n```bash\nrails generate migration add_password_digest_to_users password_digest:string\n```\n\n- https://en.wikipedia.org/wiki/Bcrypt\n- https://github.com/bcrypt-ruby/bcrypt-ruby\n\n```bash\nbundle install\n```\n\n- Creating and authenticating a user:\n\n```bash\nrails console\n```\n\n```ruby\nUser.create(name: \"Cos tin\", email: \"costin@ymail.com\", password: \"testingPwd\", password_confirmation: \"testingPwd\")\n```\n\n```ruby\nUser.find_by(email: 'costin@ymail.com').password_digest\n```\n\n```ruby\nUser.find_by(email: 'costin@ymail.com').authenticate('wrongPwd')\n```\n\n```ruby\nUser.find_by(email: 'costin@ymail.com').authenticate('testingPwd')\n```\n\n```ruby\n!!User.find_by(email: 'costin@ymail.com').authenticate('testingPwd')\n```\n\n- Rails comes equipped with three environments: `test`, `development`, and `production`. The default environment for the Rails console is `development`.\n\n- To run a console in a different environment (to debug a test, for example), you can pass the environment as an option to the console `script`:\n\n```bash\nrails console --environment test\n```\n\n- If you have deployed your sample app to Heroku, you can see its environment using `heroku run rails console`.\n\n```ruby\nputs User.find_by(email: 'costin@ymail.com').attributes.to_yaml\n```\nor\n\n```ruby\ny User.find_by(email: 'costin@ymail.com').attributes\n```\n\n- A `Users` resource:\n\n```ruby\nUser.count\n```\n\n```ruby\nUser.first\n```\n\n- [rdbg](https://blog.kiprosh.com/advanced-features-provided-by-new-debug-gem) + http://atdot.net/~ko1/activities/2021_rubyconf.pdf + https://edgeguides.rubyonrails.org/debugging_rails_applications.html#entering-a-debugging-session\n\n```ruby\n(rdbg) @user.name\n\"Cos tin\"\n(rdbg) @user.email\n\"costin@ymail.com\"\n(rdbg)\n```\n\n- [Gravatar URLs are based on an MD5 hash of the user's email address](http://en.gravatar.com/site/implement/hash)\n- https://rubyapi.org/3.1/o/digest/md5\n- https://rubyapi.org/3.1/o/string#method-i-downcase\n- https://rubyapi.org/3.1/o/string#method-i-strip\n- https://api.rubyonrails.org/classes/String.html#method-i-squish\n\n```bash\nrails console\n```\n\n```ruby\nuser = User.first\n\nuser.update(name: 'Constantin', email: \"constantin@gmail.com\", password: \"parolaDemo\", password_confirmation: 'parolaDemo')\n```\n\n- https://thoughtbot.com/upcase/videos/ruby-keyword-arguments\n- https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with\n- Soft-deprecated:\n  - https://guides.rubyonrails.org/form_helpers.html#using-form-tag-and-form-for\n  - https://github.com/rails/rails/issues/25197\n  - https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for\n  - https://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-form_tag\n- https://stackoverflow.com/questions/941594/understanding-the-rails-authenticity-token\n- http://www.railsstatuscodes.com/unprocessable_entity.html\n- https://guides.rubyonrails.org/layouts_and_rendering.html#the-status-option\n- https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-require\n- https://api.rubyonrails.org/classes/ActionController/Parameters.html#method-i-permit\n- http://127.0.0.1:3000/signup?admin=1\n\n```ruby\nuser = User.new(name: \"The coder\", email: \"mail@void\", password: \"ruby\", password_confirmation: \"ruby\")\n\nuser.save\n\nuser.errors.full_messages\n```\n\n- https://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-any-3F\n- https://api.rubyonrails.org/classes/ActiveRecord/Associations/CollectionProxy.html#method-i-empty-3F\n- https://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-pluralize\n\n```bash\nrails generate integration_test users_signup\n```\n\n- https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-redirect_to\n- https://api.rubyonrails.org/classes/ActionDispatch/Flash.html\n\n- Reset the database:\n\n```bash\nrails db:migrate:reset\n```\n\n- https://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_difference\n- https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag\n- [SSL (Secure Sockets Layer) is now TLS (Transport Layer Security)](https://en.wikipedia.org/wiki/Transport_Layer_Security)\n- https://www.learnenough.com/custom-domains\n- https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server\n- https://devcenter.heroku.com/articles/getting-started-with-rails6\n\n- Production deployment:\n```bash\nrails test\ngit add -A\ngit commit -m \"Use SSL and the Puma web server in production\"\ngit push \u0026\u0026 git push heroku\nheroku run rails db:migrate\n```\n\n- How to reset the production database:\n\n```bash\nheroku pg:reset DATABASE\nheroku run rails db:migrate\n```\n\n- [URL for the production version of chapter 7 (sign up)](https://safe-spire-86804.herokuapp.com)\n\n- Generate the Sessions controller:\n\n```bash\nrails generate controller Sessions new\n```\n\n```bash\nrails routes -c users\n   Prefix Verb   URI Pattern               Controller#Action\n   signup GET    /signup(.:format)         users#new\n    users GET    /users(.:format)          users#index\n          POST   /users(.:format)          users#create\n new_user GET    /users/new(.:format)      users#new\nedit_user GET    /users/:id/edit(.:format) users#edit\n     user GET    /users/:id(.:format)      users#show\n          PATCH  /users/:id(.:format)      users#update\n          PUT    /users/:id(.:format)      users#update\n          DELETE /users/:id(.:format)      users#destroy\n```\n\n```bash\nrails routes -c sessions\n      Prefix Verb   URI Pattern             Controller#Action\nsessions_new GET    /sessions/new(.:format) sessions#new\n       login GET    /login(.:format)        sessions#new\n             POST   /login(.:format)        sessions#create\n      logout DELETE /logout(.:format)       sessions#destroy\n```\n\n```bash\ncurl -I http://127.0.0.1:3000 | grep Set-Cookie\n```\n\n- https://guides.rubyonrails.org/security.html#session-storage\n- https://guides.rubyonrails.org/security.html#replay-attacks-for-cookiestore-sessions\n- https://guides.rubyonrails.org/action_controller_overview.html#session\n- https://github.com/rails/activerecord-session_store\n- https://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-find_by\n\n```bash\nrails generate integration_test users_login\n```\n\n- [Session replay attack](https://guides.rubyonrails.org/security.html#session-hijacking)\n- https://guides.rubyonrails.org/security.html#session-fixation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcostineest%2Flearn-enough-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcostineest%2Flearn-enough-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcostineest%2Flearn-enough-rails/lists"}