1. Project Overview & Quickstart (bbatsov/prelude)
File: README.md
Emacs Prelude
Prelude is an Emacs distribution that aims to enhance the default
Emacs experience. Prelude alters a lot of the default settings,
bundles a plethora of additional packages and adds its own core
library to the mix. The final product offers an easy to use Emacs
configuration for Emacs newcomers and lots of additional power for
Emacs power users.
Prelude is compatible ONLY with GNU Emacs 29.1+. In general
you're advised to always run Prelude with the latest stable
Emacs release.
I've been developing and maintaining Prelude in my free time for well over
a decade. That's a lot of work, and not all of it is fun!
Please consider supporting Prelude's ongoing development.
Features
- Improved UX, that's still in line with Emacs traditions
- Sane defaults of baseline Emacs functionality
- Automatic installation of many major programming modes on demand
- A curated set of 3rd party packages to enhance the base
functionality - Simple modular architecture
- Easy customization
Check out our user manual
for more information.
Fast Forward
Assuming you're using an Unix-like OS (*BSD, GNU/Linux,macOS, Solaris, etc), you already have a recent version of
Emacs installed, as well as git & curl you can skip the
whole manual and just type in your favorite shell the
following command:
curl -L https://git.io/epre | shYou can now power up your Emacs, sit back and enjoy Prelude.
There are two environment variables you can use to control the
source repository and the installation directory. To change the
installation directory:
export PRELUDE_INSTALL_DIR="$HOME/.emacs.d" && \
curl -L https://github.com/bbatsov/prelude/raw/master/utils/installer.sh | shTo change the source repository:
export PRELUDE_URL="https://github.com/yourname/prelude.git" && \
curl -L https://github.com/bbatsov/prelude/raw/master/utils/installer.sh | shNote that the installer will back up any existing .emacs file or.emacs.d since it will unpack Prelude's code in .emacs.d. If
you're doing a manual install make sure you don't have a .emacs
file or back up your existing .emacs.d directory manually.
Important: Don't forget to adjust yourprelude-modules.el file in your personal directory
once the installation is done. By default most of the modules
that ship with Prelude are not loaded.
Try Before You "Buy"
If you're using Emacs 29+ there's a simple way to try Prelude
(or any other Emacs distro for that matter).
Just clone Prelude's repo somewhere and do the following:
emacs --init-dir ~/path/to/preludePhilosophy
Prelude's philosophy is quite simple:
- simple
- easy to understand and extend
- stable
- a foundation for you to build upon, as opposed to some
end-user product
This means that it intentionally doesn't pack all the bells
and whistles that it could. Prelude aims to enhance the classic
Emacs experience without deviating a lot from it - e.g.
it would never enable something like evil-mode
(vim keybindings) by default and so on.
All the third-party packages that it bundles are carefully
vetted and are known to be of good quality and to have reliable
maintainers. That generally means that Prelude's unlikely
to immediate adopt some shiny new package, that has established
tried and true alternatives.
In practice this translates to the following:
- Prelude is less opinionated than distros like Spacemacs and
Doom Emacs (meaning it's closer to the standard Emacs
experience) - Prelude installs relatively few additional packages by default
- Most modules in Prelude are opt-in instead of opt-out
(you'll notice the default config enables only a handful of
modules) - Most modules (e.g. modules for programming languages) are
pretty short and feature setup only for essential packages
(in some cases that be just the major mode for the language
in question) - You don't really need to track Prelude's upstream - you're
encouraged to just fork it and use it as the basis for your
own configuration.
Remember that the ultimate goal of every Emacs user is to
create an Emacs setup that reflects their own experience,
needs, goals and ideas. Just like Lisp, Emacs is nothing but a
raw building material for the perfect editing experience.
More installation options are discussed in the
installation guide.
User Manual
While Emacs Prelude is pretty simple at its core, it does have
some specifics that are worth learning - e.g. configuration
options, load order of modules and personal settings and so on.
Check out our user manual
for more information.
You can also find a lot of information about specific Prelude
features and the rationale behind them on my Emacs blog
Emacs Redux.
crux and super-save
A lot of utility commands that used to be part of Prelude were
eventually extracted to the crux package, so they'd
be easily available to more people.
These days Prelude simply depends on that package.
The super-save package also used to be part
of Prelude in the past.
Upgrading to Prelude 2.0
Prelude 2.0 is a major release that modernizes the entire
distribution around Emacs 29+ features. Here's what you need to know:
Emacs 29.1 is now required
Prelude no longer supports Emacs 28 or older. If you haven't
upgraded yet, now's the time. Emacs 29 brings built-in tree-sitter,
Eglot (LSP client), use-package, and many other improvements that
Prelude 2.0 takes full advantage of.
Tree-sitter support
For built-in modes that ship both classic and tree-sitter variants
(e.g., python-mode / python-ts-mode), Prelude automatically
selects the tree-sitter version when a grammar is available and falls
back to the classic mode when it isn't. Some modules use tree-sitter
modes unconditionally (e.g., prelude-ocaml uses neocaml which is
tree-sitter-only), though such modes typically auto-install their
grammars.
To install tree-sitter grammars, useM-x treesit-install-language-grammar. See the
Emacs manual for details.
Built-in LSP via Eglot
Prelude 2.0 adds LSP support to most language modules using Eglot
(built-in since Emacs 29) as the default client. If you were
previously using prelude-lsp with lsp-mode, note that:
- The module has been renamed to
prelude-lsp-mode. - Set
(setq prelude-lsp-client 'lsp-mode)in your personal
config to keep using lsp-mode. - The default is now Eglot -- no extra packages needed.
- Eglot keybindings live under
C-c C-l(rename, code
actions, format, etc.).
Removed packages and modules
Several outdated packages have been replaced by built-in alternatives:
| Removed | Replacement |
|---|---|
nlinum |
Built-in display-line-numbers-mode |
anzu |
Built-in isearch-lazy-count |
epl |
Built-in package-upgrade-all |
smex (binding) |
execute-extended-command |
anaconda-mode |
LSP (Eglot/lsp-mode) |
js2-mode |
js-ts-mode + LSP |
tide |
typescript-ts-mode + LSP |
alchemist |
LSP |
go-projectile |
Removed (unmaintained) |
prelude-selectrum |
Use prelude-vertico instead |
Keybinding changes
C-x pno longer opensproced(reserved forproject.el).C-x C-mrunsexecute-extended-commandinstead ofsmex.C-c cis bound toorg-capture.C-c C-lprefix is used for Eglot commands in programming
modes.
What you should do
- Update Emacs to 29.1 or newer.
- Pull the latest Prelude and restart Emacs. Packages will
be updated automatically. - Review your
prelude-modules.el-- if you hadprelude-lspenabled, rename it toprelude-lsp-mode. If
you want Eglot (recommended), you don't need any LSP module
enabled. - Install tree-sitter grammars for your languages of choice
(optional but recommended). - Check your personal config for references to removed
packages (nlinum,anzu,epl,anaconda-mode,js2-mode,tide,alchemist).
Known issues
Check out the project's
issue list
a list of unresolved issues. By the way - feel free to fix any
of them and send me a pull request. :-)
Funding
While Prelude is free software and will always be, the project would
benefit immensely from some funding. If Prelude improves your daily Emacs
experience, please consider supporting its ongoing development.
You can support the development of Prelude via:
Support
Support is available via several channels:
- Prelude's Google Group
- GitHub Discussions
Contributors
Here's a list
of all the people who have contributed to the development of
Emacs Prelude.
Bugs & Improvements
Bug reports and suggestions for improvements are always
welcome. GitHub pull requests are even better! :-)
License
Copyright ยฉ 2011-2026 Bozhidar Batsov and
contributors.
Distributed under the GNU General Public License, version 3
File: docs/modules/ai.md
Prelude AI
Overview
gptel is a simple, multi-backend
LLM client for Emacs. This module installs it and provides a single
global keybinding so you can drive it from anywhere.
gptel supports many providers, including:
- Anthropic (Claude)
- OpenAI (GPT-4, GPT-5, etc.)
- Google (Gemini)
- Ollama (local models)
- Azure OpenAI, OpenRouter, Perplexity, and more
Key Bindings
| Key | Command | Description |
|---|---|---|
| C-c q | gptel-menu |
Transient menu (entry to gptel) |
Inside a gptel chat buffer, C-c RET sends the current
prompt and C-c C-c sends the region (these are gptel's
own defaults).
Configuring a backend
You need to configure a backend and an API key in your personal
config (e.g. ~/.emacs.d/personal/ai.el). Some examples:
Anthropic (Claude)
(setq gptel-backend (gptel-make-anthropic "Claude"
:stream t
:key (getenv "ANTHROPIC_API_KEY"))
gptel-model 'claude-sonnet-4-6)OpenAI
OpenAI is gptel's default backend, so you only need to set the key
and the model:
(setq gptel-api-key (getenv "OPENAI_API_KEY")
gptel-model 'gpt-4o)Local Ollama
(setq gptel-backend (gptel-make-ollama "Ollama"
:host "localhost:11434"
:stream t
:models '(llama3.1:8b qwen2.5-coder:7b))
gptel-model 'qwen2.5-coder:7b)See the gptel README for
backend-specific options and the full list of supported providers.
Tips
auth-sourceis supported for API keys โ pass:key 'gptel-api-key-from-auth-sourceor use a function โ so you
don't have to keep the key in environment variables.gptel-add(available from the transient menu) lets you attach
buffers, regions, or files to the chat context.- For agentic editing workflows, take a look at
aidermacs โ it's not
bundled here but pairs naturally with this module.
File: docs/modules/apheleia.md
Prelude Apheleia
Overview
Apheleia is a
unified format-on-save framework for Emacs. On save, it runs the
appropriate external formatter (Prettier, Black, Ruff, gofmt,
rustfmt, ...) asynchronously, then patches the buffer with the
result. The patching is point-preserving and flicker-free -- it
feels like the formatter ran instantly with no visible buffer
churn.
Apheleia ships with sensible defaults for dozens of formatters and
many major modes out of the box. Look at apheleia-formatters andapheleia-mode-alist for the full list.
What this module does
Just two things:
- Installs the
apheleiapackage. - Enables
apheleia-global-mode.
That's it -- no further setup required for the languages Apheleia
already knows about.
Relationship to language modules
Several Prelude language modules install their own format-on-save
hooks (e.g. rust-format-on-save in prelude-rust,gofmt-before-save in prelude-go). These keep working with
Apheleia enabled -- they just run redundantly. If you enable this
module you can safely drop them from your personal config, or
disable them with hooks like:
(with-eval-after-load 'rust-ts-mode
(setq rust-format-on-save nil))
(with-eval-after-load 'go-mode
(remove-hook 'before-save-hook 'gofmt-before-save))Adding a formatter
For languages or tools Apheleia doesn't know about, register a
formatter and tell Apheleia which mode it applies to:
(with-eval-after-load 'apheleia
(setf (alist-get 'shfmt apheleia-formatters)
'("shfmt" "-i" "2" "-ci"))
(setf (alist-get 'sh-mode apheleia-mode-alist) 'shfmt))See the Apheleia README
for the formatter spec and built-in entries you can copy from.
Disabling per buffer
If you need to skip formatting for a specific buffer, runM-x apheleia-mode to toggle it off locally. To skip a whole
project, set a directory-local apheleia-inhibit to t.
File: docs/modules/c.md
Prelude C/C++
!!! Note
This module builds on top of the shared [Programming](programming.md) module.cc-mode
Emacs comes with powerful C/C++ programming support through the built-incc-mode. This module provides sensible defaults for cc-mode and all modes
derived from it (e.g. java-mode, php-mode, etc.).
Prelude configures the following defaults:
- Indentation style: K&R (
c-default-styleset to"k&r") - Indent offset: 4 spaces (
c-basic-offsetset to4) - Substatement opening braces are not indented
(substatement-openoffset set to0)
You can override any of these in your personal config:
(setq prelude-c-mode-common-hook
(lambda ()
(setq c-default-style "linux"
c-basic-offset 8)))Makefile Mode
The module also provides configuration for makefile-mode:
- Tabs are allowed in Makefiles (since they are syntactically required)
indent-tabs-modeis enabled
Key Bindings
Run C-h m in any C/C++ buffer to see all available key bindings.
File: docs/modules/clojure.md
Prelude Clojure
!!! Note
This module builds on top of the shared [Lisp Base](lisp.md) module.Clojure Mode
This module bundles clojure-mode, a major mode for programming in Clojure,
and some sensible defaults for it.
Prelude uses clojure-mode rather than the newer clojure-ts-mode because:
clojure-ts-moderequires Emacs 30+, while Prelude supports Emacs 29.1+.- CIDER and
clj-refactorstill depend onclojure-modefor some APIs. clojure-ts-modeis still under active development and not yet at full
feature parity withclojure-mode.
Using clojure-ts-mode (Emacs 30+)
If you're on Emacs 30+ and want to try tree-sitter based Clojure
support, install clojure-ts-mode in your personal config:
(use-package clojure-ts-mode
:ensure t)clojure-ts-mode auto-remaps clojure-mode buffers when installed,
so no additional configuration is needed. It will also auto-install
the required tree-sitter grammar on first use. See the
clojure-ts-mode documentation
for details.
CIDER
This module also bundles CIDER, a popular interactive
programming environment for Clojure.
Intentionally, Prelude doesn't install by default popular CIDER plugins likeclj-refactor, sayid, etc, as those can be overwhelming to newcomers and
are easy to setup if you need them.
CIDER Alternatives
Depending on your preferences you might want to use inf-clojure or clojure-lsp
alongside/instead of CIDER, but you'll have to set them up yourselves.
Fun trivia
I'm the author of CIDER and inf-clojure and the primary
maintainer of clojure-mode. I'm also a co-maintainer ofclj-refactor. I guess I love Clojure! :-)
File: docs/modules/common_lisp.md
Prelude Common Lisp
!!! Note
This module builds on top of the shared [Lisp Base](lisp.md) module.lisp-mode
Not much to say here, as lisp-mode is configured in the "Lisp Base" module.
SLIME
This module bundles SLIME, a popular interactive
programming environment for Common Lisp, and enables many of its essential features.
SLIME supports many Common Lisp implementations. Prelude defaults to
SBCL on all platforms. You can change this viaslime-default-lisp, or use M-- M-x slime to pick an implementation
interactively.
You can start SLIME with M-x slime.
Alternatives
If you prefer Sly, a modernized fork
of SLIME with features like stickers (non-disruptive value tracing),
multiple REPLs, flex completion out of the box, and a more polished
inspector, you can install it in your personal config instead. Note that
SLIME and Sly conflict with each other -- use one or the other, not both.
To switch, drop something like this into a file under~/.emacs.d/personal/ (and remove prelude-common-lisp from yourprelude-modules.el, or skip loading SLIME some other way):
(use-package sly
:ensure t
:config
(setq inferior-lisp-program "sbcl"))Then start it with M-x sly.
File: docs/modules/company.md
Prelude Company
!!! Note
This module is enabled by default.company is a completion library.
This module simply provides some reasonable defaults for it and enables company-mode:
(setq company-idle-delay 0.5)
(setq company-show-numbers t)
(setq company-tooltip-limit 10)
(setq company-minimum-prefix-length 2)
(setq company-tooltip-align-annotations t)
;; invert the navigation direction if the the completion popup-isearch-match
;; is displayed on top (happens near the bottom of windows)
(setq company-tooltip-flip-when-above t)
(global-company-mode 1)You can adjust the configuration further in your personal config.
company-mode has many extensions
for various programming languages.
Some of Prelude's modules will install and enable the relevant extensions when necessary.
File: docs/modules/corfu.md
Prelude Corfu
Overview
Corfu is a minimal in-buffer
completion UI for Emacs -- a modern, lightweight alternative to
Company. It uses Emacs' built-in completion-at-point infrastructure
and the standard completion styles (so it cooperates withorderless from prelude-vertico), instead of providing its own
backend abstraction the way Company does.
Cape extendscompletion-at-point-functions with extra sources -- file paths,
dabbrev, keywords, ispell, abbrevs, etc. -- so they show up in the
Corfu popup alongside the language-specific completions provided by
LSP servers, Eglot, etc.
!!! Note
This module is mutually exclusive with the
[Company](company.md) module -- enable one or the other, not
both.Packages
Defaults
Corfu auto-pops after typing 2 characters (with a 200 ms debounce)
and cycles through candidates with TAB:
| Variable | Value | Effect |
|---|---|---|
corfu-auto |
t |
Open the popup automatically as you type |
corfu-auto-prefix |
2 |
Minimum prefix length to trigger |
corfu-auto-delay |
0.2 |
Delay (seconds) before popup |
corfu-cycle |
t |
Wrap around at end of list |
corfu-popupinfo-mode is enabled by default -- it shows
documentation for the highlighted candidate in a side popup.
Default Cape sources
The following completion-at-point sources are added globally:
cape-dabbrev- completes from words in open bufferscape-file- completes file paths
Add more from your personal config:
(with-eval-after-load 'cape
(add-hook 'completion-at-point-functions #'cape-keyword)
(add-hook 'completion-at-point-functions #'cape-elisp-block))Tips
- Press M-SPC in the popup to insert a space without
dismissing it (useful with orderless). - M-g opens the candidate at point (e.g. jumps to the
function definition); M-h shows its documentation in a
separate buffer. - For language-specific completions to feel snappy, configure your
LSP setup (Eglot orlsp-mode) to expose richercompletion-at-point-functions-- both already do this out of
the box.
File: docs/modules/css.md
Prelude CSS
CSS Mode
Emacs comes with CSS editing support through the built-incss-mode. This module
adds a couple of enhancements on top of it:
- Indent offset: 2 spaces (
css-indent-offsetset to2) - Rainbow mode:
rainbow-mode
is enabled, which colorizes color strings (like#ff0000orrgb(255, 0, 0)) with the color they represent
The module also runs the prelude-prog-mode-hook, so you get the same baseline
programming features (whitespace visualization, smartparens, etc.) as in other
programming modes.
File: docs/modules/dart.md
Prelude Dart
!!! Note
This module builds on top of the lsp-module.The dart module is powered by lsp-dart.
Some features it provides:
- Flutter integration
- Tree views
- Run pub
- Debug
- Run tests
Some essential commands:
lsp-dart-pub-get- Run pub get or flutter pub get on
project root.lsp-dart-pub-upgrade- Run pub upgrade or flutter pub
upgrade on project root.lsp-dart-pub-outdated- Run pub outdated or flutter pub
outdated on project root.lsp-dart-run-all-tests- Run all tests from project.lsp-dart-run-test-file- Run all tests from current
test buffer.
2. Official Technical Reference & Guides (bbatsov/docs)
File: README.md
Introduction
Volt is a Ruby web framework where your ruby code runs on both the server and the client (via opal). The DOM automatically updates as the user interacts with the page. Page state can be stored in the URL. If the user hits a URL directly, the HTML will first be rendered on the server for faster load times and easier indexing by search engines.
Instead of syncing data between the client and server via HTTP, Volt uses a persistent connection between the client and server. When data is updated on one client, it is updated in the database and any other listening clients (with almost no setup code needed).
Pages HTML is written in a template language where you can put ruby between {{ and }}. Volt uses data flow/reactive programming to automatically and intelligently propagate changes to the DOM (or any other code wanting to know when a value updates). When something in the DOM changes, Volt intelligently updates only the nodes that need to be changed.
See some demo videos here:
- Volt Todos Example
- Pagination Example
- Build a Blog with Volt
** Note: The blog video is outdated, expect an updated version soon.
Check out demo apps:
File: en/contributing/README.md
Contributing
You want to contribute? Great! Thanks for being awesome! We have full docs on how to contribute here:
https://github.com/voltrb/volt/blob/master/CONTRIBUTING.md
File: en/deployment/README.md
Volt Deployment
This chapter highlights various deployment options for Volt on popular cloud providers.
File: en/docs/arraymodel_events.md
ArrayModel Events
Models trigger events when their data is updated. Currently, models emit two events: added and removed. For example:
model = Volt::Model.new
model._items.on('added') { puts 'item added' }
model._items << 1
# => item added
model._items.on('removed') { puts 'item removed' }
model._items.delete_at(0)
# => item removedFile: en/docs/assets.md
Assets
Note, asset management is still early, and likely will change quite a bit
In Volt, assets such as JavaScript and CSS (or sass) are automatically included on the page for you. Anything placed inside of a components asset/js or assets/css folder is served at /assets/{js,css} (via Sprockets). Link and script tags are automatically added for each css and js file in assets/css and assets/js respectively. Files are included in their lexical order, so you can add numbers in front if you need to change the load order.
Any JS/CSS from an included component or component gem will be included as well. By default bootstrap is provided by the volt-bootstrap gem.
Note: asset bundling is on the TODO list
File: en/docs/attribute_bindings.md
Attribute Bindings
Bindings can also be placed inside of attributes.
TextThere are some special features provided to make elements work as "two way bindings":
CheckBoxes
In the example above, if _name changes, the field will update, and if the field is updated, _name will be changed:
If the value of a checked attribute is true, the checkbox will be shown checked. If it's checked or unchecked, the value will be updated to true or false respectively.
Radio Buttons
Radio buttons bind to a checked state as well, except instead of setting the value to true or false, they set it to a supplied field value.
When a radio button is checked, whatever checked is bound to is set to the field's value. When the checked binding value is changed, any radio buttons where the binding's value matches the fields value are checked. NOTE: This seems to be the most useful behavior for radio buttons.
Select Boxes
Select boxes can be bound to a value (while not technically a DOM property, this is another convenient behavior Volt adds).
<select value="{{ _rating }}">
<option value="1">*</option>
<option value="2">**</option>
<option value="3">***</option>
<option value="4">****</option>
<option value="5">*****</option>
</select>When the selected option of the select above changes, _rating is changed to match. When _rating is changed, the selected value is changed to the first option with a matching value. If no matching values are found, the select box is unselected.
File: en/docs/automatic_model_conversion.md
Automatic Model Conversion
Hash -> Model
For convenience, when placing a hash inside of another model, it is automatically converted into a model. Models are similar to hashes, but provide support for things like persistence and triggering reactive events.
user = Volt::Model.new
user._name = 'Ryan'
user._profiles = {
twitter: 'http://www.twitter.com/ryanstout',
dribbble: 'http://dribbble.com/ryanstout'
}
user._name
# => "Ryan"
user._profiles._twitter
# => "http://www.twitter.com/ryanstout"
user._profiles.class
# => Volt::ModelModels are accessed differently from hashes. Instead of using model[:symbol] to access, you call a method model.method_name. This provides a dynamic unified store where setters and getters can be added without changing any access code.
You can get a Ruby hash back out by calling #to_h on a Model.
Array -> ArrayModel
Arrays inside of models are automatically converted to an instance of ArrayModel. ArrayModels behave the same as a normal Array except that they can handle things like being bound to backend data and triggering reactive events.
model = Volt::Model.new
model._items << {name: 'item 1'}
model._items.class
# => Volt::ArrayModel
model._items[0].class
# => Volt::Model
model._items[0]To convert a Volt::Model or a Volt::ArrayModel back to a normal hash, call .to_h or .to_a respectively.
To convert them to a JavaScript Object (for passing to some JavaScript code), call #to_n (to native).
user = Volt::Model.new
user._name = 'Ryan'
user._profiles = {
_twitter: 'http://www.twitter.com/ryanstout',
_dribbble: 'http://dribbble.com/ryanstout'
}
user._profiles.to_h
# => {twitter: 'http://www.twitter.com/ryanstout', dribbble: 'http://dribbble.com/ryanstout'}
items = Volt::ArrayModel.new([1,2,3,4])
# => #<Volt::ArrayModel:70226521081980 [1, 2, 3, 4]>
items.to_a
# => [1,2,3,4]You can get a normal array again by calling .to_a on a Volt::ArrayModel.
File: en/docs/buffers.md
Buffers
Because the store collection is automatically synced to the backend, any change to a model's property will result in all other clients seeing the change immediately. Often this is not the desired behavior. To facilitate building CRUD apps, Volt provides the concept of a "buffer". A buffer can be created from one model and will not save data back to its backing model until .save! is called on it. This lets you create a form thats not saved until a submit button is pressed.
store._items << {name: 'Item 1'}
item1 = store._items[0]
item1_buffer = item1.buffer
item1_buffer._name = 'Updated Item 1'
item1_buffer._name
# => 'Updated Item 1'
item1._name
# => 'Item 1'
item1_buffer.save!
item1_buffer._name
# => 'Updated Item 1'
item1._name
# => 'Updated Item 1'#save! on buffer also returns a promise that will resolve when the data has been saved back to the server.
item1_buffer.save!.then do
puts "Item 1 saved"
end.fail do |err|
puts "Unable to save because #{err}"
endCalling .buffer on an existing model will return a buffer for that model instance. If you call .buffer on a Volt::ArrayModel (plural sub-collection), you will get a buffer for a new item in that collection. Calling .save! will then add the item to that sub-collection as if you had done << to push the item into the collection.
File: en/docs/callbacks_and_actions.md
Controller Actions
When a template binding or tag renders a view, it first loads a controller. There are four callbacks around the rendering. The {action} is the same as the view file's name. So if you were rendering about.html, about would be the action. Simply create the correct method in the controller and it will called at the time.
| action name | description |
|---|---|
{action} |
called before anything renders. Setup data you need |
{action}_ready |
called after the view renders. Run any code where you need to bind directly to the dom. jQuery setup code for example (bootstrap components) |
before_{action}_remove |
called before the view is removed (unrendered). Cleanup any dom bindings here. |
after_{action}_remove |
called after the view is removed from the dom. Cleanup anything in the controller that needs to be cleaned up. |
Most of the time all you will need is the action method to setup the controller, model, etc...
File: en/docs/channel.md
Channel
Controllers provide a #channel method, that you can use to get the status of the connection to the backend. Channel's access methods are reactive and when the status changes, the watching computations will be re-triggered. It provides the following:
| method | description |
|---|---|
| connected? | true if it is connected to the backend |
| status | possible values: :opening, :open, :closed, :reconnecting |
| error | the error message for the last failed connection |
| retry_count | the number of reconnection attempts that have been made without a successful connection |
| reconnect_interval | the time until the next reconnection attempt (in seconds) |