1. Project Overview & Quickstart (bbatsov/clojure-style-guide)
1. Project Overview & Quickstart (bbatsov/clojure-style-guide)
clojure-style-guide
A community coding style guide for the Clojure programming language
Repository Details
- Repository: bbatsov/clojure-style-guide
- GitHub Stars: โญ 4,092
- Primary Language: Unknown
Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.
2. Official Technical Reference & Guides (bbatsov/docs)
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:
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) |