├── .all-contributorsrc
├── .dockerignore
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── docker-compose.yml
├── docs
├── devise
│ ├── activejob-integration.md
│ ├── additional_information.md
│ ├── bug_reports.md
│ ├── configuring-controllers.md
│ ├── configuring-models.md
│ ├── configuring-multiple-models.md
│ ├── configuring-routes.md
│ ├── configuring-views.md
│ ├── contributing.md
│ ├── controller_filters_and_helpers.md
│ ├── example_applications.md
│ ├── extensions.md
│ ├── guides-list.md
│ ├── i18n.md
│ ├── installation.md
│ ├── omniauth.md
│ ├── other-orms.md
│ ├── overview.md
│ ├── password-reset-tokens-and-rails-logs.md
│ ├── rails-api-mode.md
│ ├── starting_with_rails.md
│ ├── strong-parameters.md
│ └── test-helpers.md
└── rails
│ ├── action_cable_overview.md
│ ├── action_controller_overview.md
│ ├── action_mailbox_basics.md
│ ├── action_mailer_basics.md
│ ├── action_text_overview.md
│ ├── action_view_overview.md
│ ├── active_job_basics.md
│ ├── active_model_basics.md
│ ├── active_record_basics.md
│ ├── active_record_callbacks.md
│ ├── active_record_migrations.md
│ ├── active_record_multiple_databases.md
│ ├── active_record_postgresql.md
│ ├── active_record_querying.md
│ ├── active_record_validations.md
│ ├── active_storage_overview.md
│ ├── active_support_core_extensions.md
│ ├── active_support_instrumentation.md
│ ├── api_app.md
│ ├── api_documentation_guidelines.md
│ ├── asset_pipeline.md
│ ├── association_basics.md
│ ├── autoloading_and_reloading_constants.md
│ ├── caching_with_rails.md
│ ├── command_line.md
│ ├── configuring.md
│ ├── contributing_to_ruby_on_rails.md
│ ├── debugging_rails_applications.md
│ ├── development_dependencies_install.md
│ ├── engines.md
│ ├── form_helpers.md
│ ├── generators.md
│ ├── getting_started.md
│ ├── i18n.md
│ ├── initialization.md
│ ├── layouts_and_rendering.md
│ ├── maintenance_policy.md
│ ├── plugins.md
│ ├── rails_application_templates.md
│ ├── rails_on_rack.md
│ ├── routing.md
│ ├── ruby_on_rails_guides_guidelines.md
│ ├── security.md
│ ├── testing.md
│ ├── threading_and_code_execution.md
│ └── working_with_javascript_in_rails.md
├── package-lock.json
├── package.json
└── website
├── README.md
├── blog
├── 2016-03-11-blog-post.md
├── 2017-04-10-blog-post-two.md
├── 2017-09-25-testing-rss.md
├── 2017-09-26-adding-rss.md
└── 2017-10-24-new-version-1.0.0.md
├── core
└── Footer.js
├── package-lock.json
├── package.json
├── pages
└── en
│ └── index.js
├── sidebars.json
├── siteConfig.js
└── static
├── css
└── custom.css
└── img
├── favicon.ico
├── logo-rails-setup.png
├── oss_logo.png
├── rails-setup-logo-red.png
├── rails-setup-logo-white.png
├── undraw_books.svg
├── undraw_code_review.svg
├── undraw_monitor.svg
├── undraw_note_list.svg
├── undraw_online.svg
├── undraw_open_source.svg
├── undraw_operating_system.svg
├── undraw_react.svg
├── undraw_tweetstorm.svg
└── undraw_youtube_tutorial.svg
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "rails-setup",
3 | "projectOwner": "HenryTabima",
4 | "repoType": "github",
5 | "repoHost": "https://github.com",
6 | "files": [
7 | "README.md"
8 | ],
9 | "imageSize": 100,
10 | "commit": true,
11 | "commitConvention": "none",
12 | "contributors": [
13 | {
14 | "login": "HenryTabima",
15 | "name": "Henry Tabima Giraldo",
16 | "avatar_url": "https://avatars0.githubusercontent.com/u/12721896?v=4",
17 | "profile": "http://henrytabima.com",
18 | "contributions": [
19 | "doc"
20 | ]
21 | }
22 | ],
23 | "contributorsPerLine": 7
24 | }
25 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | */node_modules
2 | *.log
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | node_modules
4 |
5 | lib/core/metadata.js
6 | lib/core/MetadataBlog.js
7 |
8 | website/translated_docs
9 | website/build/
10 | website/yarn.lock
11 | website/node_modules
12 | website/i18n/*
13 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies within all project spaces, and it also applies when
49 | an individual is representing the project or its community in public spaces.
50 | Examples of representing a project or community include using an official
51 | project e-mail address, posting via an official social media account, or acting
52 | as an appointed representative at an online or offline event. Representation of
53 | a project may be further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | First off, thank you for considering contributing to Rails-Setup. It’s people like you that make this project great.
4 |
5 | ## How to
6 |
7 | * Make sure that nobody else is already working on what you want to contribute (check Issues and PRs).
8 | * Raise an issue explaining what you want in the project and if you are going to take care of it.
9 | * fork the project and work on a different branch from master.
10 | * send a pull request
11 |
12 | ## Type of contributions
13 |
14 | * [Misspelling fixes](#misspelling-fixes)
15 | * [Fix documentation issues](#fix-documentation-issues)
16 | * [Add documentation for common Rails related libraries](#add-documentation-for-common-rails-related-libraries)
17 | * [Enhancing the website](#enhancing-the-website)
18 |
19 | ### Misspelling fixes
20 |
21 | As humans we are prone to erros, including misspelling. if you see any please rise an issue.
22 |
23 | ### Fix documentation issues
24 |
25 | Most of the documentation added is just copied from the original projects, sometimes it comes with links to images and another pages that get broke once you put in here. you can help fixing that kind of things.
26 |
27 | ### Add documentation for common Rails related libraries
28 |
29 | You could bring here documentation from another project that usually dont have their own documentation website or maybe their website is not friendly enough.
30 |
31 | ### Enhancing the website
32 |
33 | If you have cool ideas to imporve the look and feel of the index or any other page, please raise an issue explaining what do you have in mind.
34 |
35 | ## Roadmap
36 |
37 | the idea is to have documentatios by topic and library. like:
38 |
39 | * Rails
40 | * Authentication
41 | * devise
42 | * jwt
43 | * others libraries...
44 | * Testing
45 | * minitest
46 | * rspec
47 | * others...
48 | * Commonly used
49 | * Faker
50 | * Factory bot
51 |
52 | The ultimate goal is to have all what you need to achieve whatever you want in your rails project. All in one place. all easy to navigate.
53 |
54 | ## Getting in touch
55 |
56 | Feel free to get in touch. send me an email, or even better, tweet me [@HenryTabimaG](https://twitter.com/HenryTabimaG)
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:8.11.4
2 |
3 | WORKDIR /app/website
4 |
5 | EXPOSE 3000 35729
6 | COPY ./docs /app/docs
7 | COPY ./website /app/website
8 | RUN yarn install
9 |
10 | CMD ["yarn", "start"]
11 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019-present, Henry Tabima Giraldo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Rails Setup
2 | [](#contributors)
3 |
4 | [Visit Rails-Setup website](https://HenryTabima.github.io/rails-setup)
5 |
6 | this is a Project to collect in one place and in a friendly way the documentation for rails and commonly used related libraries
7 |
8 | ## Getting started
9 |
10 | this site is built on top of docusaurus, [see respective documentation](https://docusaurus.io/docs/en/next/installation) to getting started with this project.
11 |
12 | ## Contributing
13 |
14 | We appreciate any contribution you would like to do. To know what you can do the steps to do it, please follow the [contribution guidelines](CONTRIBUTING.md).
15 |
16 | Summary:
17 | * Make sure that nobody else is already working on what you want to contribute (check Issues and PRs).
18 | * Raise an issue explaining what you want in the project and if you are going to take care of it.
19 | * fork the project and work on a different branch from master.
20 | * send a pull request
21 |
22 | ## Todos
23 |
24 | List of possible contributions that you can do to this project
25 |
26 | * add a list of the projects added to the rails-setup website and their last update date
27 | * fix the broken URLs in the links of the rails documentation files (they are just as I copied from the source documentation site)
28 | * add documentation for other common project used with rails (like devise, factory bot and others)
29 |
30 | ## Code of conduct
31 |
32 | Read it in detail [here](CODE_OF_CONDUCT.md).
33 |
34 | ## License
35 |
36 | This project is under [MIT license](LICENSE.md)
37 |
38 | ## Contributors
39 |
40 |
41 |
42 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 |
3 | services:
4 | docusaurus:
5 | build: .
6 | ports:
7 | - 3000:3000
8 | - 35729:35729
9 | volumes:
10 | - ./docs:/app/docs
11 | - ./website/blog:/app/website/blog
12 | - ./website/core:/app/website/core
13 | - ./website/i18n:/app/website/i18n
14 | - ./website/pages:/app/website/pages
15 | - ./website/static:/app/website/static
16 | - ./website/sidebars.json:/app/website/sidebars.json
17 | - ./website/siteConfig.js:/app/website/siteConfig.js
18 | working_dir: /app/website
19 |
--------------------------------------------------------------------------------
/docs/devise/activejob-integration.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: activejob-integration
3 | title: ActiveJob integration
4 | ---
5 |
6 | If you are using Rails 4.2 and ActiveJob to deliver ActionMailer messages in the
7 | background through a queuing back-end, you can send Devise emails through your
8 | existing queue by overriding the `send_devise_notification` method in your model.
9 |
10 | ```ruby
11 | def send_devise_notification(notification, *args)
12 | devise_mailer.send(notification, self, *args).deliver_later
13 | end
14 | ```
--------------------------------------------------------------------------------
/docs/devise/additional_information.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: additional-information
3 | title: Additional information
4 | ---
5 |
6 | ## Heroku
7 |
8 | Using Devise on Heroku with Ruby on Rails 3.2 requires setting:
9 |
10 | ```ruby
11 | config.assets.initialize_on_precompile = false
12 | ```
13 |
14 | Read more about the potential issues at http://guides.rubyonrails.org/asset_pipeline.html
15 |
16 | ## Warden
17 |
18 | Devise is based on Warden, which is a general Rack authentication framework created by Daniel Neighman. We encourage you to read more about Warden here:
19 |
20 | https://github.com/hassox/warden
21 |
22 | ## DEVISE_ORM
23 |
24 |
25 | ## BUNDLE_GEMFILE
26 | We can use this variable to tell bundler what Gemfile it should use (instead of the one in the current directory).
27 | Inside the [gemfiles](https://github.com/plataformatec/devise/tree/master/gemfiles) directory, we have one for each version of Rails we support. When you send us a pull request, it may happen that the test suite breaks on Travis using some of them. If that's the case, you can simulate the same environment using the `BUNDLE_GEMFILE` variable.
28 | For example, if the tests broke using Ruby 2.4.2 and Rails 4.1, you can do the following:
29 | ```bash
30 | rbenv shell 2.4.2 # or rvm use 2.4.2
31 | BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bundle install
32 | BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bin/test
33 | ```
34 |
35 | You can also combine both of them if the tests broke for Mongoid:
36 | ```bash
37 | BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable bundle install
38 | BUNDLE_GEMFILE=gemfiles/Gemfile.rails-4.1-stable DEVISE_ORM=mongoid bin/test
39 | ```
40 |
--------------------------------------------------------------------------------
/docs/devise/bug_reports.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: bug-reports
3 | title: Bug reports
4 | ---
5 | If you were linked to this page from Github Issues Tracker or Mailing List, don't worry! We still love you and want your feedback, but you may have left some important information out of your report. Please read below.
6 |
7 | First off: if you have questions about Devise, please search the Wiki and Google Group to see if your questions have already been answered. If not, please post your questions to the Google Group. *Do not use the GitHub Issues tracker for questions*
8 |
9 | 1) Before submitting a bug report:
10 |
11 | * Ensure you are using latest devise version. If you are using Devise from git repository with bundler, be sure to run `bundle update`. Maybe your error was already fixed.
12 | * Search the existing GitHub Issues to make sure your issue hasn't already been reported. If not, proceed.
13 | * If you found a security bug, do *NOT* use the GitHub Issue tracker. Please send an email to opensource@plataformatec.com.br.
14 |
15 | 2) When submitting a bug report:
16 |
17 | * Include Ruby, Warden, Devise, OrmAdapter (if using Devise 1.2 forward) and Rails versions in the report;
18 | * Include oauth2 and faraday gem versions if using OAuth;
19 | * Include error class, message and backtrace if you are getting an error;
20 |
21 | 3) The information above can help us spot an obvious bug, however most bugs may require you to investigate deeper. In such cases:
22 |
23 | * Please try to reproduce the bug in devise test suite. Devise test suite is a Rails application as any other (check test/rails_app in the repository) making it easy to reproduce bugs;
24 | * Or try to isolate the bug in a smaller application and push it to github;
25 |
26 | Remember that this is an open-source project, and the contributions of volunteers have made it possible. Please be polite and provide as much information as possible so that we can help you!
27 |
28 | 4) Our Issues Tracker is available here:
29 |
30 | http://github.com/plataformatec/devise/issues
31 |
--------------------------------------------------------------------------------
/docs/devise/configuring-controllers.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: configuring-controllers
3 | title: Configuring controllers
4 | ---
5 |
6 | If the customization at the views level is not enough, you can customize each controller by following these steps:
7 |
8 | 1. Create your custom controllers using the generator which requires a scope:
9 |
10 | ```console
11 | $ rails generate devise:controllers [scope]
12 | ```
13 |
14 | If you specify `users` as the scope, controllers will be created in `app/controllers/users/`.
15 | And the sessions controller will look like this:
16 |
17 | ```ruby
18 | class Users::SessionsController < Devise::SessionsController
19 | # GET /resource/sign_in
20 | # def new
21 | # super
22 | # end
23 | ...
24 | end
25 | ```
26 | (Use the -c flag to specify a controller, for example: `rails generate devise:controllers users -c=sessions`)
27 |
28 | 2. Tell the router to use this controller:
29 |
30 | ```ruby
31 | devise_for :users, controllers: { sessions: 'users/sessions' }
32 | ```
33 |
34 | 3. Copy the views from `devise/sessions` to `users/sessions`. Since the controller was changed, it won't use the default views located in `devise/sessions`.
35 |
36 | 4. Finally, change or extend the desired controller actions.
37 |
38 | You can completely override a controller action:
39 |
40 | ```ruby
41 | class Users::SessionsController < Devise::SessionsController
42 | def create
43 | # custom sign-in code
44 | end
45 | end
46 | ```
47 |
48 | Or you can simply add new behaviour to it:
49 |
50 | ```ruby
51 | class Users::SessionsController < Devise::SessionsController
52 | def create
53 | super do |resource|
54 | BackgroundWorker.trigger(resource)
55 | end
56 | end
57 | end
58 | ```
59 |
60 | This is useful for triggering background jobs or logging events during certain actions.
61 |
62 | Remember that Devise uses flash messages to let users know if sign in was successful or unsuccessful. Devise expects your application to call `flash[:notice]` and `flash[:alert]` as appropriate. Do not print the entire flash hash, print only specific keys. In some circumstances, Devise adds a `:timedout` key to the flash hash, which is not meant for display. Remove this key from the hash if you intend to print the entire hash.
63 |
--------------------------------------------------------------------------------
/docs/devise/configuring-models.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: configuring-models
3 | title: Configuring Models
4 | ---
5 |
6 | The Devise method in your models also accepts some options to configure its modules. For example, you can choose the cost of the hashing algorithm with:
7 |
8 | ```ruby
9 | devise :database_authenticatable, :registerable, :confirmable, :recoverable, stretches: 12
10 | ```
11 |
12 | Besides `:stretches`, you can define `:pepper`, `:encryptor`, `:confirm_within`, `:remember_for`, `:timeout_in`, `:unlock_in` among other options. For more details, see the initializer file that was created when you invoked the "devise:install" generator described above. This file is usually located at `/config/initializers/devise.rb`.
13 |
--------------------------------------------------------------------------------
/docs/devise/configuring-multiple-models.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: configuring-multiple-models
3 | title: Configuring multiple models
4 | ---
5 |
6 | Devise allows you to set up as many Devise models as you want. If you want to have an Admin model with just authentication and timeout features, in addition to the User model above, just run:
7 |
8 | ```ruby
9 | # Create a migration with the required fields
10 | create_table :admins do |t|
11 | t.string :email
12 | t.string :encrypted_password
13 | t.timestamps null: false
14 | end
15 |
16 | # Inside your Admin model
17 | devise :database_authenticatable, :timeoutable
18 |
19 | # Inside your routes
20 | devise_for :admins
21 |
22 | # Inside your protected controller
23 | before_action :authenticate_admin!
24 |
25 | # Inside your controllers and views
26 | admin_signed_in?
27 | current_admin
28 | admin_session
29 | ```
30 |
31 | Alternatively, you can simply run the Devise generator.
32 |
33 | Keep in mind that those models will have completely different routes. They **do not** and **cannot** share the same controller for sign in, sign out and so on. In case you want to have different roles sharing the same actions, we recommend that you use a role-based approach, by either providing a role column or using a dedicated gem for authorization.
--------------------------------------------------------------------------------
/docs/devise/configuring-routes.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: configuring-routes
3 | title: Configuring routes
4 | ---
5 |
6 |
7 | Devise also ships with default routes. If you need to customize them, you should probably be able to do it through the devise_for method. It accepts several options like :class_name, :path_prefix and so on, including the possibility to change path names for I18n:
8 |
9 | ```ruby
10 | devise_for :users, path: 'auth', path_names: { sign_in: 'login', sign_out: 'logout', password: 'secret', confirmation: 'verification', unlock: 'unblock', registration: 'register', sign_up: 'cmon_let_me_in' }
11 | ```
12 |
13 | Be sure to check `devise_for` [documentation](http://www.rubydoc.info/github/plataformatec/devise/master/ActionDispatch/Routing/Mapper%3Adevise_for) for details.
14 |
15 | If you have the need for more deep customization, for instance to also allow "/sign_in" besides "/users/sign_in", all you need to do is create your routes normally and wrap them in a `devise_scope` block in the router:
16 |
17 | ```ruby
18 | devise_scope :user do
19 | get 'sign_in', to: 'devise/sessions#new'
20 | end
21 | ```
22 |
23 | This way, you tell Devise to use the scope `:user` when "/sign_in" is accessed. Notice `devise_scope` is also aliased as `as` in your router.
24 |
25 | Please note: You will still need to add `devise_for` in your routes in order to use helper methods such as `current_user`.
26 |
27 | ```ruby
28 | devise_for :users, skip: :all
29 | ```
30 |
--------------------------------------------------------------------------------
/docs/devise/configuring-views.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: configuring-views
3 | title: Configuring views
4 | ---
5 | We built Devise to help you quickly develop an application that uses authentication. However, we don't want to be in your way when you need to customize it.
6 |
7 | Since Devise is an engine, all its views are packaged inside the gem. These views will help you get started, but after some time you may want to change them. If this is the case, you just need to invoke the following generator, and it will copy all views to your application:
8 |
9 | ```console
10 | $ rails generate devise:views
11 | ```
12 |
13 | If you have more than one Devise model in your application (such as `User` and `Admin`), you will notice that Devise uses the same views for all models. Fortunately, Devise offers an easy way to customize views. All you need to do is set `config.scoped_views = true` inside the `config/initializers/devise.rb` file.
14 |
15 | After doing so, you will be able to have views based on the role like `users/sessions/new` and `admins/sessions/new`. If no view is found within the scope, Devise will use the default view at `devise/sessions/new`. You can also use the generator to generate scoped views:
16 |
17 | ```console
18 | $ rails generate devise:views users
19 | ```
20 |
21 | If you would like to generate only a few sets of views, like the ones for the `registerable` and `confirmable` module,
22 | you can pass a list of modules to the generator with the `-v` flag.
23 |
24 | ```console
25 | $ rails generate devise:views -v registrations confirmations
26 | ```
--------------------------------------------------------------------------------
/docs/devise/contributing.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: contributing
3 | title: Contributing
4 | ---
5 | We hope that you will consider contributing to Devise. You can contribute in many ways. For example, you might:
6 |
7 | * add documentation and "how-to" articles to the README or Wiki.
8 | * help people with the questions they ask on the Google Group.
9 | * create an extension that provides additional functionality above and beyond Devise itself.
10 | * improve the existing example applications to demonstrate features in Devise.
11 | * improve and/or add new I18n translations
12 | * hack on Devise itself by fixing bugs you've found in the GitHub Issue tracker or adding new features to Devise.
13 |
14 | When contributing to Devise, we ask that you:
15 |
16 | * let us know what you plan in the GitHub Issue tracker so we can provide feedback.
17 | * provide tests and documentation whenever possible. It is very unlikely that we will accept new features or functionality into Devise without the proper testing and documentation. When fixing a bug, provide a failing test case that your patch solves.
18 | * open a GitHub Pull Request with your patches and we will review your contribution and respond as quickly as possible. Keep in mind that this is an open source project, and it may take us some time to get back to you. Your patience is very much appreciated.
19 |
20 | We have a long list of valued contributors. Check them all at:
21 |
22 | http://github.com/plataformatec/devise/contributors
23 |
24 | = Testing
25 |
26 | You can run the entire test suite with the default rake task:
27 |
28 | ```
29 | rake
30 | ```
31 |
32 | To run a single test, specify the file in the `TEST` environment variable:
33 |
34 | ```
35 | rake test TEST=test/controllers/passwords_controller_test.rb
36 | ```
--------------------------------------------------------------------------------
/docs/devise/controller_filters_and_helpers.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: controller-filters-and-helpers
3 | title: Controller filters and helpers
4 | ---
5 |
6 | Devise will create some helpers to use inside your controllers and views. To set up a controller with user authentication, just add this before_action (assuming your devise model is 'User'):
7 |
8 | ```ruby
9 | before_action :authenticate_user!
10 | ```
11 |
12 | For Rails 5, note that `protect_from_forgery` is no longer prepended to the `before_action` chain, so if you have set `authenticate_user` before `protect_from_forgery`, your request will result in "Can't verify CSRF token authenticity." To resolve this, either change the order in which you call them, or use `protect_from_forgery prepend: true`.
13 |
14 | If your devise model is something other than User, replace "_user" with "_yourmodel". The same logic applies to the instructions below.
15 |
16 | To verify if a user is signed in, use the following helper:
17 |
18 | ```ruby
19 | user_signed_in?
20 | ```
21 |
22 | For the current signed-in user, this helper is available:
23 |
24 | ```ruby
25 | current_user
26 | ```
27 |
28 | You can access the session for this scope:
29 |
30 | ```ruby
31 | user_session
32 | ```
33 |
34 | After signing in a user, confirming the account or updating the password, Devise will look for a scoped root path to redirect to. For instance, when using a `:user` resource, the `user_root_path` will be used if it exists; otherwise, the default `root_path` will be used. This means that you need to set the root inside your routes:
35 |
36 | ```ruby
37 | root to: 'home#index'
38 | ```
39 |
40 | You can also override `after_sign_in_path_for` and `after_sign_out_path_for` to customize your redirect hooks.
41 |
42 | Notice that if your Devise model is called `Member` instead of `User`, for example, then the helpers available are:
43 |
44 | ```ruby
45 | before_action :authenticate_member!
46 |
47 | member_signed_in?
48 |
49 | current_member
50 |
51 | member_session
52 | ```
53 |
--------------------------------------------------------------------------------
/docs/devise/example_applications.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: example-applications
3 | title: Example Applications
4 | ---
5 |
6 | A list of example Rails applications that demonstrate how to use Devise. When adding your own examples, please add both Rails and Devise versions to your descriptions.
7 |
8 | ## Rails 5.0.0 Example
9 |
10 | | Author | Project | Comments |
11 | |--------|---------|----------|
12 | | bilal basharat | "Devise with Rails":https://github.com/bilalbash/rails_5_devise_app | Rails 5.0.0, Devise 4.2.0, plus Bootstrap |
13 | | sachin | "Rails5 skeleton":https://github.com/sachin/rails5-skeleton | Rails 5.0.0.1, Devise 4.2.0, plus Bootstrap4, Active Admin, STI for App patrons|
14 | | RailsApps | "Devise and Rails":https://github.com/RailsApps/rails-devise | Rails 5.0, Devise 4.2, plus Bootstrap or Foundation |
15 | | RailsApps | "Devise and Pundit and Rails":https://github.com/RailsApps/rails-devise-pundit | Rails 5.0, Devise 4.2, showing how to use Pundit for authorization |
16 | | Mohit Jain | "Devise, Facebook, Twitter, Google, Github, Linkedin":https://github.com/mohitjain/social-login-in-rails | Rails 5.1.5, Devise 4.4.1, Bootstrap, TurboLinks, carrierwave, MySql, Active Record. with "Demo":http://social-login-in-rails.herokuapp.com/ |
17 | | Joshua Needham | "Rails 5 Devise Omniauth Omniauth-Facebook Bootstrap":https://github.com/joshuaneedham/rails-5-devise-omniauth-facebook-bootstrap | Rails 5.2.2.1, Devise 4.6.1, OmniAuth 1.9.0, sassc 2.0.1, Bootstrap 4.3.1, TurboLinks, Active Record.|
18 |
19 |
20 | ## Rails 4.0 Examples
21 |
22 | | Author | Project | Comments |
23 | |--------|---------|----------|
24 | | Jay Shepherd | "Devise 3 example for Rails 4":https://github.com/jayshepherd/devise_example | Rails 4, Devise 3.0.0rc |
25 | | Michael Lang | "Lazy Registration":https://github.com/mwlang/lazy_registration_demos | Rails 4, Ruby 2, Devise 3.0 |
26 | | Abhilash M A | "Token based authentication for API":https://github.com/abhidsm/devise-token-api | Rails 4, Ruby 2, Devise 3.0 |
27 | | Ritesh Kumar | "Devise, Mongoid, MySQL":https://github.com/Ritesh-Kumar/rails4_mysql_mongo | Base Application of Rails 4.0 using both MySQL and Mongo, Devise 3, CanCan, OmniAuth and Twitter Bootstrap |
28 | | Rendered Text | "BaseApp":https://github.com/renderedtext/base-app | Rails 4, PostgreSQL, jQuery, RSpec, Cucumber, Devise 3.2, FB login (OmniAuth), admin system |
29 |
30 |
31 | ## Older Examples
32 |
33 | | Author | Project | Comments |
34 | |--------|---------|----------|
35 | | Andi Altendorfer | "Community Base Application (CBA)":http://github.com/iboard/CBA | Rails 3.2, Devise 1.4.2, OmniAuth 1.0.2, Mongoid, CanCan, Paperclip, etc. |
36 | | W.R. de Vos | "rails_template":https://github.com/foxycoder/rails_template | Rails 3.2, Devise 2.1.2, Oauth with Facebook and Google login (OmniAuth 1.1.1), Mongoid, Cancan, Carrierwave, Rspec, Cucumber |
37 |
--------------------------------------------------------------------------------
/docs/devise/extensions.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: extensions
3 | title: List of 3rd party Devise extensions.
4 | sidebar_label: Extensions
5 | ---
6 |
7 | ## ORM Support
8 |
9 | *mm-devise* - "Devise - MongoMapper":http://github.com/kristianmandrup/mm-devise
10 |
11 | *dm-devise* - "Devise - DataMapper":http://github.com/jm81/dm-devise
12 |
13 | *devise-couch* - "Devise - Couch DB":http://github.com/shenoudab/devise_couch
14 |
15 | *devise-ripple* - "Devise - Riak":http://github.com/frank06/devise-ripple
16 |
17 | *cequel-devise* - "Devise - Cassandra":https://github.com/cequel/cequel-devise
18 |
19 | ## Encryption Support
20 |
21 | *devise-encryptable* - adds support of other authentication mechanisms besides the built-in Bcrypt (the default).
22 | "https://github.com/plataformatec/devise-encryptable":https://github.com/plataformatec/devise-encryptable
23 |
24 | *devise_aes_encryptable* - AES-256 Reversible Encryption
25 | "http://github.com/chicks/devise_aes_encryptable":http://github.com/chicks/devise_aes_encryptable
26 |
27 | *devise-argon2* - Support for Argon2i
28 | "https://github.com/erdostom/devise-argon2":https://github.com/erdostom/devise-argon2
29 |
30 | ## Mailing List Support
31 |
32 | *devise_campaignable* - Have your users automatically added to a mail campaign tool of your choice. Currently supports MailChimp but easy adaptation for CampaignMonitor. "https://github.com/SirRawlins/devise_campaignable":https://github.com/SirRawlins/devise_campaignable
33 |
34 | *devise_mailchimp* - MailChimp integration for Devise making it effortless for users to join mailing lists when they register their account.
35 | "http://jcnnghm.github.com/devise_mailchimp/":http://jcnnghm.github.com/devise_mailchimp/
36 |
37 | h3. Miscellaneous
38 |
39 | *cantango* - Integrates Devise, Roles and CanCan with Permits for a Rails 3 app
40 | "http://github.com/kristianmandrup/cantango":http://github.com/kristianmandrup/cantango
41 | (Replaces *cream*, "http://github.com/kristianmandrup/cream":http://github.com/kristianmandrup/cream)
42 |
43 | *invitable* - Adds support for send account invitations by email.
44 | "http://github.com/scambra/devise_invitable":http://github.com/scambra/devise_invitable
45 |
46 | *devise_traceable* - Tracing Devise Model (Model Stamp login and logout)
47 | "http://github.com/shenoudab/devise_traceable":http://github.com/shenoudab/devise_traceable
48 |
49 | *devise_lastseenable* - Just adds a last_seen datetime that's updated whenever authenticate! is called.
50 | "https://github.com/ctide/devise_lastseenable":https://github.com/ctide/devise_lastseenable
51 |
52 | *devise_security* - Add "enterprise" functionality (strong passwords, password expire..., new: captcha support)
53 | "https://github.com/devise-security/devise-security":https://github.com/devise-security/devise-security
54 |
55 | *devise-basecamper* - Add basecamp-style subdomain scoped authentication
56 | "https://github.com/digitalopera/devise-basecamper":https://github.com/digitalopera/devise-basecamper
57 |
58 | *devise-two-factor* - Barebones two-factor authentication support
59 | "https://github.com/tinfoil/devise-two-factor":https://github.com/tinfoil/devise-two-factor
60 |
61 | *two_factor_authentication* - Add two factor authentication, like Gmail
62 | "https://github.com/Houdini/two_factor_authentication":https://github.com/Houdini/two_factor_authentication
63 |
64 | *devise_account_expireable* - Expire a user account at a specific date / time.
65 | "https://github.com/j-mcnally/devise_account_expireable":https://github.com/j-mcnally/devise_account_expireable
66 |
67 | *devise_uid* - Add UID support to Devise. A lot of times, we want a unique ID representing the user model instead of its incremental ID in the database, for example, in API instead of exposing the primary key, we use a random generated unique string to indentify this user.
68 | "https://github.com/jingweno/devise_uid":https://github.com/jingweno/devise_uid
69 |
70 | *devise_session_expirable* - Devise timeoutable's paranoid cousin. Enforces time-limited sessions by rejecting sessions which are not timestamped.
71 | "https://github.com/teleological/devise_session_expirable":https://github.com/teleological/devise_session_expirable
72 |
73 | *devise_zxcvbn* - Reject weak passwords using zxcvbn.
74 | "https://github.com/bitzesty/devise_zxcvbn":https://github.com/bitzesty/devise_zxcvbn
75 |
76 | *devise_invalidatable* - Invalidate sessions from the server-side.
77 | "https://github.com/madkins/devise_invalidatable":https://github.com/madkins/devise_invalidatable
78 |
79 | *any_login* - easy login with any user to make your development life easier.
80 | "https://github.com/igorkasyanchuk/any_login":https://github.com/igorkasyanchuk/any_login
81 |
82 | *devise-verifiable* - Adds a second step to Devise's signup process. Useful if you want to collect extra information or verify user's identity through a 3rd-party service. "github.com/Rodrigora/devise-verifiable":https://github.com/Rodrigora/devise-verifiable
83 |
84 | *honeybadger* - When used together, exceptions reported to honeybadger will automatically be associated with the current Devise user.
85 | "https://github.com/honeybadger-io/honeybadger-ruby":https://github.com/honeybadger-io/honeybadger-ruby
86 |
87 | *devise-uncommon_password* - Prevents a user from using a password in the list of the 100 most common passwords.
88 | "https://github.com/HCLarsen/devise-uncommon_password":https://github.com/HCLarsen/devise-uncommon_password
89 |
90 | *devise-pwned_password* - checks user passwords against the "PwnedPasswords":https://haveibeenpwned.com/Passwords dataset.
91 | "https://github.com/michaelbanfield/devise-pwned_password":https://github.com/michaelbanfield/devise-pwned_password
92 |
93 | *devise_date_restrictable* - restrict a user’s account by date range (valid from/until/between).
94 | "https://github.com/jonpearse/devise_date_restrictable":https://github.com/jonpearse/devise_date_restrictable
95 |
96 | h3. External authentication integration
97 |
98 | *devise-browserid* - Adds support for Mozilla Persona / BrowserID authentication.
99 | "https://github.com/ringe/devise-browserid/":https://github.com/ringe/devise-browserid/
100 |
101 | *facebook_connectable* - Adds support for Facebook Connect authentication, and optionally fetching user info from Facebook in the same step.
102 | "http://github.com/grimen/devise_facebook_connectable":http://github.com/grimen/devise_facebook_connectable
103 |
104 | *oauth2_authenticatable* - Adds support for OAuth2 (Facebook Graph) authentication.
105 | "http://github.com/bhbryant/devise_oauth2_authenticatable":http://github.com/bhbryant/devise_oauth2_authenticatable
106 |
107 | *oauth2_providable* - Adds an OAuth2 authentication layer to protect API resources.
108 | "https://github.com/socialcast/devise_oauth2_providable":https://github.com/socialcast/devise_oauth2_providable
109 |
110 | *devise-twitter* - Adds Sign in via Twitter and Connect your account to Twitter functionality
111 | "http://github.com/MSch/devise-twitter":http://github.com/MSch/devise-twitter
112 |
113 | *imapable* - Adds support for authentication via IMAP, a great solution for internal application where no LDAP server exists.
114 | "http://github.com/joshk/devise_imapable":http://github.com/joshk/devise_imapable
115 |
116 | *ldap_authenticatable* - Adds support for LDAP authentication via simple bind.
117 | "http://github.com/cschiewek/devise_ldap_authenticatable":http://github.com/cschiewek/devise_ldap_authenticatable
118 |
119 | *rpx_connectable* - Adds support for "RPX":http://www.rpxnow.com authentication. "RPX":http://www.rpxnow.com provides free and paid services to handle many authentication providers (facebook, twitter, OpenID...) using a single API.
120 | "http://github.com/slainer68/devise_rpx_connectable":http://github.com/slainer68/devise_rpx_connectable
121 |
122 | *cas_authenticatable* - Adds support for single sign-on via "CAS":http://www.jasig.org/cas and CAS-implementing servers.
123 | "http://github.com/nbudin/devise_cas_authenticatable":http://github.com/nbudin/devise_cas_authenticatable
124 |
125 | *openid_authenticatable* - Adds support for "OpenID":http://openid.net authentication.
126 | "http://github.com/nbudin/devise_openid_authenticatable":http://github.com/nbudin/devise_openid_authenticatable
127 |
128 | *devise_paypal* - Adds support for "Paypal":http://www.paypal.com authentication
129 | "http://github.com/dwilkie/devise_paypal":http://github.com/dwilkie/devise_paypal
130 |
131 | *devise_google_authenticator* - Adds support for "Google's Authenticator":http://code.google.com/p/google-authenticator/
132 | "http://github.com/AsteriskLabs/devise_google_authenticator":http://github.com/AsteriskLabs/devise_google_authenticator
133 |
134 | *devise_shibboleth_authenticatable* - Adds support for "Shibboleth":http://shibboleth.net
135 | "https://github.com/jgeorge300/devise_shibboleth_authenticatable":https://github.com/jgeorge300/devise_shibboleth_authenticatable
136 |
137 | *devise-radius-authenticatable* - Adds support for authenticating against radius servers
138 | "https://github.com/cbascom/devise-radius-authenticatable":https://github.com/cbascom/devise-radius-authenticatable
139 |
140 | *devise-jwt* - JWT token authentication with devise
141 | "https://github.com/waiting-for-dev/devise-jwt":https://github.com/waiting-for-dev/devise-jwt
--------------------------------------------------------------------------------
/docs/devise/guides-list.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: guides-list
3 | title: Guides list
4 | ---
5 |
6 | > Todo: move the guides to this site
7 |
8 | Feel free to add your own how-to and categorize it in this list.
9 |
10 | ## Upgrading
11 |
12 | * [Upgrade: General Instructions](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade:-General-Instructions)
13 | * [Upgrade to Devise 3.1](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-3.1)
14 | * [Upgrade to Devise 2.2](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.2)
15 | * [Upgrade to Devise 2.1](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.1)
16 | * [Upgrade to Devise 2.0](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0)
17 | * [Upgrade to Devise 2.0 migration schema style](https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style)
18 | * [Migration legacy database](https://github.com/plataformatec/devise/wiki/How-To:-Migration-legacy-database)
19 |
20 | ## Workflow Customization
21 |
22 | * [Automatically generate password for users (simpler registration)](https://github.com/plataformatec/devise/wiki/How-To:-Automatically-generate-password-for-users-%28simpler-registration%29)
23 | * [Change the default sign_in and sign_out routes](https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes)
24 | * [Change Default Sign_up Registration Path with Custom Path](https://github.com/plataformatec/devise/wiki/How-To:-Change-Default-Sign_up---Registration-Path-with-Custom-Path)
25 | * [Customize routes to user registration pages](https://github.com/plataformatec/devise/wiki/How-To:-Customize-routes-to-user-registration-pages)
26 | * [Redirect to a specific page on successful sign in out](https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in-out)
27 | * [Customize the redirect after a user edits their profile](https://github.com/plataformatec/devise/wiki/How-To:-Customize-the-redirect-after-a-user-edits-their-profile)
28 | * [Customize the redirect path after destroying a session (signing out)](https://github.com/plataformatec/devise/wiki/How-To:-Change-the-redirect-path-after-destroying-a-session-i.e.-signing-out)
29 | * [Override confirmations so users can pick their own passwords as part of confirmation activation](https://github.com/plataformatec/devise/wiki/How-To:-Override-confirmations-so-users-can-pick-their-own-passwords-as-part-of-confirmation-activation)
30 | * [Retain User Data after account Delete (soft delete)](https://github.com/plataformatec/devise/wiki/How-to:-Soft-delete-a-user-when-user-deletes-account)
31 | * [Use Omniauth in a localized scope](https://github.com/plataformatec/devise/wiki/How-To:-OmniAuth-inside-localized-scope)
32 | * [Redirect with locale after authentication failure](https://github.com/plataformatec/devise/wiki/How-To:--Redirect-with-locale-after-authentication-failure)
33 | * [Require admin to activate account before sign_in](https://github.com/plataformatec/devise/wiki/How-To:-Require-admin-to-activate-account-before-sign_in)
34 | * [Set up devise as a single user system](https://github.com/plataformatec/devise/wiki/How-To:-Set-up-devise-as-a-single-user-system)
35 | * [Two step confirmation](https://github.com/plataformatec/devise/wiki/How-To:-Two-step-confirmation)
36 | * [Redirect back to current page after sign in, sign out, sign up, update](https://github.com/plataformatec/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update)
37 | * [Redirect from HTTPS to HTTP on successful sign out](https://github.com/plataformatec/devise/wiki/How-To:-redirect-from-HTTPS-to-HTTP-on-successful-sign-out)
38 | * [Redirect to a specific page on successful sign in, sign up, or sign out](https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-on-successful-sign-in,-sign-up,-or-sign-out)
39 | * [Redirect to a specific page when the user can not be authenticated](https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated)
40 | * [Do not redirect to login page after session timeout](https://github.com/plataformatec/devise/wiki/How-To:-Do-not-redirect-to-login-page-after-session-timeout)
41 | * [Create a guest user](https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user)
42 | * [Allow users to edit their password](https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password)
43 | * [Require authentication for all pages and avoid "You need to sign in..." message when hitting the application root](https://github.com/plataformatec/devise/wiki/How-To:-Require-authentication-for-all-pages)
44 | * [Use a custom email validator with Devise](https://github.com/plataformatec/devise/wiki/How-to:-Use-a-custom-email-validator-with-Devise)
45 | * [Notify users via email when their passwords change](https://github.com/plataformatec/devise/wiki/Notify-users-via-email-when-their-passwords-change)
46 | * [Customize minimum password length](https://github.com/plataformatec/devise/wiki/Customize-minimum-password-length)
47 |
48 | ## View/Content Customization
49 |
50 | * [Create custom layouts](https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts)
51 | * [Custom mailer](https://github.com/plataformatec/devise/wiki/How-To:-Use-custom-mailer)
52 | * [I18n](https://github.com/plataformatec/devise/wiki/I18n)
53 | * [Set :host and :port for all devise mailer urls](https://github.com/plataformatec/devise/wiki/How-To:-Set-:host-and-:port-for-all-devise-mailer-urls)
54 | * [Override devise_error_messages! for use in views](https://github.com/plataformatec/devise/wiki/Override-devise_error_messages!-for-views)
55 | * [Integrate I18n Flash Messages with Devise and Bootstrap](https://github.com/plataformatec/devise/wiki/How-To:-Integrate-I18n-Flash-Messages-with-Devise-and-Bootstrap)
56 | * [I18n Messages for Scoped Resources](https://github.com/plataformatec/devise/wiki/How-To:I18n-Message-for-Scoped-Resources)
57 | * [Add sign_in, sign_out, and sign_up links to your layout template](https://github.com/plataformatec/devise/wiki/How-To:-Add-sign_in,-sign_out,-and-sign_up-links-to-your-layout-template)
58 |
59 | ## Custom Authentication Methods
60 |
61 | * [Allow users to sign in with something other than their email address](https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-with-something-other-than-their-email-address)
62 | * [Authenticate via LDAP](https://github.com/plataformatec/devise/wiki/How-To:-Authenticate-via-LDAP)
63 | * [Create a guest user](https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user)
64 | * [Email-only sign-up](https://github.com/plataformatec/devise/wiki/How-To:-Email-only-sign-up)
65 | * [Edit an account without providing a password](https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password)
66 | * [HTTP Authentication](https://github.com/plataformatec/devise/wiki/How-To:-Use-HTTP-Basic-Authentication)
67 | * [HTTP Auth Basic](https://github.com/plataformatec/devise/wiki/How-To:-Use-HTTP-Auth-Basic-with-Devise)
68 | * [Recaptcha](https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise)
69 | * [Remote authentication with Devise](https://github.com/plataformatec/devise/wiki/How-to:-Remote-authentication-with-Devise)
70 | * [Set up devise as a single user system](https://github.com/plataformatec/devise/wiki/How-To:-Set-up-devise-as-a-single-user-system)
71 | * [Sign in using either a username or email address](https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address)
72 | * [Simple Token Authentication Example](https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example)
73 | * [Use case insensitive emails](https://github.com/plataformatec/devise/wiki/How-To:-Use-case-insensitive-emails)
74 | * [Use SSL (HTTPS)](https://github.com/plataformatec/devise/wiki/How-To:-Use-SSL-%28HTTPS%29)
75 | * [Use subdomains](https://github.com/plataformatec/devise/wiki/How-To:-Use-subdomains)
76 | * [AWS Cognito Federated Identity Authentication Example](http://c.mirifique.ch/2018/04/09/rails-devise-authenticating-using-aws-cognito-identity)
77 |
78 | ### OmniAuth
79 |
80 | * [OmniAuth: Overview](https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview)
81 | * [OmniAuth: Testing](https://github.com/plataformatec/devise/wiki/OmniAuth:--Testing)
82 | * [Omniauthable, sign out action and rememberable](https://github.com/plataformatec/devise/wiki/Omniauthable,-sign-out-action-and-rememberable)
83 |
84 |
85 | ## Testing
86 |
87 | * [Capybara](https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara)
88 | * [Controller tests with Rails (and RSpec)](https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-%28and-RSpec%29)
89 | * [Cucumber](https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Cucumber)
90 | * [OmniAuth: Testing](https://github.com/plataformatec/devise/wiki/OmniAuth:--Testing)
91 | * [Rspec with devise and machinist](https://github.com/plataformatec/devise/wiki/How-To:-Rspec-with-devise-and-machinist)
92 | * [Speed up your unit tests](https://github.com/plataformatec/devise/wiki/Speed-up-your-unit-tests)
93 | * [Stub authentication in controller specs](https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs)
94 |
95 |
96 | ## Privileges/Authorization
97 |
98 | * [Add an Admin role](https://github.com/plataformatec/devise/wiki/How-To:-Add-an-Admin-role)
99 | * [Add a default role to a User](https://github.com/plataformatec/devise/wiki/How-To:-Add-a-default-role-to-a-User)
100 | * [Create a guest user](https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user)
101 | * [Integrate with CanCan for roles management](https://github.com/plataformatec/devise/wiki/How-To:-Integrate-with-CanCan-for-roles-management)
102 | * [Manage Users with an Admin Role (CanCan method)](https://github.com/plataformatec/devise/wiki/How-To:-Manage-Users-with-an-Admin-Role-(CanCan-method))
103 | * [Require admin to activate account before sign_in](https://github.com/plataformatec/devise/wiki/How-To:-Require-admin-to-activate-account-before-sign_in)
104 | * [Sign in as another user if you are an admin](https://github.com/plataformatec/devise/wiki/How-To:-Sign-in-as-another-user-if-you-are-an-admin)
105 | * [Turn off trackable for admin users](https://github.com/plataformatec/devise/wiki/How-To:-Turn-off-trackable-for-admin-users)
106 |
107 | ## Special Configurations
108 |
109 | * [Add :confirmable to Users](https://github.com/plataformatec/devise/wiki/How-To:-Add-:confirmable-to-Users)
110 | * [Add :lockable to Users](https://github.com/plataformatec/devise/wiki/How-To:-Add-:lockable-to-Users)
111 | * [Create a custom encryptor](https://github.com/plataformatec/devise/wiki/How-To:-Create-a-custom-encryptor)
112 | * [Create Haml and Slim Views](https://github.com/plataformatec/devise/wiki/How-To:-Create-Haml-and-Slim-Views)
113 | * [Configure a master password](https://github.com/plataformatec/devise/wiki/How-To:-Configure-a-master-password)
114 | * [Customize user account status validation when logging in](https://github.com/plataformatec/devise/wiki/How-To:-Customize-user-account-status-validation-when-logging-in)
115 | * [Disable user from destroying their account](https://github.com/plataformatec/devise/wiki/How-To:-Disable-user-from-destroying-their-account)
116 | * [Disallow previously used passwords](https://github.com/plataformatec/devise/wiki/How-To:-Disallow-previously-used-passwords)
117 | * [Dynamic user registration timeout](https://github.com/plataformatec/devise/wiki/How-To:-Add-timeout_in-value-dynamically)
118 | * [Embed users in your account model with Mongoid](https://github.com/plataformatec/devise/wiki/How-To:-Embed-users-in-your-account-model-with-Mongoid)
119 | * [Protect Resque Web with Devise](https://github.com/plataformatec/devise/wiki/How-To:-Protect-Resque-Web-with-Devise)
120 | * [Send emails from subdomains](https://github.com/plataformatec/devise/wiki/How-To:-Send-emails-from-subdomains)
121 | * [Send emails in background (Resque, Sidekiq and Delayed::Job)](https://github.com/plataformatec/devise/wiki/How-To%3A-Send-devise-emails-in-background-%28Resque%2C-Sidekiq-and-Delayed%3A%3AJob%29)
122 | * [Using paranoid mode, avoid user enumeration on registerable](https://github.com/plataformatec/devise/wiki/How-To:-Using-paranoid-mode,-avoid-user-enumeration-on-registerable)
123 | * [Use Devise Inside a Mountable Engine](https://github.com/plataformatec/devise/wiki/How-To:-Use-devise-inside-a-mountable-engine)
124 |
125 | ## Elsewhere in your App
126 |
127 | * [Add sign_in, sign_out, and sign_up links to your layout template](https://github.com/plataformatec/devise/wiki/How-To:-Add-sign_in,-sign_out,-and-sign_up-links-to-your-layout-template)
128 | * [Display a custom sign_in form anywhere in your app](https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app)
129 | * [Sign in from a controller](https://github.com/plataformatec/devise/wiki/How-To:-Sign-in-from-a-controller)
130 | * [Use Devise generated method and filters for controllers](https://github.com/plataformatec/devise/wiki/How-To:-Use-Devise-generated-method-and-filters-for-controllers)
131 | * [Find a user when you have their credentials](https://github.com/plataformatec/devise/wiki/How-To:-Find-a-user-when-you-have-their-credentials)
132 | * [Make Devise work with other formats like mobile, iPhone and iPad (Rails specific)](https://github.com/plataformatec/devise/wiki/How-To:-Make-Devise-work-with-other-formats-like-mobile,-iPhone-and-iPad---Rails-specific)
133 | * [Manage users through a CRUD interface](https://github.com/plataformatec/devise/wiki/How-To:-Manage-users-through-a-CRUD-interface)
134 | * [Mass password reset and email notification](https://github.com/plataformatec/devise/wiki/How-To:-Mass-password-reset-and-email-notification)
135 |
136 | ## JavaScript
137 |
138 | * [Use with BackboneJS models](https://github.com/plataformatec/devise/wiki/How-To:-Use-with-BackboneJS-models)
139 |
140 | ## Migrating from other authentication plugins
141 | * [Migrate from restful_authentication to Devise](https://github.com/plataformatec/devise/wiki/How-To:-Migrate-from-restful_authentication-to-Devise)
142 | * [Add devise required columns to an existing users table](https://github.com/plataformatec/devise/wiki/How-To:-change-an-already-existing-table-to-add-devise-required-columns)
--------------------------------------------------------------------------------
/docs/devise/i18n.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: i18n
3 | title: I18n
4 | ---
5 |
6 | Devise uses flash messages with I18n, in conjunction with the flash keys :notice and :alert. To customize your app, you can set up your locale file:
7 |
8 | ```yaml
9 | en:
10 | devise:
11 | sessions:
12 | signed_in: 'Signed in successfully.'
13 | ```
14 |
15 | You can also create distinct messages based on the resource you've configured using the singular name given in routes:
16 |
17 | ```yaml
18 | en:
19 | devise:
20 | sessions:
21 | user:
22 | signed_in: 'Welcome user, you are signed in.'
23 | admin:
24 | signed_in: 'Hello admin!'
25 | ```
26 |
27 | The Devise mailer uses a similar pattern to create subject messages:
28 |
29 | ```yaml
30 | en:
31 | devise:
32 | mailer:
33 | confirmation_instructions:
34 | subject: 'Hello everybody!'
35 | user_subject: 'Hello User! Please confirm your email'
36 | reset_password_instructions:
37 | subject: 'Reset instructions'
38 | ```
39 |
40 | Take a look at our locale file to check all available messages. You may also be interested in one of the many translations that are available on our wiki:
41 |
42 | https://github.com/plataformatec/devise/wiki/I18n
43 |
44 | Caution: Devise Controllers inherit from ApplicationController. If your app uses multiple locales, you should be sure to set I18n.locale in ApplicationController.
--------------------------------------------------------------------------------
/docs/devise/installation.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: installation
3 | title: Installation
4 | ---
5 | Devise 4.0 works with Rails 4.1 onwards. Add the following line to your Gemfile:
6 |
7 | ```ruby
8 | gem 'devise'
9 | ```
10 |
11 | Then run `bundle install`
12 |
13 | Next, you need to run the generator:
14 |
15 | ```console
16 | $ rails generate devise:install
17 | ```
18 |
19 | At this point, a number of instructions will appear in the console. Among these instructions, you'll need to set up the default URL options for the Devise mailer in each environment. Here is a possible configuration for `config/environments/development.rb`:
20 |
21 | ```ruby
22 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
23 | ```
24 |
25 | The generator will install an initializer which describes ALL of Devise's configuration options. It is *imperative* that you take a look at it. When you are done, you are ready to add Devise to any of your models using the generator.
26 |
27 |
28 | In the following command you will replace `MODEL` with the class name used for the application’s users (it’s frequently `User` but could also be `Admin`). This will create a model (if one does not exist) and configure it with the default Devise modules. The generator also configures your `config/routes.rb` file to point to the Devise controller.
29 |
30 | ```console
31 | $ rails generate devise MODEL
32 | ```
33 |
34 | Next, check the MODEL for any additional configuration options you might want to add, such as confirmable or lockable. If you add an option, be sure to inspect the migration file (created by the generator if your ORM supports them) and uncomment the appropriate section. For example, if you add the confirmable option in the model, you'll need to uncomment the Confirmable section in the migration.
35 |
36 | Then run `rails db:migrate`
37 |
38 | You should restart your application after changing Devise's configuration options (this includes stopping spring). Otherwise, you will run into strange errors, for example, users being unable to login and route helpers being undefined.
39 |
--------------------------------------------------------------------------------
/docs/devise/omniauth.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: omniauth
3 | title: OmniAuth
4 | ---
5 | > Since version 1.2, Devise supports integration with [OmniAuth](http://github.com/intridea/omniauth). This wiki page will cover the basics to have this integration working using an OAuth provider as example.
6 |
7 | > Since version 1.5, Devise supports OmniAuth 1.0 forward which will be the version covered by this tutorial.
8 |
9 | Devise comes with OmniAuth support out of the box to authenticate with other providers. To use it, simply specify your OmniAuth configuration in `config/initializers/devise.rb`:
10 |
11 | ```ruby
12 | config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
13 | ```
14 |
15 | ## Before you start
16 |
17 | Remember that `config.omniauth` adds omniauth provider middleware to your application. This means you should **not** add this provider middleware again in `config/initializers/omniauth.rb` as they'll clash with each other and result in always-failing authentication.
18 |
19 | ## Facebook example
20 |
21 | The first step then is to add an OmniAuth gem to your application. This can be done in our `Gemfile`:
22 |
23 | ```ruby
24 | gem 'omniauth-facebook'
25 | ```
26 |
27 | Here we'll use Facebook as an example, but you are free to use whatever and as many OmniAuth gems as you'd like. Generally, the gem name is "omniauth-provider" where provider can be "facebook" or "twitter", for example. For a full list of these providers, please check [OmniAuth's list of strategies](https://github.com/intridea/omniauth/wiki/List-of-Strategies).
28 |
29 | Next up, you should add the columns "provider" (string) and "uid" (string) to your User model.
30 |
31 | ```rails
32 | rails g migration AddOmniauthToUsers provider:string uid:string
33 | rake db:migrate
34 | ```
35 |
36 | Next, you need to declare the provider in your `config/initializers/devise.rb`:
37 |
38 | ```ruby
39 | config.omniauth :facebook, "APP_ID", "APP_SECRET"
40 | ```
41 |
42 | If you are seeing something like _Could not authenticate you from Facebook because “Invalid credentials”_
43 | you may need to add `token_params: { parse: :json }` to your config, i.e.:
44 |
45 | ```ruby
46 | config.omniauth :facebook, "APP_ID", "APP_SECRET", token_params: { parse: :json }
47 | ```
48 |
49 | To alter the permissions or scopes requested, check the [omniauth-facebook](https://github.com/mkdynamic/omniauth-facebook) gem's README.
50 |
51 | After configuring your strategy, you need to make your model (e.g. `app/models/user.rb`) omniauthable:
52 |
53 | ```ruby
54 | devise :omniauthable, omniauth_providers: %i[facebook]
55 | ```
56 |
57 | >**Note**: If you're running a rails server, you'll need to restart it to recognize the change in the `Devise` initializer or adding `:omniauthable` to your `User` model will create an error.
58 |
59 | Currently, Devise allows only one model to be omniauthable. If you want to use `OmniAuth` with multiple models, check out [OmniAuth with multiple models](https://github.com/plataformatec/devise/wiki/OmniAuth-with-multiple-models).
60 |
61 | After making a model named `User` omniauthable and if `devise_for :users` was already added to your `config/routes.rb`, Devise will create the following url methods:
62 |
63 | * user_{provider}_omniauth_authorize_path
64 | * user_{provider}_omniauth_callback_path
65 |
66 | Note that Devise does not create `*_url` methods. While you will never use the callback helper above directly, you only need to add the first one to your layouts in order to provide facebook authentication:
67 |
68 | ```ruby
69 | <%= link_to "Sign in with Facebook", user_facebook_omniauth_authorize_path %>
70 | ```
71 |
72 | >**Note**: The `{provider}` in the above `*_path` methods matches the symbol of the provider passed to Devise's config block. Please check that `omniauth-*` gem's **README** to know which symbol you should use.
73 |
74 | By clicking on the above link, the user will be redirected to `Facebook`. (If this link doesn't exist, try restarting the server.) After inserting their credentials, they will be redirected back to your application's callback method. To implement a callback, the first step is to go back to our `config/routes.rb` file and tell Devise in which controller we will implement Omniauth callbacks:
75 |
76 | ```ruby
77 | devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
78 | ```
79 |
80 | Now we just add the file `app/controllers/users/omniauth_callbacks_controller.rb`:
81 |
82 | ```ruby
83 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
84 | end
85 | ```
86 |
87 | The callback should be implemented as an action with the same name as the provider. Here is an example action for our facebook provider that we could add to our controller:
88 |
89 | ```ruby
90 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
91 | def facebook
92 | # You need to implement the method below in your model (e.g. app/models/user.rb)
93 | @user = User.from_omniauth(request.env["omniauth.auth"])
94 |
95 | if @user.persisted?
96 | sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
97 | set_flash_message(:notice, :success, kind: "Facebook") if is_navigational_format?
98 | else
99 | session["devise.facebook_data"] = request.env["omniauth.auth"]
100 | redirect_to new_user_registration_url
101 | end
102 | end
103 |
104 | def failure
105 | redirect_to root_path
106 | end
107 | end
108 | ```
109 |
110 | This action has a few aspects worth describing:
111 |
112 | 1. All information retrieved from Facebook by OmniAuth is available as a hash at `request.env["omniauth.auth"]`. Check the [OmniAuth docs](https://github.com/intridea/omniauth/wiki/Auth-Hash-Schema) and each [omniauth-facebook](https://github.com/mkdynamic/omniauth-facebook#auth-hash) gem's README to know which information is being returned.
113 |
114 | 2. When a valid user is found, they can be signed in with one of two Devise methods: `sign_in` or `sign_in_and_redirect`. Passing `:event => :authentication` is optional. You should only do so if you wish to use [Warden callbacks](http://stackoverflow.com/a/13389324/1160916).
115 |
116 | 3. A flash message can also be set using one of Devise's default messages, but that is up to you.
117 |
118 | 4. In case the user is not persisted, we store the OmniAuth data in the session. Notice we store this data using "devise." as key namespace. This is useful because Devise removes all the data starting with "devise." from the session whenever a user signs in, so we get automatic session clean up. At the end, we redirect the user back to our registration form.
119 |
120 | After the controller is defined, we need to implement the `from_omniauth` method in our model (e.g. `app/models/user.rb`):
121 |
122 | ```ruby
123 | def self.from_omniauth(auth)
124 | where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
125 | user.email = auth.info.email
126 | user.password = Devise.friendly_token[0, 20]
127 | user.name = auth.info.name # assuming the user model has a name
128 | user.image = auth.info.image # assuming the user model has an image
129 | # If you are using confirmable and the provider(s) you use validate emails,
130 | # uncomment the line below to skip the confirmation emails.
131 | # user.skip_confirmation!
132 | end
133 | end
134 | ```
135 |
136 | This method tries to find an existing user by the `provider` and `uid` fields. If no user is found, a new one is created with a random password and some extra information.
137 | Note that the [`first_or_create` method](http://apidock.com/rails/v3.2.1/ActiveRecord/Relation/first_or_create) automatically sets the `provider` and `uid` fields when creating a new user. The [`first_or_create!` method](http://apidock.com/rails/v3.2.1/ActiveRecord/Relation/first_or_create!) operates similarly, except that it will raise an Exception if the user record fails validation.
138 |
139 | Notice that Devise's `RegistrationsController` by default calls `User.new_with_session` before building a resource. This means that, if we need to copy data from session whenever a user is initialized before sign up, we just need to implement `new_with_session` in our model. Here is an example that copies the facebook email if available:
140 |
141 | ```ruby
142 | class User < ApplicationRecord
143 | def self.new_with_session(params, session)
144 | super.tap do |user|
145 | if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
146 | user.email = data["email"] if user.email.blank?
147 | end
148 | end
149 | end
150 | end
151 | ```
152 |
153 | Finally, if you want to allow your users to cancel sign up with Facebook, you can redirect them to `cancel_user_registration_path`. This will remove all session data starting with `devise.` and the `new_with_session` hook above will no longer be called.
154 |
155 | ### Logout links
156 |
157 |
158 | ```ruby
159 | # config/routes.rb
160 | devise_scope :user do
161 | delete 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
162 | end
163 | ```
164 |
165 | And that is all you need! After you get your integration working, it's time to write some integration tests:
166 |
167 | [https://github.com/intridea/omniauth/wiki/Integration-Testing](https://github.com/intridea/omniauth/wiki/Integration-Testing)
168 |
169 | ## Using OmniAuth without other authentications
170 |
171 | If you are using **ONLY** omniauth authentication, you need to define a route named `new_user_session` (if not defined, root will be used). Below is an example of such routes (you don't need to include it if you are also using database or other authentication with omniauth):
172 |
173 | ```ruby
174 | devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
175 |
176 | devise_scope :user do
177 | get 'sign_in', :to => 'devise/sessions#new', :as => :new_user_session
178 | get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
179 | end
180 | ```
181 |
182 | In the example above, the sessions controller doesn't need to do anything special. For example, showing a link to the provider authentication will suffice.
183 |
184 | > **Note**: If your Devise configuration specifies `sign_out_via = :delete`, you may need to adjust your sign_out route to match an incoming DELETE request instead.
185 |
186 | Also, if you are not using `:database_authenticatable` you have to define the helper method `new_session_path(scope)` so it can correctly redirect in case of failure:
187 |
188 | ```ruby
189 | class ApplicationController < ActionController::Base
190 | # ...
191 | def new_session_path(scope)
192 | new_user_session_path
193 | end
194 | end
195 | ```
196 |
197 | ## Troubleshooting
198 |
199 | ### User didn't allow email permissions
200 |
201 | In the new Facebook login dialog the user can decline to provide email address.
202 | Devise usually requires email to register. A quick and dirty solution to this problem is to re-request the email if it wasn't found:
203 |
204 | ```ruby
205 | class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
206 | def facebook
207 | if request.env["omniauth.auth"].info.email.blank?
208 | redirect_to "/users/auth/facebook?auth_type=rerequest&scope=email"
209 | return # be sure to include an return if there is code after this otherwise it will be executed
210 | end
211 | end
212 | end
213 | ```
214 |
215 | ### Facebook returning nulled email
216 |
217 | Since July 8th 2015 Facebook changed to api v2.4, you need to add extra `info_fields` to get email field.
218 | ```ruby
219 | config.omniauth :facebook, "APP_ID", "APP_SECRET", scope: 'email', info_fields: 'email,name'
220 | ```
221 | [found solution from here by @techmonster](https://www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application)
222 |
223 | If this solution doesn't work for you. Please, try to use fields instead of info_fields.
224 |
225 | ### Extra config
226 |
227 | Facebook OAuth gem uses the API version `V2.6` by default.
228 | This might not work for you, as your app might be configured to use a different version of GraphAPI.
229 | So you need to make sure your web-app is making the correct call.
230 | You need to add extra option `client_options`. See an example:
231 |
232 | ```ruby
233 | config.omniauth :facebook, ENV['FB_APP_ID'], ENV['FB_APP_SECRET'],
234 | scope: 'public_profile,email',
235 | info_fields: 'email,first_name,last_name,gender,birthday,location,picture',
236 | client_options: {
237 | site: 'https://graph.facebook.com/v2.11',
238 | authorize_url: "https://www.facebook.com/v2.11/dialog/oauth"
239 | }
240 | ```
241 |
242 | ### OpenSSL
243 |
244 | If you run into an OpenSSL error like this:
245 |
246 | ```ruby
247 | OpenSSL::SSL::SSLError (SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed):
248 | ```
249 |
250 | Then you need to explicitly tell OmniAuth where to locate your CA certificate file.
251 | Either use the [certified gem](https://github.com/stevegraham/certified) or this method (depending on the OS you are running on):
252 |
253 | ```ruby
254 | config.omniauth :facebook, "APP_ID", "APP_SECRET",
255 | client_options: { ssl: { ca_path: '/etc/ssl/certs' } }
256 | ```
257 |
258 | On Heroku, the CA file is located at `/usr/lib/ssl/certs/ca-certificates.crt`
259 |
260 | On Engine Yard Cloud servers, the CA file is located at `/etc/ssl/certs/ca-certificates.crt`.
261 |
262 | These certificates can be set using the `:ca_file` key:
263 |
264 | ```ruby
265 | config.omniauth :facebook, "APP_ID", "APP_SECRET",
266 | client_options: { ssl: { ca_file: '/usr/lib/ssl/certs/ca-certificates.crt' } }
267 | ```
268 |
269 | If you are using a strategy that uses the OAuth gem eg [omniauth-oauth](https://github.com/intridea/omniauth-oauth) then specify the certificate file this way:
270 |
271 | ```ruby
272 | config.omniauth :facebook, "APP_ID", "APP_SECRET",
273 | client_options: { ca_file: '/usr/lib/ssl/certs/ca-certificates.crt' }
274 | ```
275 |
276 | On macOS, for development only, it may be easiest just to disable certificate verification because the certificates are stored in the keychain, not the file system:
277 |
278 | ```ruby
279 | require "omniauth-facebook"
280 | config.omniauth :facebook, "APP_ID", "APP_SECRET", client_options: { ssl: { verify: !Rails.env.development? } }
281 | ```
282 |
283 | A deeper discussion of this error can be found here: https://github.com/intridea/omniauth/issues/260
284 |
285 | ### Cannot load strategy class
286 |
287 | If for some reason Devise cannot load your strategy class, you can set it explicitly with the `:strategy_class` option:
288 |
289 | ```ruby
290 | config.omniauth :facebook, "APP_ID", "APP_SECRET", :strategy_class => OmniAuth::Strategies::Facebook
291 | ```
292 |
--------------------------------------------------------------------------------
/docs/devise/other-orms.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: other-orms
3 | title: Other ORMs
4 | ---
5 |
6 | Since Devise support both Mongoid and ActiveRecord, we rely on this variable to run specific code for each ORM.
7 | The default value of `DEVISE_ORM` is `active_record`. To run the tests for mongoid, you can pass `mongoid`:
8 | ```
9 | DEVISE_ORM=mongoid bin/test
10 |
11 | ==> Devise.orm = :mongoid
12 | ```
13 | When running the tests for Mongoid, you will need to have a MongoDB server (version 2.0 or newer) running on your system.
14 |
15 | Please note that the command output will show the variable value being used.
--------------------------------------------------------------------------------
/docs/devise/overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: overview
3 | title: Overview
4 | ---
5 | 
6 |
7 | By [Plataformatec](http://plataformatec.com.br/).
8 |
9 | Devise is a flexible authentication solution for Rails based on Warden. It:
10 |
11 | * Is Rack based;
12 | * Is a complete MVC solution based on Rails engines;
13 | * Allows you to have multiple models signed in at the same time;
14 | * Is based on a modularity concept: use only what you really need.
15 |
16 | ## Modules
17 |
18 | It's composed of 10 modules:
19 |
20 | * [Database Authenticatable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/DatabaseAuthenticatable): hashes and stores a password in the database to validate the authenticity of a user while signing in. The authentication can be done both through POST requests or HTTP Basic Authentication.
21 | * [Omniauthable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Omniauthable): adds OmniAuth (https://github.com/omniauth/omniauth) support.
22 | * [Confirmable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Confirmable): sends emails with confirmation instructions and verifies whether an account is already confirmed during sign in.
23 | * [Recoverable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable): resets the user password and sends reset instructions.
24 | * [Registerable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Registerable): handles signing up users through a registration process, also allowing them to edit and destroy their account.
25 | * [Rememberable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Rememberable): manages generating and clearing a token for remembering the user from a saved cookie.
26 | * [Trackable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Trackable): tracks sign in count, timestamps and IP address.
27 | * [Timeoutable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Timeoutable): expires sessions that have not been active in a specified period of time.
28 | * [Validatable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Validatable): provides validations of email and password. It's optional and can be customized, so you're able to define your own validations.
29 | * [Lockable](http://www.rubydoc.info/github/plataformatec/devise/master/Devise/Models/Lockable): locks an account after a specified number of failed sign-in attempts. Can unlock via email or after a specified time period.
30 |
31 | ## RDocs (API)
32 |
33 | You can view the Devise documentation in RDoc format here:
34 |
35 | http://rubydoc.info/github/plataformatec/devise/master/frames
36 |
37 | If you need to use Devise with previous versions of Rails, you can always run "gem server" from the command line after you install the gem to access the old documentation.
38 |
39 |
40 | ## StackOverflow and Mailing List
41 |
42 | If you have any questions, comments, or concerns, please use StackOverflow instead of the GitHub issue tracker:
43 |
44 | http://stackoverflow.com/questions/tagged/devise
45 |
46 | The deprecated mailing list can still be read on
47 |
48 | https://groups.google.com/group/plataformatec-devise
49 |
50 |
51 | ## Running tests
52 | Devise uses [Mini Test](https://github.com/seattlerb/minitest) as test framework.
53 |
54 | * Running all tests:
55 | ```bash
56 | bin/test
57 | ```
58 |
59 | * Running tests for an specific file:
60 | ```bash
61 | bin/test test/models/trackable_test.rb
62 | ```
63 |
64 | * Running a specific test given a regex:
65 | ```bash
66 | bin/test test/models/trackable_test.rb:16
67 | ```
68 |
69 | ## Contributors
70 |
71 | We have a long list of valued contributors. Check them all at:
72 |
73 | https://github.com/plataformatec/devise/graphs/contributors
74 |
75 | ## License
76 |
77 | MIT License. Copyright 2009-2018 Plataformatec. http://plataformatec.com.br
78 |
79 | You are not granted rights or licenses to the trademarks of Plataformatec, including without limitation the Devise name or logo.
--------------------------------------------------------------------------------
/docs/devise/password-reset-tokens-and-rails-logs.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: password-reset-tokens-and-rails-logs
3 | title: Password reset tokens and Rails logs
4 | ---
5 |
6 | If you enable the [Recoverable](http://rubydoc.info/github/plataformatec/devise/master/Devise/Models/Recoverable) module, note that a stolen password reset token could give an attacker access to your application. Devise takes effort to generate random, secure tokens, and stores only token digests in the database, never plaintext. However the default logging behavior in Rails can cause plaintext tokens to leak into log files:
7 |
8 | 1. Action Mailer logs the entire contents of all outgoing emails to the DEBUG level. Password reset tokens delivered to users in email will be leaked.
9 | 2. Active Job logs all arguments to every enqueued job at the INFO level. If you configure Devise to use `deliver_later` to send password reset emails, password reset tokens will be leaked.
10 |
11 | Rails sets the production logger level to DEBUG by default. Consider changing your production logger level to WARN if you wish to prevent tokens from being leaked into your logs. In `config/environments/production.rb`:
12 |
13 | ```ruby
14 | config.log_level = :warn
15 | ```
16 |
--------------------------------------------------------------------------------
/docs/devise/rails-api-mode.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: rails-api-mode
3 | title: Rails API mode
4 | ---
5 |
6 | Rails 5+ has a built-in [API Mode](https://edgeguides.rubyonrails.org/api_app.html) which optimizes Rails for use as an API (only). One of the side effects is that it changes the order of the middleware stack, and this can cause problems for `Devise::Test::IntegrationHelpers`. This problem usually surfaces as an ```undefined method `[]=' for nil:NilClass``` error when using integration test helpers, such as `#sign_in`. The solution is simply to reorder the middlewares by adding the following to test.rb:
7 |
8 | ```ruby
9 | Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Cookies
10 | Rails.application.config.middleware.insert_before Warden::Manager, ActionDispatch::Session::CookieStore
11 | ```
12 |
13 | For a deeper understanding of this, review [this issue](https://github.com/plataformatec/devise/issues/4696).
--------------------------------------------------------------------------------
/docs/devise/starting_with_rails.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: starting-with-rails
3 | title: Starting with rails?
4 | ---
5 |
6 | If you are building your first Rails application, we recommend you *do not* use Devise. Devise requires a good understanding of the Rails Framework. In such cases, we advise you to start a simple authentication system from scratch. Today, we have three resources that should help you get started:
7 |
8 | * Michael Hartl's online book: https://www.railstutorial.org/book/modeling_users
9 | * Ryan Bates' Railscast: http://railscasts.com/episodes/250-authentication-from-scratch
10 | * Codecademy's Ruby on Rails: Authentication and Authorization: https://www.codecademy.com/learn/rails-auth
11 |
12 | Once you have solidified your understanding of Rails and authentication mechanisms, we assure you Devise will be very pleasant to work with. :smiley:
--------------------------------------------------------------------------------
/docs/devise/strong-parameters.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: strong-parameters
3 | title: Strong Parameters
4 | ---
5 |
6 | > The Parameter Sanitizer API has changed for Devise 4.
7 | > *For previous Devise versions see https://github.com/plataformatec/devise/tree/3-stable#strong-parameters*
8 |
9 | When you customize your own views, you may end up adding new attributes to forms. Rails 4 moved the parameter sanitization from the model to the controller, causing Devise to handle this concern at the controller as well.
10 |
11 | There are just three actions in Devise that allow any set of parameters to be passed down to the model, therefore requiring sanitization. Their names and default permitted parameters are:
12 |
13 | * `sign_in` (`Devise::SessionsController#create`) - Permits only the authentication keys (like `email`)
14 | * `sign_up` (`Devise::RegistrationsController#create`) - Permits authentication keys plus `password` and `password_confirmation`
15 | * `account_update` (`Devise::RegistrationsController#update`) - Permits authentication keys plus `password`, `password_confirmation` and `current_password`
16 |
17 | In case you want to permit additional parameters (the lazy way™), you can do so using a simple before filter in your `ApplicationController`:
18 |
19 | ```ruby
20 | class ApplicationController < ActionController::Base
21 | before_action :configure_permitted_parameters, if: :devise_controller?
22 |
23 | protected
24 |
25 | def configure_permitted_parameters
26 | devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
27 | end
28 | end
29 | ```
30 |
31 | The above works for any additional fields where the parameters are simple scalar types. If you have nested attributes (say you're using `accepts_nested_attributes_for`), then you will need to tell devise about those nestings and types:
32 |
33 | ```ruby
34 | class ApplicationController < ActionController::Base
35 | before_action :configure_permitted_parameters, if: :devise_controller?
36 |
37 | protected
38 |
39 | def configure_permitted_parameters
40 | devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name, address_attributes: [:country, :state, :city, :area, :postal_code]])
41 | end
42 | end
43 | ```
44 |
45 | Devise allows you to completely change Devise defaults or invoke custom behaviour by passing a block:
46 |
47 | To permit simple scalar values for username and email, use this
48 |
49 | ```ruby
50 | def configure_permitted_parameters
51 | devise_parameter_sanitizer.permit(:sign_in) do |user_params|
52 | user_params.permit(:username, :email)
53 | end
54 | end
55 | ```
56 |
57 | If you have some checkboxes that express the roles a user may take on registration, the browser will send those selected checkboxes as an array. An array is not one of Strong Parameters' permitted scalars, so we need to configure Devise in the following way:
58 |
59 | ```ruby
60 | def configure_permitted_parameters
61 | devise_parameter_sanitizer.permit(:sign_up) do |user_params|
62 | user_params.permit({ roles: [] }, :email, :password, :password_confirmation)
63 | end
64 | end
65 | ```
66 | For the list of permitted scalars, and how to declare permitted keys in nested hashes and arrays, see
67 |
68 | https://github.com/rails/strong_parameters#nested-parameters
69 |
70 | If you have multiple Devise models, you may want to set up a different parameter sanitizer per model. In this case, we recommend inheriting from `Devise::ParameterSanitizer` and adding your own logic:
71 |
72 | ```ruby
73 | class User::ParameterSanitizer < Devise::ParameterSanitizer
74 | def initialize(*)
75 | super
76 | permit(:sign_up, keys: [:username, :email])
77 | end
78 | end
79 | ```
80 |
81 | And then configure your controllers to use it:
82 |
83 | ```ruby
84 | class ApplicationController < ActionController::Base
85 | protected
86 |
87 | def devise_parameter_sanitizer
88 | if resource_class == User
89 | User::ParameterSanitizer.new(User, :user, params)
90 | else
91 | super # Use the default one
92 | end
93 | end
94 | end
95 | ```
96 |
97 | The example above overrides the permitted parameters for the user to be both `:username` and `:email`. The non-lazy way to configure parameters would be by defining the before filter above in a custom controller. We detail how to configure and customize controllers in some sections below.
--------------------------------------------------------------------------------
/docs/devise/test-helpers.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: test-helpers
3 | title: Test helpers
4 | ---
5 |
6 | Devise includes some test helpers for controller and integration tests.
7 | In order to use them, you need to include the respective module in your test
8 | cases/specs.
9 |
10 | ## Controller tests
11 |
12 | Controller tests require that you include `Devise::Test::ControllerHelpers` on
13 | your test case or its parent `ActionController::TestCase` superclass.
14 | For Rails 5, include `Devise::Test::IntegrationHelpers` instead, since the superclass
15 | for controller tests has been changed to ActionDispatch::IntegrationTest
16 | (for more details, see the [Integration tests](#integration-tests) section).
17 |
18 | ```ruby
19 | class PostsControllerTest < ActionController::TestCase
20 | include Devise::Test::ControllerHelpers
21 | end
22 | ```
23 |
24 | If you're using RSpec, you can put the following inside a file named
25 | `spec/support/devise.rb` or in your `spec/spec_helper.rb` (or
26 | `spec/rails_helper.rb` if you are using `rspec-rails`):
27 |
28 | ```ruby
29 | RSpec.configure do |config|
30 | config.include Devise::Test::ControllerHelpers, type: :controller
31 | config.include Devise::Test::ControllerHelpers, type: :view
32 | end
33 | ```
34 |
35 | Just be sure that this inclusion is made *after* the `require 'rspec/rails'` directive.
36 |
37 | Now you are ready to use the `sign_in` and `sign_out` methods on your controller
38 | tests:
39 |
40 | ```ruby
41 | sign_in @user
42 | sign_in @user, scope: :admin
43 | ```
44 |
45 | If you are testing Devise internal controllers or a controller that inherits
46 | from Devise's, you need to tell Devise which mapping should be used before a
47 | request. This is necessary because Devise gets this information from the router,
48 | but since controller tests do not pass through the router, it needs to be stated
49 | explicitly. For example, if you are testing the user scope, simply use:
50 |
51 | ```ruby
52 | test 'GET new' do
53 | # Mimic the router behavior of setting the Devise scope through the env.
54 | @request.env['devise.mapping'] = Devise.mappings[:user]
55 |
56 | # Use the sign_in helper to sign in a fixture `User` record.
57 | sign_in users(:alice)
58 |
59 | get :new
60 |
61 | # assert something
62 | end
63 | ```
64 |
65 | ## Integration tests
66 |
67 | Integration test helpers are available by including the
68 | `Devise::Test::IntegrationHelpers` module.
69 |
70 | ```ruby
71 | class PostsTests < ActionDispatch::IntegrationTest
72 | include Devise::Test::IntegrationHelpers
73 | end
74 | ```
75 |
76 | Now you can use the following `sign_in` and `sign_out` methods in your integration
77 | tests:
78 |
79 | ```ruby
80 | sign_in users(:bob)
81 | sign_in users(:bob), scope: :admin
82 |
83 | sign_out :user
84 | ```
85 |
86 | RSpec users can include the `IntegrationHelpers` module on their `:feature` specs.
87 |
88 | ```ruby
89 | RSpec.configure do |config|
90 | config.include Devise::Test::IntegrationHelpers, type: :feature
91 | end
92 | ```
93 |
94 | Unlike controller tests, integration tests do not need to supply the
95 | `devise.mapping` `env` value, as the mapping can be inferred by the routes that
96 | are executed in your tests.
97 |
98 | You can read more about testing your Rails 3 - Rails 4 controllers with RSpec in the wiki:
99 |
100 | * https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-(and-RSpec)
--------------------------------------------------------------------------------
/docs/rails/action_mailbox_basics.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: action-mailbox
3 | title: Action Mailbox Basics
4 | ---
5 | This guide provides you with all you need to get started in receiving
6 | emails to your application.
7 |
8 | After reading this guide, you will know:
9 |
10 | * How to receive email within a Rails application.
11 | * How to configure Action Mailbox.
12 | * How to generate and route emails to a mailbox.
13 | * How to test incoming emails.
14 |
15 | --------------------------------------------------------------------------------
16 |
17 | Introduction
18 | ------------
19 |
20 | Action Mailbox routes incoming emails to controller-like mailboxes for
21 | processing in Rails. It ships with ingresses for Mailgun, Mandrill, Postmark,
22 | and SendGrid. You can also handle inbound mails directly via the built-in Exim,
23 | Postfix, and Qmail ingresses.
24 |
25 | The inbound emails are turned into `InboundEmail` records using Active Record
26 | and feature lifecycle tracking, storage of the original email on cloud storage
27 | via Active Storage, and responsible data handling with
28 | on-by-default incineration.
29 |
30 | These inbound emails are routed asynchronously using Active Job to one or
31 | several dedicated mailboxes, which are capable of interacting directly
32 | with the rest of your domain model.
33 |
34 | ## Setup
35 |
36 | Install migrations needed for `InboundEmail` and ensure Active Storage is set up:
37 |
38 | ```bash
39 | $ rails action_mailbox:install
40 | $ rails db:migrate
41 | ```
42 |
43 | ## Configuration
44 |
45 | ### Exim
46 |
47 | Tell Action Mailbox to accept emails from an SMTP relay:
48 |
49 | ```ruby
50 | # config/environments/production.rb
51 | config.action_mailbox.ingress = :relay
52 | ```
53 |
54 | Generate a strong password that Action Mailbox can use to authenticate requests to the relay ingress.
55 |
56 | Use `rails credentials:edit` to add the password to your application's encrypted credentials under
57 | `action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
58 |
59 | ```yaml
60 | action_mailbox:
61 | ingress_password: ...
62 | ```
63 |
64 | Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
65 |
66 | Configure Exim to pipe inbound emails to `bin/rails action_mailbox:ingress:exim`,
67 | providing the `URL` of the relay ingress and the `INGRESS_PASSWORD` you
68 | previously generated. If your application lived at `https://example.com`, the
69 | full command would look like this:
70 |
71 | ```shell
72 | bin/rails action_mailbox:ingress:exim URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...
73 | ```
74 |
75 | ### Mailgun
76 |
77 | Give Action Mailbox your
78 | [Mailgun API key](https://help.mailgun.com/hc/en-us/articles/203380100-Where-can-I-find-my-API-key-and-SMTP-credentials)
79 | so it can authenticate requests to the Mailgun ingress.
80 |
81 | Use `rails credentials:edit` to add your API key to your application's
82 | encrypted credentials under `action_mailbox.mailgun_api_key`,
83 | where Action Mailbox will automatically find it:
84 |
85 | ```yaml
86 | action_mailbox:
87 | mailgun_api_key: ...
88 | ```
89 |
90 | Alternatively, provide your API key in the `MAILGUN_INGRESS_API_KEY` environment
91 | variable.
92 |
93 | Tell Action Mailbox to accept emails from Mailgun:
94 |
95 | ```ruby
96 | # config/environments/production.rb
97 | config.action_mailbox.ingress = :mailgun
98 | ```
99 |
100 | [Configure Mailgun](https://documentation.mailgun.com/en/latest/user_manual.html#receiving-forwarding-and-storing-messages)
101 | to forward inbound emails to `/rails/action_mailbox/mailgun/inbound_emails/mime`.
102 | If your application lived at `https://example.com`, you would specify the
103 | fully-qualified URL `https://example.com/rails/action_mailbox/mailgun/inbound_emails/mime`.
104 |
105 | ### Mandrill
106 |
107 | Give Action Mailbox your Mandrill API key so it can authenticate requests to
108 | the Mandrill ingress.
109 |
110 | Use `rails credentials:edit` to add your API key to your application's
111 | encrypted credentials under `action_mailbox.mandrill_api_key`,
112 | where Action Mailbox will automatically find it:
113 |
114 | ```yaml
115 | action_mailbox:
116 | mandrill_api_key: ...
117 | ```
118 |
119 | Alternatively, provide your API key in the `MANDRILL_INGRESS_API_KEY`
120 | environment variable.
121 |
122 | Tell Action Mailbox to accept emails from Mandrill:
123 |
124 | ```ruby
125 | # config/environments/production.rb
126 | config.action_mailbox.ingress = :mandrill
127 | ```
128 |
129 | [Configure Mandrill](https://mandrill.zendesk.com/hc/en-us/articles/205583197-Inbound-Email-Processing-Overview)
130 | to route inbound emails to `/rails/action_mailbox/mandrill/inbound_emails`.
131 | If your application lived at `https://example.com`, you would specify
132 | the fully-qualified URL `https://example.com/rails/action_mailbox/mandrill/inbound_emails`.
133 |
134 | ### Postfix
135 |
136 | Tell Action Mailbox to accept emails from an SMTP relay:
137 |
138 | ```ruby
139 | # config/environments/production.rb
140 | config.action_mailbox.ingress = :relay
141 | ```
142 |
143 | Generate a strong password that Action Mailbox can use to authenticate requests to the relay ingress.
144 |
145 | Use `rails credentials:edit` to add the password to your application's encrypted credentials under
146 | `action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
147 |
148 | ```yaml
149 | action_mailbox:
150 | ingress_password: ...
151 | ```
152 |
153 | Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
154 |
155 | [Configure Postfix](https://serverfault.com/questions/258469/how-to-configure-postfix-to-pipe-all-incoming-email-to-a-script)
156 | to pipe inbound emails to `bin/rails action_mailbox:ingress:postfix`, providing
157 | the `URL` of the Postfix ingress and the `INGRESS_PASSWORD` you previously
158 | generated. If your application lived at `https://example.com`, the full command
159 | would look like this:
160 |
161 | ```shell
162 | $ bin/rails action_mailbox:ingress:postfix URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...
163 | ```
164 |
165 | ### Postmark
166 |
167 | Tell Action Mailbox to accept emails from Postmark:
168 |
169 | ```ruby
170 | # config/environments/production.rb
171 | config.action_mailbox.ingress = :postmark
172 | ```
173 |
174 | Generate a strong password that Action Mailbox can use to authenticate
175 | requests to the Postmark ingress.
176 |
177 | Use `rails credentials:edit` to add the password to your application's
178 | encrypted credentials under `action_mailbox.ingress_password`,
179 | where Action Mailbox will automatically find it:
180 |
181 | ```yaml
182 | action_mailbox:
183 | ingress_password: ...
184 | ```
185 |
186 | Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD`
187 | environment variable.
188 |
189 | [Configure Postmark inbound webhook](https://postmarkapp.com/manual#configure-your-inbound-webhook-url)
190 | to forward inbound emails to `/rails/action_mailbox/postmark/inbound_emails` with the username `actionmailbox`
191 | and the password you previously generated. If your application lived at `https://example.com`, you would
192 | configure Postmark with the following fully-qualified URL:
193 |
194 | ```
195 | https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/postmark/inbound_emails
196 | ```
197 |
198 | NOTE: When configuring your Postmark inbound webhook, be sure to check the box labeled **"Include raw email content in JSON payload"**.
199 | Action Mailbox needs the raw email content to work.
200 |
201 | ### Qmail
202 |
203 | Tell Action Mailbox to accept emails from an SMTP relay:
204 |
205 | ```ruby
206 | # config/environments/production.rb
207 | config.action_mailbox.ingress = :relay
208 | ```
209 |
210 | Generate a strong password that Action Mailbox can use to authenticate requests to the relay ingress.
211 |
212 | Use `rails credentials:edit` to add the password to your application's encrypted credentials under
213 | `action_mailbox.ingress_password`, where Action Mailbox will automatically find it:
214 |
215 | ```yaml
216 | action_mailbox:
217 | ingress_password: ...
218 | ```
219 |
220 | Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` environment variable.
221 |
222 | Configure Qmail to pipe inbound emails to `bin/rails action_mailbox:ingress:qmail`,
223 | providing the `URL` of the relay ingress and the `INGRESS_PASSWORD` you
224 | previously generated. If your application lived at `https://example.com`, the
225 | full command would look like this:
226 |
227 | ```shell
228 | bin/rails action_mailbox:ingress:qmail URL=https://example.com/rails/action_mailbox/relay/inbound_emails INGRESS_PASSWORD=...
229 | ```
230 |
231 | ### SendGrid
232 |
233 | Tell Action Mailbox to accept emails from SendGrid:
234 |
235 | ```ruby
236 | # config/environments/production.rb
237 | config.action_mailbox.ingress = :sendgrid
238 | ```
239 |
240 | Generate a strong password that Action Mailbox can use to authenticate
241 | requests to the SendGrid ingress.
242 |
243 | Use `rails credentials:edit` to add the password to your application's
244 | encrypted credentials under `action_mailbox.ingress_password`,
245 | where Action Mailbox will automatically find it:
246 |
247 | ```yaml
248 | action_mailbox:
249 | ingress_password: ...
250 | ```
251 |
252 | Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD`
253 | environment variable.
254 |
255 | [Configure SendGrid Inbound Parse](https://sendgrid.com/docs/for-developers/parsing-email/setting-up-the-inbound-parse-webhook/)
256 | to forward inbound emails to
257 | `/rails/action_mailbox/sendgrid/inbound_emails` with the username `actionmailbox`
258 | and the password you previously generated. If your application lived at `https://example.com`,
259 | you would configure SendGrid with the following URL:
260 |
261 | ```
262 | https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/sendgrid/inbound_emails
263 | ```
264 |
265 | NOTE: When configuring your SendGrid Inbound Parse webhook, be sure to check the box labeled **“Post the raw, full MIME message.”** Action Mailbox needs the raw MIME message to work.
266 |
267 | ## Examples
268 |
269 | Configure basic routing:
270 |
271 | ```ruby
272 | # app/mailboxes/application_mailbox.rb
273 | class ApplicationMailbox < ActionMailbox::Base
274 | routing /^save@/i => :forwards
275 | routing /@replies\./i => :replies
276 | end
277 | ```
278 |
279 | Then set up a mailbox:
280 |
281 | ```ruby
282 | # Generate new mailbox
283 | $ bin/rails generate mailbox forwards
284 | ```
285 |
286 | ```ruby
287 | # app/mailboxes/forwards_mailbox.rb
288 | class ForwardsMailbox < ApplicationMailbox
289 | # Callbacks specify prerequisites to processing
290 | before_processing :require_forward
291 |
292 | def process
293 | if forwarder.buckets.one?
294 | record_forward
295 | else
296 | stage_forward_and_request_more_details
297 | end
298 | end
299 |
300 | private
301 | def require_forward
302 | unless message.forward?
303 | # Use Action Mailers to bounce incoming emails back to sender – this halts processing
304 | bounce_with Forwards::BounceMailer.missing_forward(
305 | inbound_email, forwarder: forwarder
306 | )
307 | end
308 | end
309 |
310 | def forwarder
311 | @forwarder ||= Person.where(email_address: mail.from)
312 | end
313 |
314 | def record_forward
315 | forwarder.buckets.first.record \
316 | Forward.new forwarder: forwarder, subject: message.subject, content: mail.content
317 | end
318 |
319 | def stage_forward_and_request_more_details
320 | Forwards::RoutingMailer.choose_project(mail).deliver_now
321 | end
322 | end
323 | ```
324 |
325 | ## Incineration of InboundEmails
326 |
327 | By default, an InboundEmail that has been successfully processed will be
328 | incinerated after 30 days. This ensures you're not holding on to people's data
329 | willy-nilly after they may have canceled their accounts or deleted their
330 | content. The intention is that after you've processed an email, you should have
331 | extracted all the data you needed and turned it into domain models and content
332 | on your side of the application. The InboundEmail simply stays in the system
333 | for the extra time to provide debugging and forensics options.
334 |
335 | The actual incineration is done via the `IncinerationJob` that's scheduled
336 | to run after `config.action_mailbox.incinerate_after` time. This value is
337 | by default set to `30.days`, but you can change it in your production.rb
338 | configuration. (Note that this far-future incineration scheduling relies on
339 | your job queue being able to hold jobs for that long.)
340 |
341 | ## Working with Action Mailbox in development
342 |
343 | It's helpful to be able to test incoming emails in development without actually
344 | sending and receiving real emails. To accomplish this, there's a conductor
345 | controller mounted at `/rails/conductor/action_mailbox/inbound_emails`,
346 | which gives you an index of all the InboundEmails in the system, their
347 | state of processing, and a form to create a new InboundEmail as well.
348 |
349 | ## Testing mailboxes
350 |
351 | Example:
352 |
353 | ```ruby
354 | class ForwardsMailboxTest < ActionMailbox::TestCase
355 | test "directly recording a client forward for a forwarder and forwardee corresponding to one project" do
356 | assert_difference -> { people(:david).buckets.first.recordings.count } do
357 | receive_inbound_email_from_mail \
358 | to: 'save@example.com',
359 | from: people(:david).email_address,
360 | subject: "Fwd: Status update?",
361 | body: <<~BODY
362 | --- Begin forwarded message ---
363 | From: Frank Holland
364 |
365 | What's the status?
366 | BODY
367 | end
368 |
369 | recording = people(:david).buckets.first.recordings.last
370 | assert_equal people(:david), recording.creator
371 | assert_equal "Status update?", recording.forward.subject
372 | assert_match "What's the status?", recording.forward.content.to_s
373 | end
374 | end
375 | ```
376 |
--------------------------------------------------------------------------------
/docs/rails/action_text_overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: action-text
3 | title: Action Text Overview
4 | ---
5 |
6 | This guide provides you with all you need to get started in handling
7 | rich text content.
8 |
9 | After reading this guide, you will know:
10 |
11 | * How to configure Action Text.
12 | * How to handle rich text content.
13 | * How to style rich text content.
14 |
15 | --------------------------------------------------------------------------------
16 |
17 | Introduction
18 | ------------
19 |
20 | Action Text brings rich text content and editing to Rails. It includes
21 | the [Trix editor](https://trix-editor.org) that handles everything from formatting
22 | to links to quotes to lists to embedded images and galleries.
23 | The rich text content generated by the Trix editor is saved in its own
24 | RichText model that's associated with any existing Active Record model in the application.
25 | Any embedded images (or other attachments) are automatically stored using
26 | Active Storage and associated with the included RichText model.
27 |
28 | ## Trix compared to other rich text editors
29 |
30 | Most WYSIWYG editors are wrappers around HTML’s `contenteditable` and `execCommand` APIs,
31 | designed by Microsoft to support live editing of web pages in Internet Explorer 5.5,
32 | and [eventually reverse-engineered](https://blog.whatwg.org/the-road-to-html-5-contenteditable#history)
33 | and copied by other browsers.
34 |
35 | Because these APIs were never fully specified or documented,
36 | and because WYSIWYG HTML editors are enormous in scope, each
37 | browser's implementation has its own set of bugs and quirks,
38 | and JavaScript developers are left to resolve the inconsistencies.
39 |
40 | Trix sidesteps these inconsistencies by treating contenteditable
41 | as an I/O device: when input makes its way to the editor, Trix converts that input
42 | into an editing operation on its internal document model, then re-renders
43 | that document back into the editor. This gives Trix complete control over what
44 | happens after every keystroke, and avoids the need to use execCommand at all.
45 |
46 | ## Installation
47 |
48 | Run `rails action_text:install` to add the Yarn package and copy over the necessary migration.
49 | Also, you need to set up Active Storage for embedded images and other attachments.
50 | Please refer to the [Active Storage Overview](active_storage_overview.md) guide.
51 |
52 | ## Examples
53 |
54 | Adding a rich text field to an existing model:
55 |
56 | ```ruby
57 | # app/models/message.rb
58 | class Message < ApplicationRecord
59 | has_rich_text :content
60 | end
61 | ```
62 |
63 | Then refer to this field in the form for the model:
64 |
65 | ```erb
66 | <%# app/views/messages/_form.html.erb %>
67 | <%= form_with(model: message) do |form| %>
68 |
72 | <% end %>
73 | ```
74 |
75 | And finally display the sanitized rich text on a page:
76 |
77 | ```erb
78 | <%= @message.content %>
79 | ```
80 |
81 | To accept the rich text content, all you have to do is permit the referenced attribute:
82 |
83 | ```ruby
84 | class MessagesController < ApplicationController
85 | def create
86 | message = Message.create! params.require(:message).permit(:title, :content)
87 | redirect_to message
88 | end
89 | end
90 | ```
91 |
92 | ## Custom styling
93 |
94 | By default, the Action Text editor and content is styled by the Trix defaults.
95 | If you want to change these defaults, you'll want to remove
96 | the `app/assets/stylesheets/actiontext.scss` linker and base your stylings on
97 | the [contents of that file](https://raw.githubusercontent.com/basecamp/trix/master/dist/trix.css).
98 |
99 | You can also style the HTML used for embedded images and other attachments (known as blobs).
100 | On installation, Action Text will copy over a partial to
101 | `app/views/active_storage/blobs/_blob.html.erb`, which you can specialize.
102 |
--------------------------------------------------------------------------------
/docs/rails/active_record_multiple_databases.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: multiple-databases
3 | title: Multiple Databases with Active Record
4 | ---
5 |
6 | This guide covers using multiple databases with your Rails application.
7 |
8 | After reading this guide you will know:
9 |
10 | * How to setup your application for multiple databases.
11 | * How automatic connection switching works.
12 | * What features are supported and what's still a work in progress.
13 |
14 | --------------------------------------------------------------------------------
15 |
16 | As an application grows in popularity and usage you'll need to scale the application
17 | to support your new users and their data. One way in which your application may need
18 | to scale is on the database level. Rails now has support for multiple databases
19 | so you don't have to store your data all in one place.
20 |
21 | At this time the following features are supported:
22 |
23 | * Multiple primary databases and a replica for each
24 | * Automatic connection switching for the model you're working with
25 | * Automatic swapping between the primary and replica depending on the HTTP verb
26 | and recent writes
27 | * Rails tasks for creating, dropping, migrating, and interacting with the multiple
28 | databases
29 |
30 | The following features are not (yet) supported:
31 |
32 | * Sharding
33 | * Joining across clusters
34 | * Load balancing replicas
35 |
36 | ## Setting up your application
37 |
38 | While Rails tries to do most of the work for you there are still some steps you'll
39 | need to do to get your application ready for multiple databases.
40 |
41 | Let's say we have an application with a single primary database and we need to add a
42 | new database for some new tables we're adding. The name of the new database will be
43 | "animals".
44 |
45 | The database.yml looks like this:
46 |
47 | ```yaml
48 | production:
49 | database: my_primary_database
50 | user: root
51 | adapter: mysql
52 | ```
53 |
54 | Let's add a replica for the primary, a new writer called animals and a replica for that
55 | as well. To do this we need to change our database.yml from a 2-tier to a 3-tier config.
56 |
57 | ```yaml
58 | production:
59 | primary:
60 | database: my_primary_database
61 | user: root
62 | adapter: mysql
63 | primary_replica:
64 | database: my_primary_database
65 | user: root_readonly
66 | adapter: mysql
67 | replica: true
68 | animals:
69 | database: my_animals_database
70 | user: animals_root
71 | adapter: mysql
72 | migrations_paths: db/animals_migrate
73 | animals_replica:
74 | database: my_animals_database
75 | user: animals_readonly
76 | adapter: mysql
77 | replica: true
78 | ```
79 |
80 | When using multiple databases there are a few important settings.
81 |
82 | First, the database name for the primary and replica should be the same because they contain
83 | the same data. Second, the username for the primary and replica should be different, and the
84 | replica user's permissions should be to read and not write.
85 |
86 | When using a replica database you need to add a `replica: true` entry to the replica in the
87 | `database.yml`. This is because Rails otherwise has no way of knowing which one is a replica
88 | and which one is the primary.
89 |
90 | Lastly, for new primary databases you need to set the `migrations_paths` to the directory
91 | where you will store migrations for that database. We'll look more at `migrations_paths`
92 | later on in this guide.
93 |
94 | Now that we have a new database, let's set up the model. In order to use the new database we
95 | need to create a new abstract class and connect to the animals databases.
96 |
97 | ```ruby
98 | class AnimalsBase < ApplicationRecord
99 | self.abstract_class = true
100 |
101 | connects_to database: { writing: :animals, reading: :animals_replica }
102 | end
103 | ```
104 | Then we need to
105 | update `ApplicationRecord` to be aware of our new replica.
106 |
107 | ```ruby
108 | class ApplicationRecord < ActiveRecord::Base
109 | self.abstract_class = true
110 |
111 | connects_to database: { writing: :primary, reading: :primary_replica }
112 | end
113 | ```
114 |
115 | By default Rails expects the database roles to be `writing` and `reading` for the primary
116 | and replica respectively. If you have a legacy system you may already have roles set up that
117 | you don't want to change. In that case you can set a new role name in your application config.
118 |
119 | ```ruby
120 | config.active_record.writing_role = :default
121 | config.active_record.reading_role = :readonly
122 | ```
123 |
124 | Now that we have the database.yml and the new model set up it's time to create the databases.
125 | Rails 6.0 ships with all the rails tasks you need to use multiple databases in Rails.
126 |
127 | You can run `rails -T` to see all the commands you're able to run. You should see the following:
128 |
129 | ```
130 | $ rails -T
131 | rails db:create # Creates the database from DATABASE_URL or config/database.yml for the ...
132 | rails db:create:animals # Create animals database for current environment
133 | rails db:create:primary # Create primary database for current environment
134 | rails db:drop # Drops the database from DATABASE_URL or config/database.yml for the cu...
135 | rails db:drop:animals # Drop animals database for current environment
136 | rails db:drop:primary # Drop primary database for current environment
137 | rails db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
138 | rails db:migrate:animals # Migrate animals database for current environment
139 | rails db:migrate:primary # Migrate primary database for current environment
140 | rails db:migrate:status # Display status of migrations
141 | rails db:migrate:status:animals # Display status of migrations for animals database
142 | rails db:migrate:status:primary # Display status of migrations for primary database
143 | ```
144 |
145 | Running a command like `rails db:create` will create both the primary and animals databases.
146 | Note that there is no command for creating the users and you'll need to do that manually
147 | to support the readonly users for your replicas. If you want to create just the animals
148 | database you can run `rails db:create:animals`.
149 |
150 | ## Migrations
151 |
152 | Migrations for multiple databases should live in their own folders prefixed with the
153 | name of the database key in the configuration.
154 |
155 | You also need to set the `migrations_paths` in the database configurations to tell Rails
156 | where to find the migrations.
157 |
158 | For example the `animals` database would look in the `db/animals_migrate` directory and
159 | `primary` would look in `db/migrate`. Rails generators now take a `--database` option
160 | so that the file is generated in the correct directory. The command can be run like so:
161 |
162 | ```
163 | $ rails g migration CreateDogs name:string --database animals
164 | ```
165 |
166 | ## Activating automatic connection switching
167 |
168 | Finally, in order to use the read-only replica in your application you'll need to activate
169 | the middleware for automatic switching.
170 |
171 | Automatic switching allows the application to switch from the primary to replica or replica
172 | to primary based on the HTTP verb and whether there was a recent write.
173 |
174 | If the application is receiving a POST, PUT, DELETE, or PATCH request the application will
175 | automatically write to the primary. For the specified time after the write the application
176 | will read from the replica. For a GET or HEAD request the application will read from the
177 | replica unless there was a recent write.
178 |
179 | To activate the automatic connection switching middleware, add or uncomment the following
180 | lines in your application config.
181 |
182 | ```ruby
183 | config.active_record.database_selector = { delay: 2.seconds }
184 | config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
185 | config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
186 | ```
187 |
188 | Rails guarantees "read your own write" and will send your GET or HEAD request to the
189 | primary if it's within the `delay` window. By default the delay is set to 2 seconds. You
190 | should change this based on your database infrastructure. Rails doesn't guarantee "read
191 | a recent write" for other users within the delay window and will send GET and HEAD requests
192 | to the replicas unless they wrote recently.
193 |
194 | The automatic connection switching in Rails is relatively primitive and deliberately doesn't
195 | do a whole lot. The goal was a system that demonstrated how to do automatic connection
196 | switching that was flexible enough to be customizable by app developers.
197 |
198 | The setup in Rails allows you to easily change how the switching is done and what
199 | parameters it's based on. Let's say you want to use a cookie instead of a session to
200 | decide when to swap connections. You can write your own class:
201 |
202 | ```ruby
203 | class MyCookieResolver
204 | # code for your cookie class
205 | end
206 | ```
207 |
208 | And then pass it to the middleware:
209 |
210 | ```ruby
211 | config.active_record.database_selector = { delay: 2.seconds }
212 | config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
213 | config.active_record.database_resolver_context = MyCookieResolver
214 | ```
215 |
216 | ## Using manual connection switching
217 |
218 | There are some cases where you may want your application to connect to a primary or a replica
219 | and the automatic connection switching isn't adequate. For example, you may know that for a
220 | particular request you always want to send the request to a replica, even when you are in a
221 | POST request path.
222 |
223 | To do this Rails provides a `connected_to` method that will switch to the connection you
224 | need.
225 |
226 | ```ruby
227 | ActiveRecord::Base.connected_to(role: :reading) do
228 | # all code in this block will be connected to the reading role
229 | end
230 | ```
231 |
232 | The "role" in the `connected_to` call looks up the connections that are connected on that
233 | connection handler (or role). The `reading` connection handler will hold all the connections
234 | that were connected via `connects_to` with the role name of `reading`.
235 |
236 | There also may be a case where you have a database that you don't always want to connect to
237 | on application boot but may need for a slow query or analytics. After defining that database
238 | in the database.yml you can connect by passing a database argument to `connected_to`
239 |
240 | ```ruby
241 | ActiveRecord::Base.connected_to(database: { reading_slow: :animals_slow_replica }) do
242 | # do something while connected to the slow replica
243 | end
244 | ```
245 |
246 | The `database` argument for `connected_to` will take a symbol or a config hash.
247 |
248 | Note that `connected_to` with a role will look up an existing connection and switch
249 | using the connection specification name. This means that if you pass an unknown role
250 | like `connected_to(role: :nonexistent)` you will get an error that says
251 | `ActiveRecord::ConnectionNotEstablished (No connection pool with 'AnimalsBase' found
252 | for the 'nonexistent' role.)`
253 |
254 | ## Caveats
255 |
256 | As noted at the top, Rails doesn't (yet) support sharding. We had to do a lot of work
257 | to support multiple databases for Rails 6.0. The lack of support for sharding isn't
258 | an oversight, but does require additional work that didn't make it in for 6.0. For now
259 | if you need sharding it may be advisable to continue using one of the many gems
260 | that supports this.
261 |
262 | Rails also doesn't support automatic load balancing of replicas. This is very
263 | dependent on your infrastructure. We may implement basic, primitive load balancing
264 | in the future, but for an application at scale this should be something your application
265 | handles outside of Rails.
266 |
267 | Lastly, you cannot join across databases. Rails 6.1 will support using `has_many`
268 | relationships and creating 2 queries instead of joining, but Rails 6.0 will require
269 | you to split the joins into 2 selects manually.
270 |
--------------------------------------------------------------------------------
/docs/rails/development_dependencies_install.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: development-dependencies-install
3 | title: Development Dependencies Install
4 | ---
5 |
6 | This guide covers how to setup an environment for Ruby on Rails core development.
7 |
8 | After reading this guide, you will know:
9 |
10 | * How to set up your machine for Rails development
11 |
12 | --------------------------------------------------------------------------------
13 |
14 | The Easy Way
15 | ------------
16 |
17 | The easiest and recommended way to get a development environment ready to hack is to use the [Rails development box](https://github.com/rails/rails-dev-box).
18 |
19 | The Hard Way
20 | ------------
21 |
22 | In case you can't use the Rails development box, see the steps below to manually
23 | build a development box for Ruby on Rails core development.
24 |
25 | ### Install Git
26 |
27 | Ruby on Rails uses Git for source code control. The [Git homepage](https://git-scm.com/) has installation instructions. There are a variety of resources on the net that will help you get familiar with Git:
28 |
29 | * [Try Git course](https://try.github.io/) is an interactive course that will teach you the basics.
30 | * The [official Documentation](https://git-scm.com/documentation) is pretty comprehensive and also contains some videos with the basics of Git.
31 | * [Everyday Git](https://schacon.github.io/git/everyday.html) will teach you just enough about Git to get by.
32 | * [GitHub](https://help.github.com/) offers links to a variety of Git resources.
33 | * [Pro Git](https://git-scm.com/book) is an entire book about Git with a Creative Commons license.
34 |
35 | ### Clone the Ruby on Rails Repository
36 |
37 | Navigate to the folder where you want the Ruby on Rails source code (it will create its own `rails` subdirectory) and run:
38 |
39 | ```bash
40 | $ git clone https://github.com/rails/rails.git
41 | $ cd rails
42 | ```
43 |
44 | ### Install Additional Tools and Services
45 |
46 | Some Rails tests depend on additional tools that you need to install before running those specific tests.
47 |
48 | Here's the list of each gems' additional dependencies:
49 |
50 | * Action Cable depends on Redis
51 | * Active Record depends on SQLite3, MySQL and PostgreSQL
52 | * Active Storage depends on Yarn (additionally Yarn depends on
53 | [Node.js](https://nodejs.org/)), ImageMagick, FFmpeg, muPDF, and on macOS
54 | also XQuartz and Poppler.
55 | * Active Support depends on memcached and Redis
56 | * Railties depend on a JavaScript runtime environment, such as having
57 | [Node.js](https://nodejs.org/) installed.
58 |
59 | Install all the services you need to properly test the full gem you'll be
60 | making changes to.
61 |
62 | NOTE: Redis' documentation discourage installations with package managers as those are usually outdated. Installing from source and bringing the server up is straight forward and well documented on [Redis' documentation](https://redis.io/download#installation).
63 |
64 | NOTE: Active Record tests _must_ pass for at least MySQL, PostgreSQL, and SQLite3. Subtle differences between the various adapters have been behind the rejection of many patches that looked OK when tested only against single adapter.
65 |
66 | Below you can find instructions on how to install all of the additional
67 | tools for different OSes.
68 |
69 | #### macOS
70 |
71 | On macOS you can use [Homebrew](https://brew.sh/) to install all of the
72 | additional tools.
73 |
74 | To install all run:
75 |
76 | ```bash
77 | $ brew bundle
78 | ```
79 |
80 | You'll also need to start each of the installed services. To list all
81 | available services run:
82 |
83 | ```bash
84 | $ brew services list
85 | ```
86 |
87 | You can then start each of the services one by one like this:
88 |
89 | ```bash
90 | $ brew services start mysql
91 | ```
92 |
93 | Replace `mysql` with the name of the service you want to start.
94 |
95 | #### Ubuntu
96 |
97 | To install all run:
98 |
99 | ```bash
100 | $ sudo apt-get update
101 | $ sudo apt-get install sqlite3 libsqlite3-dev
102 | mysql-server libmysqlclient-dev
103 | postgresql postgresql-client postgresql-contrib libpq-dev
104 | redis-server memcached imagemagick ffmpeg mupdf mupdf-tools
105 |
106 | # Install Yarn
107 | $ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
108 | $ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
109 | $ sudo apt-get install yarn
110 | ```
111 |
112 | #### Fedora or CentOS
113 |
114 | To install all run:
115 |
116 | ```bash
117 | $ sudo dnf install sqlite-devel sqlite-libs
118 | mysql-server mysql-devel
119 | postgresql-server postgresql-devel
120 | redis memcached imagemagick ffmpeg mupdf
121 |
122 | # Install Yarn
123 | # Use this command if you do not have Node.js installed
124 | $ curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
125 | # If you have Node.js installed, use this command instead
126 | $ curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo
127 | $ sudo dnf install yarn
128 | ```
129 |
130 | #### Arch Linux
131 |
132 | To install all run:
133 |
134 | ```bash
135 | $ sudo pacman -S sqlite
136 | mariadb libmariadbclient mariadb-clients
137 | postgresql postgresql-libs
138 | redis memcached imagemagick ffmpeg mupdf mupdf-tools poppler
139 | yarn
140 | $ sudo systemctl start redis
141 | ```
142 |
143 | NOTE: If you are running Arch Linux, MySQL isn't supported anymore so you will need to
144 | use MariaDB instead (see [this announcement](https://www.archlinux.org/news/mariadb-replaces-mysql-in-repositories/)).
145 |
146 | #### FreeBSD
147 |
148 | To install all run:
149 |
150 | ```bash
151 | # pkg install sqlite3
152 | mysql80-client mysql80-server
153 | postgresql11-client postgresql11-server
154 | memcached imagemagick ffmpeg mupdf
155 | yarn
156 | # portmaster databases/redis
157 | ```
158 |
159 | Or install everything through ports (these packages are located under the
160 | `databases` folder).
161 |
162 | NOTE: If you run into troubles during the installation of MySQL, please see
163 | [the MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/freebsd-installation.html).
164 |
165 | ### Database Configuration
166 |
167 | There are couple of additional steps required to configure database engines
168 | required for running Active Record tests.
169 |
170 | In order to be able to run the test suite against MySQL you need to create a user named `rails` with privileges on the test databases:
171 |
172 | ```bash
173 | $ mysql -uroot -p
174 |
175 | mysql> CREATE USER 'rails'@'localhost';
176 | mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.*
177 | to 'rails'@'localhost';
178 | mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.*
179 | to 'rails'@'localhost';
180 | mysql> GRANT ALL PRIVILEGES ON inexistent_activerecord_unittest.*
181 | to 'rails'@'localhost';
182 | ```
183 |
184 | PostgreSQL's authentication works differently. To setup the development environment
185 | with your development account, on Linux or BSD, you just have to run:
186 |
187 | ```bash
188 | $ sudo -u postgres createuser --superuser $USER
189 | ```
190 |
191 | and for macOS:
192 |
193 | ```bash
194 | $ createuser --superuser $USER
195 | ```
196 |
197 | Then, you need to create the test databases for both MySQL and PostgreSQL with:
198 |
199 | ```bash
200 | $ cd activerecord
201 | $ bundle exec rake db:create
202 | ```
203 |
204 | NOTE: You'll see the following warning (or localized warning) during activating HStore extension in PostgreSQL 9.1.x or earlier: "WARNING: => is deprecated as an operator".
205 |
206 | You can also create test databases for each database engine separately:
207 |
208 | ```bash
209 | $ cd activerecord
210 | $ bundle exec rake db:mysql:build
211 | $ bundle exec rake db:postgresql:build
212 | ```
213 |
214 | and you can drop the databases using:
215 |
216 | ```bash
217 | $ cd activerecord
218 | $ bundle exec rake db:drop
219 | ```
220 |
221 | NOTE: Using the Rake task to create the test databases ensures they have the correct character set and collation.
222 |
223 | If you're using another database, check the file `activerecord/test/config.yml` or `activerecord/test/config.example.yml` for default connection information. You can edit `activerecord/test/config.yml` to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails.
224 |
225 | ### Install JavaScript dependencies
226 |
227 | If you installed Yarn, you will need to install the javascript dependencies:
228 |
229 | ```bash
230 | $ yarn install
231 | ```
232 |
233 | ### Install Bundler gem
234 |
235 | Get a recent version of [Bundler](https://bundler.io/)
236 |
237 | ```bash
238 | $ gem install bundler
239 | $ gem update bundler
240 | ```
241 |
242 | and run:
243 |
244 | ```bash
245 | $ bundle install
246 | ```
247 |
248 | or:
249 |
250 | ```bash
251 | $ bundle install --without db
252 | ```
253 |
254 | if you don't need to run Active Record tests.
255 |
256 | ### Contribute to Rails
257 |
258 | After you've setup everything, read how you can start [contributing](contributing_to_ruby_on_rails.html#running-an-application-against-your-local-branch).
259 |
--------------------------------------------------------------------------------
/docs/rails/maintenance_policy.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: maintenance-policy
3 | title: Maintenance Policy for Ruby on Rails
4 | ---
5 |
6 | Support of the Rails framework is divided into four groups: New features, bug
7 | fixes, security issues, and severe security issues. They are handled as
8 | follows, all versions in `X.Y.Z` format.
9 |
10 | --------------------------------------------------------------------------------
11 |
12 | Rails follows a shifted version of [semver](http://semver.org/):
13 |
14 | **Patch `Z`**
15 |
16 | Only bug fixes, no API changes, no new features.
17 | Except as necessary for security fixes.
18 |
19 | **Minor `Y`**
20 |
21 | New features, may contain API changes (Serve as major versions of Semver).
22 | Breaking changes are paired with deprecation notices in the previous minor
23 | or major release.
24 |
25 | **Major `X`**
26 |
27 | New features, will likely contain API changes. The difference between Rails'
28 | minor and major releases is the magnitude of breaking changes, and usually
29 | reserved for special occasions.
30 |
31 | New Features
32 | ------------
33 |
34 | New features are only added to the master branch and will not be made available
35 | in point releases.
36 |
37 | Bug Fixes
38 | ---------
39 |
40 | Only the latest release series will receive bug fixes. When enough bugs are
41 | fixed and its deemed worthy to release a new gem, this is the branch it happens
42 | from.
43 |
44 | In special situations, where someone from the Core Team agrees to support more series,
45 | they are included in the list of supported series.
46 |
47 | **Currently included series:** `5.2.Z`.
48 |
49 | Security Issues
50 | ---------------
51 |
52 | The current release series and the next most recent one will receive patches
53 | and new versions in case of a security issue.
54 |
55 | These releases are created by taking the last released version, applying the
56 | security patches, and releasing. Those patches are then applied to the end of
57 | the x-y-stable branch. For example, a theoretical 1.2.3 security release would
58 | be built from 1.2.2, and then added to the end of 1-2-stable. This means that
59 | security releases are easy to upgrade to if you're running the latest version
60 | of Rails.
61 |
62 | **Currently included series:** `5.2.Z`, `5.1.Z`.
63 |
64 | Severe Security Issues
65 | ----------------------
66 |
67 | For severe security issues all releases in the current major series, and also the
68 | last major release series will receive patches and new versions. The
69 | classification of the security issue is judged by the core team.
70 |
71 | **Currently included series:** `5.2.Z`, `5.1.Z`, `5.0.Z`, `4.2.Z`.
72 |
73 | Unsupported Release Series
74 | --------------------------
75 |
76 | When a release series is no longer supported, it's your own responsibility to
77 | deal with bugs and security issues. We may provide backports of the fixes and
78 | publish them to git, however there will be no new versions released. If you are
79 | not comfortable maintaining your own versions, you should upgrade to a
80 | supported version.
81 |
--------------------------------------------------------------------------------
/docs/rails/rails_application_templates.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: application-templates
3 | title: Rails Application Templates
4 | ---
5 |
6 | Application templates are simple Ruby files containing DSL for adding gems/initializers etc. to your freshly created Rails project or an existing Rails project.
7 |
8 | After reading this guide, you will know:
9 |
10 | * How to use templates to generate/customize Rails applications.
11 | * How to write your own reusable application templates using the Rails template API.
12 |
13 | --------------------------------------------------------------------------------
14 |
15 | Usage
16 | -----
17 |
18 | To apply a template, you need to provide the Rails generator with the location of the template you wish to apply using the `-m` option. This can either be a path to a file or a URL.
19 |
20 | ```bash
21 | $ rails new blog -m ~/template.rb
22 | $ rails new blog -m http://example.com/template.rb
23 | ```
24 |
25 | You can use the `app:template` rails command to apply templates to an existing Rails application. The location of the template needs to be passed in via the LOCATION environment variable. Again, this can either be path to a file or a URL.
26 |
27 | ```bash
28 | $ rails app:template LOCATION=~/template.rb
29 | $ rails app:template LOCATION=http://example.com/template.rb
30 | ```
31 |
32 | Template API
33 | ------------
34 |
35 | The Rails templates API is easy to understand. Here's an example of a typical Rails template:
36 |
37 | ```ruby
38 | # template.rb
39 | generate(:scaffold, "person name:string")
40 | route "root to: 'people#index'"
41 | rails_command("db:migrate")
42 |
43 | after_bundle do
44 | git :init
45 | git add: "."
46 | git commit: %Q{ -m 'Initial commit' }
47 | end
48 | ```
49 |
50 | The following sections outline the primary methods provided by the API:
51 |
52 | ### gem(*args)
53 |
54 | Adds a `gem` entry for the supplied gem to the generated application's `Gemfile`.
55 |
56 | For example, if your application depends on the gems `bj` and `nokogiri`:
57 |
58 | ```ruby
59 | gem "bj"
60 | gem "nokogiri"
61 | ```
62 |
63 | Please note that this will NOT install the gems for you and you will have to run `bundle install` to do that.
64 |
65 | ```bash
66 | bundle install
67 | ```
68 |
69 | ### gem_group(*names, &block)
70 |
71 | Wraps gem entries inside a group.
72 |
73 | For example, if you want to load `rspec-rails` only in the `development` and `test` groups:
74 |
75 | ```ruby
76 | gem_group :development, :test do
77 | gem "rspec-rails"
78 | end
79 | ```
80 |
81 | ### add_source(source, options={}, &block)
82 |
83 | Adds the given source to the generated application's `Gemfile`.
84 |
85 | For example, if you need to source a gem from `"http://code.whytheluckystiff.net"`:
86 |
87 | ```ruby
88 | add_source "http://code.whytheluckystiff.net"
89 | ```
90 |
91 | If block is given, gem entries in block are wrapped into the source group.
92 |
93 | ```ruby
94 | add_source "http://gems.github.com/" do
95 | gem "rspec-rails"
96 | end
97 | ```
98 |
99 | ### environment/application(data=nil, options={}, &block)
100 |
101 | Adds a line inside the `Application` class for `config/application.rb`.
102 |
103 | If `options[:env]` is specified, the line is appended to the corresponding file in `config/environments`.
104 |
105 | ```ruby
106 | environment 'config.action_mailer.default_url_options = {host: "http://yourwebsite.example.com"}', env: 'production'
107 | ```
108 |
109 | A block can be used in place of the `data` argument.
110 |
111 | ### vendor/lib/file/initializer(filename, data = nil, &block)
112 |
113 | Adds an initializer to the generated application's `config/initializers` directory.
114 |
115 | Let's say you like using `Object#not_nil?` and `Object#not_blank?`:
116 |
117 | ```ruby
118 | initializer 'bloatlol.rb', <<-CODE
119 | class Object
120 | def not_nil?
121 | !nil?
122 | end
123 |
124 | def not_blank?
125 | !blank?
126 | end
127 | end
128 | CODE
129 | ```
130 |
131 | Similarly, `lib()` creates a file in the `lib/` directory and `vendor()` creates a file in the `vendor/` directory.
132 |
133 | There is even `file()`, which accepts a relative path from `Rails.root` and creates all the directories/files needed:
134 |
135 | ```ruby
136 | file 'app/components/foo.rb', <<-CODE
137 | class Foo
138 | end
139 | CODE
140 | ```
141 |
142 | That'll create the `app/components` directory and put `foo.rb` in there.
143 |
144 | ### rakefile(filename, data = nil, &block)
145 |
146 | Creates a new rake file under `lib/tasks` with the supplied tasks:
147 |
148 | ```ruby
149 | rakefile("bootstrap.rake") do
150 | <<-TASK
151 | namespace :boot do
152 | task :strap do
153 | puts "i like boots!"
154 | end
155 | end
156 | TASK
157 | end
158 | ```
159 |
160 | The above creates `lib/tasks/bootstrap.rake` with a `boot:strap` rake task.
161 |
162 | ### generate(what, *args)
163 |
164 | Runs the supplied rails generator with given arguments.
165 |
166 | ```ruby
167 | generate(:scaffold, "person", "name:string", "address:text", "age:number")
168 | ```
169 |
170 | ### run(command)
171 |
172 | Executes an arbitrary command. Just like the backticks. Let's say you want to remove the `README.rdoc` file:
173 |
174 | ```ruby
175 | run "rm README.rdoc"
176 | ```
177 |
178 | ### rails_command(command, options = {})
179 |
180 | Runs the supplied command in the Rails application. Let's say you want to migrate the database:
181 |
182 | ```ruby
183 | rails_command "db:migrate"
184 | ```
185 |
186 | You can also run commands with a different Rails environment:
187 |
188 | ```ruby
189 | rails_command "db:migrate", env: 'production'
190 | ```
191 |
192 | You can also run commands as a super-user:
193 |
194 | ```ruby
195 | rails_command "log:clear", sudo: true
196 | ```
197 |
198 | You can also run commands that should abort application generation if they fail:
199 |
200 | ```ruby
201 | rails_command "db:migrate", abort_on_failure: true
202 | ```
203 |
204 | ### route(routing_code)
205 |
206 | Adds a routing entry to the `config/routes.rb` file. In the steps above, we generated a person scaffold and also removed `README.rdoc`. Now, to make `PeopleController#index` the default page for the application:
207 |
208 | ```ruby
209 | route "root to: 'person#index'"
210 | ```
211 |
212 | ### inside(dir)
213 |
214 | Enables you to run a command from the given directory. For example, if you have a copy of edge rails that you wish to symlink from your new apps, you can do this:
215 |
216 | ```ruby
217 | inside('vendor') do
218 | run "ln -s ~/commit-rails/rails rails"
219 | end
220 | ```
221 |
222 | ### ask(question)
223 |
224 | `ask()` gives you a chance to get some feedback from the user and use it in your templates. Let's say you want your user to name the new shiny library you're adding:
225 |
226 | ```ruby
227 | lib_name = ask("What do you want to call the shiny library ?")
228 | lib_name << ".rb" unless lib_name.index(".rb")
229 |
230 | lib lib_name, <<-CODE
231 | class Shiny
232 | end
233 | CODE
234 | ```
235 |
236 | ### yes?(question) or no?(question)
237 |
238 | These methods let you ask questions from templates and decide the flow based on the user's answer. Let's say you want to Freeze Rails only if the user wants to:
239 |
240 | ```ruby
241 | rails_command("rails:freeze:gems") if yes?("Freeze rails gems?")
242 | # no?(question) acts just the opposite.
243 | ```
244 |
245 | ### git(:command)
246 |
247 | Rails templates let you run any git command:
248 |
249 | ```ruby
250 | git :init
251 | git add: "."
252 | git commit: "-a -m 'Initial commit'"
253 | ```
254 |
255 | ### after_bundle(&block)
256 |
257 | Registers a callback to be executed after the gems are bundled and binstubs
258 | are generated. Useful for all generated files to version control:
259 |
260 | ```ruby
261 | after_bundle do
262 | git :init
263 | git add: '.'
264 | git commit: "-a -m 'Initial commit'"
265 | end
266 | ```
267 |
268 | The callbacks gets executed even if `--skip-bundle` and/or `--skip-spring` has
269 | been passed.
270 |
271 | Advanced Usage
272 | --------------
273 |
274 | The application template is evaluated in the context of a
275 | `Rails::Generators::AppGenerator` instance. It uses the `apply` action
276 | provided by
277 | [Thor](https://github.com/erikhuda/thor/blob/master/lib/thor/actions.rb#L207).
278 | This means you can extend and change the instance to match your needs.
279 |
280 | For example by overwriting the `source_paths` method to contain the
281 | location of your template. Now methods like `copy_file` will accept
282 | relative paths to your template's location.
283 |
284 | ```ruby
285 | def source_paths
286 | [__dir__]
287 | end
288 | ```
289 |
--------------------------------------------------------------------------------
/docs/rails/rails_on_rack.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: rails-on-rack
3 | title: Rails on Rack
4 | ---
5 |
6 | This guide covers Rails integration with Rack and interfacing with other Rack components.
7 |
8 | After reading this guide, you will know:
9 |
10 | * How to use Rack Middlewares in your Rails applications.
11 | * Action Pack's internal Middleware stack.
12 | * How to define a custom Middleware stack.
13 |
14 | --------------------------------------------------------------------------------
15 |
16 | WARNING: This guide assumes a working knowledge of Rack protocol and Rack concepts such as middlewares, URL maps, and `Rack::Builder`.
17 |
18 | Introduction to Rack
19 | --------------------
20 |
21 | Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.
22 |
23 | Explaining how Rack works is not really in the scope of this guide. In case you
24 | are not familiar with Rack's basics, you should check out the [Resources](#resources)
25 | section below.
26 |
27 | Rails on Rack
28 | -------------
29 |
30 | ### Rails Application's Rack Object
31 |
32 | `Rails.application` is the primary Rack application object of a Rails
33 | application. Any Rack compliant web server should be using
34 | `Rails.application` object to serve a Rails application.
35 |
36 | ### `rails server`
37 |
38 | `rails server` does the basic job of creating a `Rack::Server` object and starting the web server.
39 |
40 | Here's how `rails server` creates an instance of `Rack::Server`
41 |
42 | ```ruby
43 | Rails::Server.new.tap do |server|
44 | require APP_PATH
45 | Dir.chdir(Rails.application.root)
46 | server.start
47 | end
48 | ```
49 |
50 | The `Rails::Server` inherits from `Rack::Server` and calls the `Rack::Server#start` method this way:
51 |
52 | ```ruby
53 | class Server < ::Rack::Server
54 | def start
55 | ...
56 | super
57 | end
58 | end
59 | ```
60 |
61 | ### `rackup`
62 |
63 | To use `rackup` instead of Rails' `rails server`, you can put the following inside `config.ru` of your Rails application's root directory:
64 |
65 | ```ruby
66 | # Rails.root/config.ru
67 | require_relative 'config/environment'
68 | run Rails.application
69 | ```
70 |
71 | And start the server:
72 |
73 | ```bash
74 | $ rackup config.ru
75 | ```
76 |
77 | To find out more about different `rackup` options, you can run:
78 |
79 | ```bash
80 | $ rackup --help
81 | ```
82 |
83 | ### Development and auto-reloading
84 |
85 | Middlewares are loaded once and are not monitored for changes. You will have to restart the server for changes to be reflected in the running application.
86 |
87 | Action Dispatcher Middleware Stack
88 | ----------------------------------
89 |
90 | Many of Action Dispatcher's internal components are implemented as Rack middlewares. `Rails::Application` uses `ActionDispatch::MiddlewareStack` to combine various internal and external middlewares to form a complete Rails Rack application.
91 |
92 | NOTE: `ActionDispatch::MiddlewareStack` is Rails' equivalent of `Rack::Builder`,
93 | but is built for better flexibility and more features to meet Rails' requirements.
94 |
95 | ### Inspecting Middleware Stack
96 |
97 | Rails has a handy command for inspecting the middleware stack in use:
98 |
99 | ```bash
100 | $ rails middleware
101 | ```
102 |
103 | For a freshly generated Rails application, this might produce something like:
104 |
105 | ```ruby
106 | use Rack::Sendfile
107 | use ActionDispatch::Static
108 | use ActionDispatch::Executor
109 | use ActiveSupport::Cache::Strategy::LocalCache::Middleware
110 | use Rack::Runtime
111 | use Rack::MethodOverride
112 | use ActionDispatch::RequestId
113 | use ActionDispatch::RemoteIp
114 | use Sprockets::Rails::QuietAssets
115 | use Rails::Rack::Logger
116 | use ActionDispatch::ShowExceptions
117 | use WebConsole::Middleware
118 | use ActionDispatch::DebugExceptions
119 | use ActionDispatch::Reloader
120 | use ActionDispatch::Callbacks
121 | use ActiveRecord::Migration::CheckPending
122 | use ActionDispatch::Cookies
123 | use ActionDispatch::Session::CookieStore
124 | use ActionDispatch::Flash
125 | use ActionDispatch::ContentSecurityPolicy::Middleware
126 | use Rack::Head
127 | use Rack::ConditionalGet
128 | use Rack::ETag
129 | use Rack::TempfileReaper
130 | run MyApp::Application.routes
131 | ```
132 |
133 | The default middlewares shown here (and some others) are each summarized in the [Internal Middlewares](#internal-middleware-stack) section, below.
134 |
135 | ### Configuring Middleware Stack
136 |
137 | Rails provides a simple configuration interface `config.middleware` for adding, removing, and modifying the middlewares in the middleware stack via `application.rb` or the environment specific configuration file `environments/.rb`.
138 |
139 | #### Adding a Middleware
140 |
141 | You can add a new middleware to the middleware stack using any of the following methods:
142 |
143 | * `config.middleware.use(new_middleware, args)` - Adds the new middleware at the bottom of the middleware stack.
144 |
145 | * `config.middleware.insert_before(existing_middleware, new_middleware, args)` - Adds the new middleware before the specified existing middleware in the middleware stack.
146 |
147 | * `config.middleware.insert_after(existing_middleware, new_middleware, args)` - Adds the new middleware after the specified existing middleware in the middleware stack.
148 |
149 | ```ruby
150 | # config/application.rb
151 |
152 | # Push Rack::BounceFavicon at the bottom
153 | config.middleware.use Rack::BounceFavicon
154 |
155 | # Add Lifo::Cache after ActionDispatch::Executor.
156 | # Pass { page_cache: false } argument to Lifo::Cache.
157 | config.middleware.insert_after ActionDispatch::Executor, Lifo::Cache, page_cache: false
158 | ```
159 |
160 | #### Swapping a Middleware
161 |
162 | You can swap an existing middleware in the middleware stack using `config.middleware.swap`.
163 |
164 | ```ruby
165 | # config/application.rb
166 |
167 | # Replace ActionDispatch::ShowExceptions with Lifo::ShowExceptions
168 | config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions
169 | ```
170 |
171 | #### Deleting a Middleware
172 |
173 | Add the following lines to your application configuration:
174 |
175 | ```ruby
176 | # config/application.rb
177 | config.middleware.delete Rack::Runtime
178 | ```
179 |
180 | And now if you inspect the middleware stack, you'll find that `Rack::Runtime` is
181 | not a part of it.
182 |
183 | ```bash
184 | $ rails middleware
185 | (in /Users/lifo/Rails/blog)
186 | use ActionDispatch::Static
187 | use #
188 | ...
189 | run Rails.application.routes
190 | ```
191 |
192 | If you want to remove session related middleware, do the following:
193 |
194 | ```ruby
195 | # config/application.rb
196 | config.middleware.delete ActionDispatch::Cookies
197 | config.middleware.delete ActionDispatch::Session::CookieStore
198 | config.middleware.delete ActionDispatch::Flash
199 | ```
200 |
201 | And to remove browser related middleware,
202 |
203 | ```ruby
204 | # config/application.rb
205 | config.middleware.delete Rack::MethodOverride
206 | ```
207 |
208 | ### Internal Middleware Stack
209 |
210 | Much of Action Controller's functionality is implemented as Middlewares. The following list explains the purpose of each of them:
211 |
212 | **`Rack::Sendfile`**
213 |
214 | * Sets server specific X-Sendfile header. Configure this via `config.action_dispatch.x_sendfile_header` option.
215 |
216 | **`ActionDispatch::Static`**
217 |
218 | * Used to serve static files from the public directory. Disabled if `config.public_file_server.enabled` is `false`.
219 |
220 | **`Rack::Lock`**
221 |
222 | * Sets `env["rack.multithread"]` flag to `false` and wraps the application within a Mutex.
223 |
224 | **`ActionDispatch::Executor`**
225 |
226 | * Used for thread safe code reloading during development.
227 |
228 | **`ActiveSupport::Cache::Strategy::LocalCache::Middleware`**
229 |
230 | * Used for memory caching. This cache is not thread safe.
231 |
232 | **`Rack::Runtime`**
233 |
234 | * Sets an X-Runtime header, containing the time (in seconds) taken to execute the request.
235 |
236 | **`Rack::MethodOverride`**
237 |
238 | * Allows the method to be overridden if `params[:_method]` is set. This is the middleware which supports the PUT and DELETE HTTP method types.
239 |
240 | **`ActionDispatch::RequestId`**
241 |
242 | * Makes a unique `X-Request-Id` header available to the response and enables the `ActionDispatch::Request#request_id` method.
243 |
244 | **`ActionDispatch::RemoteIp`**
245 |
246 | * Checks for IP spoofing attacks.
247 |
248 | **`Sprockets::Rails::QuietAssets`**
249 |
250 | * Suppresses logger output for asset requests.
251 |
252 | **`Rails::Rack::Logger`**
253 |
254 | * Notifies the logs that the request has begun. After the request is complete, flushes all the logs.
255 |
256 | **`ActionDispatch::ShowExceptions`**
257 |
258 | * Rescues any exception returned by the application and calls an exceptions app that will wrap it in a format for the end user.
259 |
260 | **`ActionDispatch::DebugExceptions`**
261 |
262 | * Responsible for logging exceptions and showing a debugging page in case the request is local.
263 |
264 | **`ActionDispatch::Reloader`**
265 |
266 | * Provides prepare and cleanup callbacks, intended to assist with code reloading during development.
267 |
268 | **`ActionDispatch::Callbacks`**
269 |
270 | * Provides callbacks to be executed before and after dispatching the request.
271 |
272 | **`ActiveRecord::Migration::CheckPending`**
273 |
274 | * Checks pending migrations and raises `ActiveRecord::PendingMigrationError` if any migrations are pending.
275 |
276 | **`ActionDispatch::Cookies`**
277 |
278 | * Sets cookies for the request.
279 |
280 | **`ActionDispatch::Session::CookieStore`**
281 |
282 | * Responsible for storing the session in cookies.
283 |
284 | **`ActionDispatch::Flash`**
285 |
286 | * Sets up the flash keys. Only available if `config.action_controller.session_store` is set to a value.
287 |
288 | **`ActionDispatch::ContentSecurityPolicy::Middleware`**
289 |
290 | * Provides a DSL to configure a Content-Security-Policy header.
291 |
292 | **`Rack::Head`**
293 |
294 | * Converts HEAD requests to `GET` requests and serves them as so.
295 |
296 | **`Rack::ConditionalGet`**
297 |
298 | * Adds support for "Conditional `GET`" so that server responds with nothing if the page wasn't changed.
299 |
300 | **`Rack::ETag`**
301 |
302 | * Adds ETag header on all String bodies. ETags are used to validate cache.
303 |
304 | **`Rack::TempfileReaper`**
305 |
306 | * Cleans up tempfiles used to buffer multipart requests.
307 |
308 | TIP: It's possible to use any of the above middlewares in your custom Rack stack.
309 |
310 | Resources
311 | ---------
312 |
313 | ### Learning Rack
314 |
315 | * [Official Rack Website](https://rack.github.io)
316 | * [Introducing Rack](http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html)
317 |
318 | ### Understanding Middlewares
319 |
320 | * [Railscast on Rack Middlewares](http://railscasts.com/episodes/151-rack-middleware)
321 |
--------------------------------------------------------------------------------
/docs/rails/ruby_on_rails_guides_guidelines.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: guides-guidelines
3 | title: Ruby on Rails Guides Guidelines
4 | ---
5 |
6 | This guide documents guidelines for writing Ruby on Rails Guides. This guide follows itself in a graceful loop, serving itself as an example.
7 |
8 | After reading this guide, you will know:
9 |
10 | * About the conventions to be used in Rails documentation.
11 | * How to generate guides locally.
12 |
13 | --------------------------------------------------------------------------------
14 |
15 | Markdown
16 | -------
17 |
18 | Guides are written in [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown). There is comprehensive [documentation for Markdown](http://daringfireball.net/projects/markdown/syntax), as well as a [cheatsheet](http://daringfireball.net/projects/markdown/basics).
19 |
20 | Prologue
21 | --------
22 |
23 | Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. As an example, see the [Routing Guide](routing.md).
24 |
25 | Headings
26 | ------
27 |
28 | The title of every guide uses an `h1` heading; guide sections use `h2` headings; subsections use `h3` headings; etc. Note that the generated HTML output will use heading tags starting with `
`.
29 |
30 | ```
31 | Guide Title
32 | ===========
33 |
34 | Section
35 | -------
36 |
37 | ### Sub Section
38 | ```
39 |
40 | When writing headings, capitalize all words except for prepositions, conjunctions, internal articles, and forms of the verb "to be":
41 |
42 | ```
43 | #### Middleware Stack is an Array
44 | #### When are Objects Saved?
45 | ```
46 |
47 | Use the same inline formatting as regular text:
48 |
49 | ```
50 | ##### The `:content_type` Option
51 | ```
52 |
53 | Linking to the API
54 | ------------------
55 |
56 | Links to the API (`api.rubyonrails.org`) are processed by the guides generator in the following manner:
57 |
58 | Links that include a release tag are left untouched. For example
59 |
60 | ```
61 | https://api.rubyonrails.org/v5.0.1/classes/ActiveRecord/Attributes/ClassMethods.html
62 | ```
63 |
64 | is not modified.
65 |
66 | Please use these in release notes, since they should point to the corresponding version no matter the target being generated.
67 |
68 | If the link does not include a release tag and edge guides are being generated, the domain is replaced by `edgeapi.rubyonrails.org`. For example,
69 |
70 | ```
71 | https://api.rubyonrails.org/classes/ActionDispatch/Response.html
72 | ```
73 |
74 | becomes
75 |
76 | ```
77 | https://edgeapi.rubyonrails.org/classes/ActionDispatch/Response.html
78 | ```
79 |
80 | If the link does not include a release tag and release guides are being generated, the Rails version is injected. For example, if we are generating the guides for v5.1.0 the link
81 |
82 | ```
83 | https://api.rubyonrails.org/classes/ActionDispatch/Response.html
84 | ```
85 |
86 | becomes
87 |
88 | ```
89 | https://api.rubyonrails.org/v5.1.0/classes/ActionDispatch/Response.html
90 | ```
91 |
92 | Please don't link to `edgeapi.rubyonrails.org` manually.
93 |
94 |
95 | API Documentation Guidelines
96 | ----------------------------
97 |
98 | The guides and the API should be coherent and consistent where appropriate. In particular, these sections of the [API Documentation Guidelines](api_documentation_guidelines.md) also apply to the guides:
99 |
100 | * [Wording](api_documentation_guidelines.md#wording)
101 | * [English](api_documentation_guidelines.md#english)
102 | * [Example Code](api_documentation_guidelines.md#example-code)
103 | * [Filenames](api_documentation_guidelines.md#file-names)
104 | * [Fonts](api_documentation_guidelines.md#fonts)
105 |
106 | HTML Guides
107 | -----------
108 |
109 | Before generating the guides, make sure that you have the latest version of
110 | Bundler installed on your system. You can find the latest Bundler version
111 | [here](https://rubygems.org/gems/bundler). As of this writing, it's v1.17.1.
112 |
113 | To install the latest version of Bundler, run `gem install bundler`.
114 |
115 | ### Generation
116 |
117 | To generate all the guides, just `cd` into the `guides` directory, run `bundle install`, and execute:
118 |
119 | ```
120 | bundle exec rake guides:generate
121 | ```
122 |
123 | or
124 |
125 | ```
126 | bundle exec rake guides:generate:html
127 | ```
128 |
129 | Resulting HTML files can be found in the `./output` directory.
130 |
131 | To process `my_guide.md` and nothing else use the `ONLY` environment variable:
132 |
133 | ```
134 | touch my_guide.md
135 | bundle exec rake guides:generate ONLY=my_guide
136 | ```
137 |
138 | By default, guides that have not been modified are not processed, so `ONLY` is rarely needed in practice.
139 |
140 | To force processing all the guides, pass `ALL=1`.
141 |
142 | If you want to generate guides in a language other than English, you can keep them in a separate directory under `source` (eg. `source/es`) and use the `GUIDES_LANGUAGE` environment variable:
143 |
144 | ```
145 | bundle exec rake guides:generate GUIDES_LANGUAGE=es
146 | ```
147 |
148 | If you want to see all the environment variables you can use to configure the generation script just run:
149 |
150 | ```
151 | rake
152 | ```
153 |
154 | ### Validation
155 |
156 | Please validate the generated HTML with:
157 |
158 | ```
159 | bundle exec rake guides:validate
160 | ```
161 |
162 | Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set `WARNINGS=1` when generating guides to detect them. The warning messages suggest a solution.
163 |
164 | Kindle Guides
165 | -------------
166 |
167 | ### Generation
168 |
169 | To generate guides for the Kindle, use the following rake task:
170 |
171 | ```
172 | bundle exec rake guides:generate:kindle
173 | ```
174 |
--------------------------------------------------------------------------------
/docs/rails/threading_and_code_execution.md:
--------------------------------------------------------------------------------
1 | ---
2 | id: threading
3 | title: Threading and Code Execution in Rails
4 | ---
5 |
6 | After reading this guide, you will know:
7 |
8 | * What code Rails will automatically execute concurrently
9 | * How to integrate manual concurrency with Rails internals
10 | * How to wrap all application code
11 | * How to affect application reloading
12 |
13 | --------------------------------------------------------------------------------
14 |
15 | Automatic Concurrency
16 | ---------------------
17 |
18 | Rails automatically allows various operations to be performed at the same time.
19 |
20 | When using a threaded web server, such as the default Puma, multiple HTTP
21 | requests will be served simultaneously, with each request provided its own
22 | controller instance.
23 |
24 | Threaded Active Job adapters, including the built-in Async, will likewise
25 | execute several jobs at the same time. Action Cable channels are managed this
26 | way too.
27 |
28 | These mechanisms all involve multiple threads, each managing work for a unique
29 | instance of some object (controller, job, channel), while sharing the global
30 | process space (such as classes and their configurations, and global variables).
31 | As long as your code doesn't modify any of those shared things, it can mostly
32 | ignore that other threads exist.
33 |
34 | The rest of this guide describes the mechanisms Rails uses to make it "mostly
35 | ignorable", and how extensions and applications with special needs can use them.
36 |
37 | Executor
38 | --------
39 |
40 | The Rails Executor separates application code from framework code: any time the
41 | framework invokes code you've written in your application, it will be wrapped by
42 | the Executor.
43 |
44 | The Executor consists of two callbacks: `to_run` and `to_complete`. The Run
45 | callback is called before the application code, and the Complete callback is
46 | called after.
47 |
48 | ### Default callbacks
49 |
50 | In a default Rails application, the Executor callbacks are used to:
51 |
52 | * track which threads are in safe positions for autoloading and reloading
53 | * enable and disable the Active Record query cache
54 | * return acquired Active Record connections to the pool
55 | * constrain internal cache lifetimes
56 |
57 | Prior to Rails 5.0, some of these were handled by separate Rack middleware
58 | classes (such as `ActiveRecord::ConnectionAdapters::ConnectionManagement`), or
59 | directly wrapping code with methods like
60 | `ActiveRecord::Base.connection_pool.with_connection`. The Executor replaces
61 | these with a single more abstract interface.
62 |
63 | ### Wrapping application code
64 |
65 | If you're writing a library or component that will invoke application code, you
66 | should wrap it with a call to the executor:
67 |
68 | ```ruby
69 | Rails.application.executor.wrap do
70 | # call application code here
71 | end
72 | ```
73 |
74 | TIP: If you repeatedly invoke application code from a long-running process, you
75 | may want to wrap using the Reloader instead.
76 |
77 | Each thread should be wrapped before it runs application code, so if your
78 | application manually delegates work to other threads, such as via `Thread.new`
79 | or Concurrent Ruby features that use thread pools, you should immediately wrap
80 | the block:
81 |
82 | ```ruby
83 | Thread.new do
84 | Rails.application.executor.wrap do
85 | # your code here
86 | end
87 | end
88 | ```
89 |
90 | NOTE: Concurrent Ruby uses a `ThreadPoolExecutor`, which it sometimes configures
91 | with an `executor` option. Despite the name, it is unrelated.
92 |
93 | The Executor is safely re-entrant; if it is already active on the current
94 | thread, `wrap` is a no-op.
95 |
96 | If it's impractical to wrap the application code in a block (for
97 | example, the Rack API makes this problematic), you can also use the `run!` /
98 | `complete!` pair:
99 |
100 | ```ruby
101 | Thread.new do
102 | execution_context = Rails.application.executor.run!
103 | # your code here
104 | ensure
105 | execution_context.complete! if execution_context
106 | end
107 | ```
108 |
109 | ### Concurrency
110 |
111 | The Executor will put the current thread into `running` mode in the Load
112 | Interlock. This operation will block temporarily if another thread is currently
113 | either autoloading a constant or unloading/reloading the application.
114 |
115 | Reloader
116 | --------
117 |
118 | Like the Executor, the Reloader also wraps application code. If the Executor is
119 | not already active on the current thread, the Reloader will invoke it for you,
120 | so you only need to call one. This also guarantees that everything the Reloader
121 | does, including all its callback invocations, occurs wrapped inside the
122 | Executor.
123 |
124 | ```ruby
125 | Rails.application.reloader.wrap do
126 | # call application code here
127 | end
128 | ```
129 |
130 | The Reloader is only suitable where a long-running framework-level process
131 | repeatedly calls into application code, such as for a web server or job queue.
132 | Rails automatically wraps web requests and Active Job workers, so you'll rarely
133 | need to invoke the Reloader for yourself. Always consider whether the Executor
134 | is a better fit for your use case.
135 |
136 | ### Callbacks
137 |
138 | Before entering the wrapped block, the Reloader will check whether the running
139 | application needs to be reloaded -- for example, because a model's source file has
140 | been modified. If it determines a reload is required, it will wait until it's
141 | safe, and then do so, before continuing. When the application is configured to
142 | always reload regardless of whether any changes are detected, the reload is
143 | instead performed at the end of the block.
144 |
145 | The Reloader also provides `to_run` and `to_complete` callbacks; they are
146 | invoked at the same points as those of the Executor, but only when the current
147 | execution has initiated an application reload. When no reload is deemed
148 | necessary, the Reloader will invoke the wrapped block with no other callbacks.
149 |
150 | ### Class Unload
151 |
152 | The most significant part of the reloading process is the Class Unload, where
153 | all autoloaded classes are removed, ready to be loaded again. This will occur
154 | immediately before either the Run or Complete callback, depending on the
155 | `reload_classes_only_on_change` setting.
156 |
157 | Often, additional reloading actions need to be performed either just before or
158 | just after the Class Unload, so the Reloader also provides `before_class_unload`
159 | and `after_class_unload` callbacks.
160 |
161 | ### Concurrency
162 |
163 | Only long-running "top level" processes should invoke the Reloader, because if
164 | it determines a reload is needed, it will block until all other threads have
165 | completed any Executor invocations.
166 |
167 | If this were to occur in a "child" thread, with a waiting parent inside the
168 | Executor, it would cause an unavoidable deadlock: the reload must occur before
169 | the child thread is executed, but it cannot be safely performed while the parent
170 | thread is mid-execution. Child threads should use the Executor instead.
171 |
172 | Framework Behavior
173 | ------------------
174 |
175 | The Rails framework components use these tools to manage their own concurrency
176 | needs too.
177 |
178 | `ActionDispatch::Executor` and `ActionDispatch::Reloader` are Rack middlewares
179 | that wraps the request with a supplied Executor or Reloader, respectively. They
180 | are automatically included in the default application stack. The Reloader will
181 | ensure any arriving HTTP request is served with a freshly-loaded copy of the
182 | application if any code changes have occurred.
183 |
184 | Active Job also wraps its job executions with the Reloader, loading the latest
185 | code to execute each job as it comes off the queue.
186 |
187 | Action Cable uses the Executor instead: because a Cable connection is linked to
188 | a specific instance of a class, it's not possible to reload for every arriving
189 | websocket message. Only the message handler is wrapped, though; a long-running
190 | Cable connection does not prevent a reload that's triggered by a new incoming
191 | request or job. Instead, Action Cable uses the Reloader's `before_class_unload`
192 | callback to disconnect all its connections. When the client automatically
193 | reconnects, it will be speaking to the new version of the code.
194 |
195 | The above are the entry points to the framework, so they are responsible for
196 | ensuring their respective threads are protected, and deciding whether a reload
197 | is necessary. Other components only need to use the Executor when they spawn
198 | additional threads.
199 |
200 | ### Configuration
201 |
202 | The Reloader only checks for file changes when `cache_classes` is false and
203 | `reload_classes_only_on_change` is true (which is the default in the
204 | `development` environment).
205 |
206 | When `cache_classes` is true (in `production`, by default), the Reloader is only
207 | a pass-through to the Executor.
208 |
209 | The Executor always has important work to do, like database connection
210 | management. When `cache_classes` and `eager_load` are both true (`production`),
211 | no autoloading or class reloading will occur, so it does not need the Load
212 | Interlock. If either of those are false (`development`), then the Executor will
213 | use the Load Interlock to ensure constants are only loaded when it is safe.
214 |
215 | Load Interlock
216 | --------------
217 |
218 | The Load Interlock allows autoloading and reloading to be enabled in a
219 | multi-threaded runtime environment.
220 |
221 | When one thread is performing an autoload by evaluating the class definition
222 | from the appropriate file, it is important no other thread encounters a
223 | reference to the partially-defined constant.
224 |
225 | Similarly, it is only safe to perform an unload/reload when no application code
226 | is in mid-execution: after the reload, the `User` constant, for example, may
227 | point to a different class. Without this rule, a poorly-timed reload would mean
228 | `User.new.class == User`, or even `User == User`, could be false.
229 |
230 | Both of these constraints are addressed by the Load Interlock. It keeps track of
231 | which threads are currently running application code, loading a class, or
232 | unloading autoloaded constants.
233 |
234 | Only one thread may load or unload at a time, and to do either, it must wait
235 | until no other threads are running application code. If a thread is waiting to
236 | perform a load, it doesn't prevent other threads from loading (in fact, they'll
237 | cooperate, and each perform their queued load in turn, before all resuming
238 | running together).
239 |
240 | ### `permit_concurrent_loads`
241 |
242 | The Executor automatically acquires a `running` lock for the duration of its
243 | block, and autoload knows when to upgrade to a `load` lock, and switch back to
244 | `running` again afterwards.
245 |
246 | Other blocking operations performed inside the Executor block (which includes
247 | all application code), however, can needlessly retain the `running` lock. If
248 | another thread encounters a constant it must autoload, this can cause a
249 | deadlock.
250 |
251 | For example, assuming `User` is not yet loaded, the following will deadlock:
252 |
253 | ```ruby
254 | Rails.application.executor.wrap do
255 | th = Thread.new do
256 | Rails.application.executor.wrap do
257 | User # inner thread waits here; it cannot load
258 | # User while another thread is running
259 | end
260 | end
261 |
262 | th.join # outer thread waits here, holding 'running' lock
263 | end
264 | ```
265 |
266 | To prevent this deadlock, the outer thread can `permit_concurrent_loads`. By
267 | calling this method, the thread guarantees it will not dereference any
268 | possibly-autoloaded constant inside the supplied block. The safest way to meet
269 | that promise is to put it as close as possible to the blocking call:
270 |
271 | ```ruby
272 | Rails.application.executor.wrap do
273 | th = Thread.new do
274 | Rails.application.executor.wrap do
275 | User # inner thread can acquire the 'load' lock,
276 | # load User, and continue
277 | end
278 | end
279 |
280 | ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
281 | th.join # outer thread waits here, but has no lock
282 | end
283 | end
284 | ```
285 |
286 | Another example, using Concurrent Ruby:
287 |
288 | ```ruby
289 | Rails.application.executor.wrap do
290 | futures = 3.times.collect do |i|
291 | Concurrent::Future.execute do
292 | Rails.application.executor.wrap do
293 | # do work here
294 | end
295 | end
296 | end
297 |
298 | values = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
299 | futures.collect(&:value)
300 | end
301 | end
302 | ```
303 |
304 |
305 | ### ActionDispatch::DebugLocks
306 |
307 | If your application is deadlocking and you think the Load Interlock may be
308 | involved, you can temporarily add the ActionDispatch::DebugLocks middleware to
309 | `config/application.rb`:
310 |
311 | ```ruby
312 | config.middleware.insert_before Rack::Sendfile,
313 | ActionDispatch::DebugLocks
314 | ```
315 |
316 | If you then restart the application and re-trigger the deadlock condition,
317 | `/rails/locks` will show a summary of all threads currently known to the
318 | interlock, which lock level they are holding or awaiting, and their current
319 | backtrace.
320 |
321 | Generally a deadlock will be caused by the interlock conflicting with some other
322 | external lock or blocking I/O call. Once you find it, you can wrap it with
323 | `permit_concurrent_loads`.
324 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rails-setup",
3 | "version": "0.0.1",
4 | "description": "this is a Project to collect in one place and in a friendly way the documentation for rails and commonly used related libraries",
5 | "main": "index.js",
6 | "directories": {
7 | "doc": "docs"
8 | },
9 | "dependencies": {},
10 | "devDependencies": {
11 | "all-contributors-cli": "^6.7.0"
12 | },
13 | "scripts": {
14 | "test": "echo \"Error: no test specified\" && exit 1"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/HenryTabima/rails-setup.git"
19 | },
20 | "keywords": [
21 | "ruby-on-rails",
22 | "documentation"
23 | ],
24 | "author": "Henry Tabima Giraldo",
25 | "license": "MIT",
26 | "bugs": {
27 | "url": "https://github.com/HenryTabima/rails-setup/issues"
28 | },
29 | "homepage": "https://github.com/HenryTabima/rails-setup#readme"
30 | }
31 |
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | This website was created with [Docusaurus](https://docusaurus.io/).
2 |
3 | # What's In This Document
4 |
5 | * [Get Started in 5 Minutes](#get-started-in-5-minutes)
6 | * [Directory Structure](#directory-structure)
7 | * [Editing Content](#editing-content)
8 | * [Adding Content](#adding-content)
9 | * [Full Documentation](#full-documentation)
10 |
11 | # Get Started in 5 Minutes
12 |
13 | 1. Make sure all the dependencies for the website are installed:
14 |
15 | ```sh
16 | # Install dependencies
17 | $ yarn
18 | ```
19 | 2. Run your dev server:
20 |
21 | ```sh
22 | # Start the site
23 | $ yarn start
24 | ```
25 |
26 | ## Directory Structure
27 |
28 | Your project file structure should look something like this
29 |
30 | ```
31 | my-docusaurus/
32 | docs/
33 | doc-1.md
34 | doc-2.md
35 | doc-3.md
36 | website/
37 | blog/
38 | 2016-3-11-oldest-post.md
39 | 2017-10-24-newest-post.md
40 | core/
41 | node_modules/
42 | pages/
43 | static/
44 | css/
45 | img/
46 | package.json
47 | sidebar.json
48 | siteConfig.js
49 | ```
50 |
51 | # Editing Content
52 |
53 | ## Editing an existing docs page
54 |
55 | Edit docs by navigating to `docs/` and editing the corresponding document:
56 |
57 | `docs/doc-to-be-edited.md`
58 |
59 | ```markdown
60 | ---
61 | id: page-needs-edit
62 | title: This Doc Needs To Be Edited
63 | ---
64 |
65 | Edit me...
66 | ```
67 |
68 | For more information about docs, click [here](https://docusaurus.io/docs/en/navigation)
69 |
70 | ## Editing an existing blog post
71 |
72 | Edit blog posts by navigating to `website/blog` and editing the corresponding post:
73 |
74 | `website/blog/post-to-be-edited.md`
75 | ```markdown
76 | ---
77 | id: post-needs-edit
78 | title: This Blog Post Needs To Be Edited
79 | ---
80 |
81 | Edit me...
82 | ```
83 |
84 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)
85 |
86 | # Adding Content
87 |
88 | ## Adding a new docs page to an existing sidebar
89 |
90 | 1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`:
91 |
92 | ```md
93 | ---
94 | id: newly-created-doc
95 | title: This Doc Needs To Be Edited
96 | ---
97 |
98 | My new content here..
99 | ```
100 |
101 | 1. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`:
102 |
103 | ```javascript
104 | // Add newly-created-doc to the Getting Started category of docs
105 | {
106 | "docs": {
107 | "Getting Started": [
108 | "quick-start",
109 | "newly-created-doc" // new doc here
110 | ],
111 | ...
112 | },
113 | ...
114 | }
115 | ```
116 |
117 | For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation)
118 |
119 | ## Adding a new blog post
120 |
121 | 1. Make sure there is a header link to your blog in `website/siteConfig.js`:
122 |
123 | `website/siteConfig.js`
124 | ```javascript
125 | headerLinks: [
126 | ...
127 | { blog: true, label: 'Blog' },
128 | ...
129 | ]
130 | ```
131 |
132 | 2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`:
133 |
134 | `website/blog/2018-05-21-New-Blog-Post.md`
135 |
136 | ```markdown
137 | ---
138 | author: Frank Li
139 | authorURL: https://twitter.com/foobarbaz
140 | authorFBID: 503283835
141 | title: New Blog Post
142 | ---
143 |
144 | Lorem Ipsum...
145 | ```
146 |
147 | For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)
148 |
149 | ## Adding items to your site's top navigation bar
150 |
151 | 1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`:
152 |
153 | `website/siteConfig.js`
154 | ```javascript
155 | {
156 | headerLinks: [
157 | ...
158 | /* you can add docs */
159 | { doc: 'my-examples', label: 'Examples' },
160 | /* you can add custom pages */
161 | { page: 'help', label: 'Help' },
162 | /* you can add external links */
163 | { href: 'https://github.com/facebook/Docusaurus', label: 'GitHub' },
164 | ...
165 | ],
166 | ...
167 | }
168 | ```
169 |
170 | For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation)
171 |
172 | ## Adding custom pages
173 |
174 | 1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`:
175 | 1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element:
176 |
177 | `website/siteConfig.js`
178 | ```javascript
179 | {
180 | headerLinks: [
181 | ...
182 | { page: 'my-new-custom-page', label: 'My New Custom Page' },
183 | ...
184 | ],
185 | ...
186 | }
187 | ```
188 |
189 | For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages).
190 |
191 | # Full Documentation
192 |
193 | Full documentation can be found on the [website](https://docusaurus.io/).
194 |
--------------------------------------------------------------------------------
/website/blog/2016-03-11-blog-post.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog Title
3 | author: Blog Author
4 | authorURL: http://twitter.com/
5 | authorFBID: 100002976521003
6 | ---
7 |
8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien.
9 |
10 |
11 |
12 | Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut.
13 |
14 | Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra.
15 |
16 | Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum.
17 |
18 | Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis.
19 |
--------------------------------------------------------------------------------
/website/blog/2017-04-10-blog-post-two.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: New Blog Post
3 | author: Blog Author
4 | authorURL: http://twitter.com/
5 | authorFBID: 100002976521003
6 | ---
7 |
8 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus elementum massa eget nulla aliquet sagittis. Proin odio tortor, vulputate ut odio in, ultrices ultricies augue. Cras ornare ultrices lorem malesuada iaculis. Etiam sit amet libero tempor, pulvinar mauris sed, sollicitudin sapien.
9 |
10 |
11 |
12 | Mauris vestibulum ullamcorper nibh, ut semper purus pulvinar ut. Donec volutpat orci sit amet mauris malesuada, non pulvinar augue aliquam. Vestibulum ultricies at urna ut suscipit. Morbi iaculis, erat at imperdiet semper, ipsum nulla sodales erat, eget tincidunt justo dui quis justo. Pellentesque dictum bibendum diam at aliquet. Sed pulvinar, dolor quis finibus ornare, eros odio facilisis erat, eu rhoncus nunc dui sed ex. Nunc gravida dui massa, sed ornare arcu tincidunt sit amet. Maecenas efficitur sapien neque, a laoreet libero feugiat ut.
13 |
14 | Nulla facilisi. Maecenas sodales nec purus eget posuere. Sed sapien quam, pretium a risus in, porttitor dapibus erat. Sed sit amet fringilla ipsum, eget iaculis augue. Integer sollicitudin tortor quis ultricies aliquam. Suspendisse fringilla nunc in tellus cursus, at placerat tellus scelerisque. Sed tempus elit a sollicitudin rhoncus. Nulla facilisi. Morbi nec dolor dolor. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras et aliquet lectus. Pellentesque sit amet eros nisi. Quisque ac sapien in sapien congue accumsan. Nullam in posuere ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Proin lacinia leo a nibh fringilla pharetra.
15 |
16 | Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin venenatis lectus dui, vel ultrices ante bibendum hendrerit. Aenean egestas feugiat dui id hendrerit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur in tellus laoreet, eleifend nunc id, viverra leo. Proin vulputate non dolor vel vulputate. Curabitur pretium lobortis felis, sit amet finibus lorem suscipit ut. Sed non mollis risus. Duis sagittis, mi in euismod tincidunt, nunc mauris vestibulum urna, at euismod est elit quis erat. Phasellus accumsan vitae neque eu placerat. In elementum arcu nec tellus imperdiet, eget maximus nulla sodales. Curabitur eu sapien eget nisl sodales fermentum.
17 |
18 | Phasellus pulvinar ex id commodo imperdiet. Praesent odio nibh, sollicitudin sit amet faucibus id, placerat at metus. Donec vitae eros vitae tortor hendrerit finibus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque vitae purus dolor. Duis suscipit ac nulla et finibus. Phasellus ac sem sed dui dictum gravida. Phasellus eleifend vestibulum facilisis. Integer pharetra nec enim vitae mattis. Duis auctor, lectus quis condimentum bibendum, nunc dolor aliquam massa, id bibendum orci velit quis magna. Ut volutpat nulla nunc, sed interdum magna condimentum non. Sed urna metus, scelerisque vitae consectetur a, feugiat quis magna. Donec dignissim ornare nisl, eget tempor risus malesuada quis.
19 |
--------------------------------------------------------------------------------
/website/blog/2017-09-25-testing-rss.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Adding RSS Support - RSS Truncation Test
3 | author: Eric Nakagawa
4 | authorURL: http://twitter.com/ericnakagawa
5 | authorFBID: 661277173
6 | ---
7 | 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
8 |
9 | This should be truncated.
10 |
11 | This line should never render in XML.
12 |
--------------------------------------------------------------------------------
/website/blog/2017-09-26-adding-rss.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Adding RSS Support
3 | author: Eric Nakagawa
4 | authorURL: http://twitter.com/ericnakagawa
5 | authorFBID: 661277173
6 | ---
7 |
8 | This is a test post.
9 |
10 | A whole bunch of other information.
11 |
--------------------------------------------------------------------------------
/website/blog/2017-10-24-new-version-1.0.0.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: New Version 1.0.0
3 | author: Eric Nakagawa
4 | authorURL: http://twitter.com/ericnakagawa
5 | authorFBID: 661277173
6 | ---
7 |
8 | This blog post will test file name parsing issues when periods are present.
9 |
--------------------------------------------------------------------------------
/website/core/Footer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | const React = require('react');
9 |
10 | class Footer extends React.Component {
11 | docUrl(doc, language) {
12 | const baseUrl = this.props.config.baseUrl;
13 | const docsUrl = this.props.config.docsUrl;
14 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
15 | const langPart = `${language ? `${language}/` : ''}`;
16 | return `${baseUrl}${docsPart}${langPart}${doc}`;
17 | }
18 |
19 | pageUrl(doc, language) {
20 | const baseUrl = this.props.config.baseUrl;
21 | return baseUrl + (language ? `${language}/` : '') + doc;
22 | }
23 |
24 | render() {
25 | return (
26 |
29 | );
30 | }
31 | }
32 |
33 | module.exports = Footer;
34 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "examples": "docusaurus-examples",
4 | "start": "docusaurus-start",
5 | "build": "docusaurus-build",
6 | "publish-gh-pages": "docusaurus-publish",
7 | "write-translations": "docusaurus-write-translations",
8 | "version": "docusaurus-version",
9 | "rename-version": "docusaurus-rename-version"
10 | },
11 | "devDependencies": {
12 | "docusaurus": "^1.11.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/website/pages/en/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2017-present, Facebook, Inc.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | const React = require('react');
9 |
10 | const CompLibrary = require('../../core/CompLibrary.js');
11 |
12 | const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */
13 | const Container = CompLibrary.Container;
14 | const GridBlock = CompLibrary.GridBlock;
15 |
16 | class HomeSplash extends React.Component {
17 | render() {
18 | const {siteConfig, language = ''} = this.props;
19 | const {baseUrl, docsUrl} = siteConfig;
20 | const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
21 | const langPart = `${language ? `${language}/` : ''}`;
22 | const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`;
23 |
24 | const SplashContainer = props => (
25 |