├── .gitignore
├── LANGS.md
├── README.md
├── book.json
├── en
├── README.md
├── SUMMARY.md
├── book.json
├── contributing
│ ├── README.md
│ └── component_gems.md
├── cover.jpg
├── cover_small.jpg
├── deployment
│ ├── README.md
│ ├── apache.md
│ ├── cloud9.md
│ ├── docker.md
│ ├── heroku.md
│ └── nginx.md
├── docs
│ ├── README.md
│ ├── arraymodel_events.md
│ ├── assets.md
│ ├── associations.md
│ ├── attribute_bindings.md
│ ├── automatic_model_conversion.md
│ ├── beforeafter_actions.md
│ ├── buffers.md
│ ├── callbacks_and_actions.md
│ ├── channel.md
│ ├── component_gems.md
│ ├── components.md
│ ├── content_binding.md
│ ├── controllers.md
│ ├── debugging.md
│ ├── delayed_rendering.md
│ ├── dependencies.md
│ ├── each_binding.md
│ ├── environment_options.md
│ ├── escaping.md
│ ├── event_bindings.md
│ ├── fields.md
│ ├── flash_collection.md
│ ├── forking_server.md
│ ├── getting_view_dom_nodes.md
│ ├── http_controllers.md
│ ├── if_binding.md
│ ├── lib.md
│ ├── lifecycle_callbacks.md
│ ├── long_running_processes.md
│ ├── long_running_tasks.md
│ ├── message_bus.md
│ ├── middleware.md
│ ├── model_classes.md
│ ├── model_states.md
│ ├── models.md
│ ├── nil_models.md
│ ├── permissions.md
│ ├── provided_collections.md
│ ├── provided_components.md
│ ├── reactive_accessors.md
│ ├── rendering.md
│ ├── requiring_files.md
│ ├── routes.md
│ ├── routes_file.md
│ ├── runnersprocesses.md
│ ├── store_collections.md
│ ├── sub_collections.md
│ ├── tag_attributes.md
│ ├── tag_events_and_triggering.md
│ ├── tags.md
│ ├── tasks.md
│ ├── testing.md
│ ├── url.md
│ ├── url_for_and_url_with.md
│ ├── users.md
│ ├── validations.md
│ ├── view_bindings.md
│ ├── views.md
│ ├── volt_command.md
│ ├── volt_helpers.md
│ ├── volt_internals.md
│ ├── volt_time.md
│ └── yield_binding.md
├── getting_help
│ ├── README.md
│ ├── can_i_use_jquery_or_other_dom_manipulating_js.md
│ ├── can_i_use_opal_gems.md
│ ├── does_volt_support_haml,_slim,_etc.md
│ ├── faq.md
│ ├── is_keeping_a_persistent_connection_open_a_performance_problem.md
│ ├── what_browsers_does_volt_support.md
│ ├── what_runs_on_the_client_vs_server.md
│ ├── whats_the_difference_between_volt_and_meteor.md
│ └── why_use_underscore_accessors_instead_of_[property].md
├── introduction
│ └── README.md
├── roadmap
│ └── README.md
├── tutorial
│ ├── README.md
│ ├── a_sample_todo_app.md
│ └── todo_functionality.md
└── why_volt
│ └── README.md
├── es
├── README.md
├── SUMMARY.md
├── book.json
├── contributing
│ ├── README.md
│ └── component_gems.md
├── deployment
│ ├── README.md
│ ├── apache.md
│ ├── cloud9.md
│ ├── docker.md
│ ├── heroku.md
│ └── nginx.md
├── docs
│ ├── README.md
│ ├── arraymodel_events.md
│ ├── assets.md
│ ├── associations.md
│ ├── attribute_bindings.md
│ ├── automatic_model_conversion.md
│ ├── beforeafter_actions.md
│ ├── buffers.md
│ ├── callbacks_and_actions.md
│ ├── channel.md
│ ├── component_gems.md
│ ├── components.md
│ ├── content_binding.md
│ ├── controllers.md
│ ├── debugging.md
│ ├── dependencies.md
│ ├── each_binding.md
│ ├── environment_options.md
│ ├── escaping.md
│ ├── event_bindings.md
│ ├── fields.md
│ ├── flash_collection.md
│ ├── forking_server.md
│ ├── getting_view_dom_nodes.md
│ ├── http_controllers.md
│ ├── if_binding.md
│ ├── lib.md
│ ├── lifecycle_callbacks.md
│ ├── message_bus.md
│ ├── middleware.md
│ ├── model_classes.md
│ ├── model_states.md
│ ├── models.md
│ ├── nil_models.md
│ ├── permissions.md
│ ├── provided_collections.md
│ ├── provided_components.md
│ ├── reactive_accessors.md
│ ├── rendering.md
│ ├── requiring_files.md
│ ├── routes.md
│ ├── routes_file.md
│ ├── runnersprocesses.md
│ ├── store_collections.md
│ ├── sub_collections.md
│ ├── tag_attributes.md
│ ├── tag_events_and_triggering.md
│ ├── tags.md
│ ├── tasks.md
│ ├── testing.md
│ ├── url.md
│ ├── url_for_and_url_with.md
│ ├── users.md
│ ├── validations.md
│ ├── view_bindings.md
│ ├── views.md
│ ├── volt_command.md
│ ├── volt_helpers.md
│ ├── volt_internals.md
│ └── yield_binding.md
├── getting_help
│ ├── README.md
│ ├── can_i_use_jquery_or_other_dom_manipulating_js.md
│ ├── can_i_use_opal_gems.md
│ ├── does_volt_support_haml,_slim,_etc.md
│ ├── faq.md
│ ├── is_keeping_a_persistent_connection_open_a_performance_problem.md
│ ├── what_browsers_does_volt_support.md
│ ├── what_runs_on_the_client_vs_server.md
│ ├── whats_the_difference_between_volt_and_meteor.md
│ └── why_use_underscore_accessors_instead_of_[property].md
├── introduction
│ └── README.md
├── tutorial
│ ├── README.md
│ ├── a_sample_todo_app.md
│ └── todo_functionality.md
└── why_volt
│ └── README.md
├── ja
├── README.md
├── SUMMARY.md
├── book.json
├── contributing
│ ├── README.md
│ └── component_gems.md
├── cover.jpg
├── cover_small.jpg
├── deployment
│ ├── README.md
│ ├── apache.md
│ ├── cloud9.md
│ ├── docker.md
│ ├── heroku.md
│ └── nginx.md
├── docs
│ ├── README.md
│ ├── arraymodel_events.md
│ ├── assets.md
│ ├── associations.md
│ ├── attribute_bindings.md
│ ├── automatic_model_conversion.md
│ ├── beforeafter_actions.md
│ ├── buffers.md
│ ├── callbacks_and_actions.md
│ ├── channel.md
│ ├── component_gems.md
│ ├── components.md
│ ├── content_binding.md
│ ├── controllers.md
│ ├── debugging.md
│ ├── delayed_rendering.md
│ ├── dependencies.md
│ ├── each_binding.md
│ ├── environment_options.md
│ ├── escaping.md
│ ├── event_bindings.md
│ ├── fields.md
│ ├── flash_collection.md
│ ├── forking_server.md
│ ├── getting_view_dom_nodes.md
│ ├── http_controllers.md
│ ├── if_binding.md
│ ├── lib.md
│ ├── long_running_processes.md
│ ├── long_running_tasks.md
│ ├── message_bus.md
│ ├── middleware.md
│ ├── model_classes.md
│ ├── model_states.md
│ ├── models.md
│ ├── nil_models.md
│ ├── permissions.md
│ ├── provided_collections.md
│ ├── provided_components.md
│ ├── reactive_accessors.md
│ ├── rendering.md
│ ├── requiring_files.md
│ ├── routes.md
│ ├── routes_file.md
│ ├── runnersprocesses.md
│ ├── store_collections.md
│ ├── sub_collections.md
│ ├── tag_attributes.md
│ ├── tag_events_and_triggering.md
│ ├── tags.md
│ ├── tasks.md
│ ├── testing.md
│ ├── url.md
│ ├── url_for_and_url_with.md
│ ├── users.md
│ ├── validations.md
│ ├── view_bindings.md
│ ├── views.md
│ ├── volt_command.md
│ ├── volt_helpers.md
│ ├── volt_internals.md
│ └── yield_binding.md
├── getting_help
│ ├── README.md
│ ├── can_i_use_jquery_or_other_dom_manipulating_js.md
│ ├── can_i_use_opal_gems.md
│ ├── does_volt_support_haml,_slim,_etc.md
│ ├── faq.md
│ ├── is_keeping_a_persistent_connection_open_a_performance_problem.md
│ ├── what_browsers_does_volt_support.md
│ ├── what_runs_on_the_client_vs_server.md
│ ├── whats_the_difference_between_volt_and_meteor.md
│ └── why_use_underscore_accessors_instead_of_[property].md
├── introduction
│ └── README.md
├── roadmap
│ └── README.md
├── tutorial
│ ├── README.md
│ ├── a_sample_todo_app.md
│ └── todo_functionality.md
└── why_volt
│ └── README.md
└── styles
└── website.css
/.gitignore:
--------------------------------------------------------------------------------
1 | _book
2 | .DS_Store
--------------------------------------------------------------------------------
/LANGS.md:
--------------------------------------------------------------------------------
1 | * [English](en/)
2 | * [Spanish](es/)
3 | * [Japanese](ja/)
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | Volt is a Ruby web framework where your ruby code runs on both the server and the client (via [opal](https://github.com/opal/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.
4 |
5 | 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).
6 |
7 | 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.
8 |
9 | See some demo videos here:
10 | - [Volt Todos Example](https://www.youtube.com/watch?v=Tg-EtRnMz7o)
11 | - [Pagination Example](https://www.youtube.com/watch?v=1uanfzMLP9g)
12 | - [Build a Blog with Volt](https://www.youtube.com/watch?v=c478sMlhx1o)
13 | ** Note: The blog video is outdated, expect an updated version soon.
14 |
15 | Check out demo apps:
16 | - https://github.com/voltrb/todos3
17 | - https://github.com/voltrb/contactsdemo
18 |
19 |
--------------------------------------------------------------------------------
/book.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/en/README.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | Volt is a Ruby web framework where your Ruby code runs on both the server and the client (via [opal](https://github.com/opal/opal)). The DOM automatically updates as a user interacts with the page. Page state can be stored in the URL, so bookmarks return to the same state.
4 |
5 | Instead of syncing data between the client and the server via HTTP, Volt uses a persistent connection. When data is updated on one client, it is updated in the database and in any other listening clients (with no setup needed). Permissions and validations can be created to control how data can be updated.
6 |
7 | Page 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 that wants to know when a value changes). When something in the DOM changes, Volt intelligently updates only the nodes that need to be changed.
8 |
9 | In addition to the docs, a good way to get started is with the demo videos:
10 |
11 | - [Volt Todos Example](https://www.youtube.com/watch?v=KbFtIt7-ge8)
12 | - [What Is Volt in 6 Minutes](https://www.youtube.com/watch?v=P27EPQ4ne7o)
13 | - [Pagination Example](https://www.youtube.com/watch?v=1uanfzMLP9g)
14 | - [Routes and Templates](https://www.youtube.com/watch?v=1yNMP3XR6jU)
15 | - [Isomorphic App Development - RubyConf 2014](https://www.youtube.com/watch?v=7i6AL7Walc4)
16 |
17 | Check out demo apps:
18 | - https://github.com/voltrb/todomvc
19 | - https://github.com/voltrb/blog5
20 |
21 |
--------------------------------------------------------------------------------
/en/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Volt Introduction and Docs",
3 | "description": "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.\n\nInstead 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).\n\nPages HTML is written in a handlebars-like template language. 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."
4 | }
--------------------------------------------------------------------------------
/en/contributing/README.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | You want to contribute? Great! Thanks for being awesome! We have full docs on how to contribute here:
4 | https://github.com/voltrb/volt/blob/master/CONTRIBUTING.md
5 |
--------------------------------------------------------------------------------
/en/contributing/component_gems.md:
--------------------------------------------------------------------------------
1 | # Component Gems
2 |
3 | NOTE: this section is a work in progress
4 |
5 | There is a discussion about gems in [this chapter]("../docs/lib.html")
6 |
7 | ## Component Load Order
8 |
9 | -
10 |
--------------------------------------------------------------------------------
/en/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voltrb/docs/9e8b414a9e2209a82b4d3451d734a4b5e7c15fd2/en/cover.jpg
--------------------------------------------------------------------------------
/en/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voltrb/docs/9e8b414a9e2209a82b4d3451d734a4b5e7c15fd2/en/cover_small.jpg
--------------------------------------------------------------------------------
/en/deployment/apache.md:
--------------------------------------------------------------------------------
1 | # Apache
2 |
3 | Apache does not support Websockets, [see this post](https://github.com/phusion/passenger/issues/1202).
4 | Therefore you'll have to use Apache as a forward-proxy to [thin](http://code.macournoyer.com/thin/).
5 | Your Apache will need the following modules enabled:
6 | - [mod_proxy](http://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
7 | - [mod_proxy_wstunnel](http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
8 |
9 | ```
10 |
11 | ServerName YOUR.SERVER.NAME
12 | DocumentRoot /PATH/TO/APP_NAME/public
13 |
14 | ProxyRequests Off
15 | ProxyPreserveHost On
16 |
17 | # a2enmod proxy_wstunnel
18 | ProxyPass /socket ws://localhost:3001/socket
19 | ProxyPassReverse /socket ws://localhost:3001/socket
20 | ProxyPass / http://localhost:3001/
21 | ProxyPassReverse / http://localhost:3001/
22 |
23 | LogLevel warn
24 |
25 | CustomLog ${APACHE_LOG_DIR}/APP_NAME_access.log combined
26 | ErrorLog ${APACHE_LOG_DIR}/APP_NAME_error.log
27 |
28 | ```
29 |
30 | Install this as a service with `thin install` and add the following configuration file inside `/var/thin/volt.yml`
31 |
32 | ```
33 | ---
34 | chdir: "/PATH/TO/APP_NAME"
35 | environment: production
36 | address: 0.0.0.0
37 | port: 3001
38 | timeout: 30
39 | log: "/var/log/thin-expenses.log"
40 | pid: tmp/pids/thin.pid
41 | max_conns: 1024
42 | max_persistent_conns: 100
43 | require: []
44 | wait: 30
45 | threadpool_size: 20
46 | servers: 1
47 | daemonize: true
48 | ```
49 |
50 | Start thin afterwards with `sudo /etc/init.d/thin start`
51 |
--------------------------------------------------------------------------------
/en/deployment/cloud9.md:
--------------------------------------------------------------------------------
1 | # Cloud9
2 |
3 | To get started on cloud9, boot up a rails image (since it has everything we need). Once booted, remove the existing project:
4 |
5 | ```rm -rf *```
6 |
7 | First lets setup mongo (see the full docs on running mongo here).
8 |
9 | Start a new terminal and enter the following:
10 |
11 | ```
12 | mkdir data
13 | echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest "$@"' > mongod
14 | chmod a+x mongod
15 | ```
16 |
17 | Then you can run mongod with:
18 |
19 | ```
20 | ./mongod
21 | ```
22 |
23 | Next lets install volt.
24 |
25 | ```gem install volt```
26 |
27 | Then create a new project:
28 |
29 | ```volt new projectname```
30 |
31 | cd into the project:
32 |
33 | ```cd projectname```
34 |
35 | And start the server (on Cloud9, you must pass in the port and ip from ENV's)
36 |
37 | ```bundle exec volt server -p $PORT -b $IP```
38 |
39 | Cloud9 will give each app a custom sub-domain, to visit the running app, click the ```Preview``` menu, then ```Preview Running Application```
40 |
41 | At least with the free version on Cloud9, your mongoDB may be uncleanly shut down periodically. You can set up a free Mongo store on www.mongolab.com instead as an alternative. Set up an account there, then add the following to your config/app.rb:
42 |
43 | ```
44 | config.db_driver = 'mongo'
45 | config.db_name = (config.app_name + '_' + Volt.env.to_s)
46 | if ENV['MONGOHQ_URL'].present?```
47 | config.db_uri = ENV['MONGOHQ_URL'] # you will have to set this on Cloud9.
48 | else
49 | config.db_host = 'localhost'
50 | config.db_port = 27017
51 | end
52 | ```
53 |
54 |
55 | NOTE: if anyone wants to create a custom Volt image for cloud9, please let @ryanstout know in the gitter room. Thanks!
56 |
--------------------------------------------------------------------------------
/en/deployment/docker.md:
--------------------------------------------------------------------------------
1 | ## Docker container for Volt
2 |
3 | Create a Dockerfile in your Volt app with the following
4 |
5 | ```
6 | FROM otzy007/voltframework
7 | ```
8 |
9 | Then you can build the Docker image:
10 |
11 | ```
12 | docker build -t my-volt-app .
13 | ```
14 |
15 | And run it:
16 |
17 | ```
18 | docker run --name my-volt-app -p 3000:3000 -d my-volt-app
19 | ```
20 |
21 | You can then go to http://localhost:3000 in your browser
22 |
--------------------------------------------------------------------------------
/en/deployment/heroku.md:
--------------------------------------------------------------------------------
1 | ## Heroku
2 |
3 | Edit your ```Gemfile``` to specify Ruby version, e.g.
4 |
5 | ```ruby
6 | source 'https://rubygems.org'
7 |
8 | ruby "2.1.3" # specify a Ruby version
9 |
10 | gem 'volt', ~> '0.9.0'
11 | ```
12 |
13 | Add a ```Procfile``` that uses Thin
14 |
15 | web: bundle exec thin start -p $PORT -e $RACK_ENV
16 |
17 | Set up your data store connection in ```config/app.rb```.
18 | Below you see an example for MongoHQ. You'll need to adapt for your provider.
19 | [MongoLab](http://www.mongolab.com) is a great free solution.
20 |
21 | ```ruby
22 | config.db_driver = 'mongo'
23 | config.db_name = (config.app_name + '_' + Volt.env.to_s)
24 |
25 | if ENV['MONGOLAB_URI'].present?
26 | config.db_uri = ENV['MONGOLAB_URI'] # you will have to set this on heroku
27 | else
28 | config.db_host = 'localhost'
29 | config.db_port = 27017
30 | end
31 | ```
32 |
--------------------------------------------------------------------------------
/en/docs/arraymodel_events.md:
--------------------------------------------------------------------------------
1 | ## ArrayModel Events
2 |
3 | ArrayModels trigger events when their data is updated. Currently, models emit two events: ```added``` and ```removed```. For example:
4 |
5 | ```ruby
6 | page._items.on('added') { puts 'item added' }
7 | page._items << 1
8 | # => item added
9 |
10 | page._items.on('removed') { puts 'item removed' }
11 | page._items.delete_at(0)
12 | # => item removed
13 | ```
14 |
15 | This is used internally on each bindings, but can be used in your own code.
16 |
17 | NOTE: ArrayModel events are sort of an unofficial feature right now. No guarentees on them working in all cases.
18 |
--------------------------------------------------------------------------------
/en/docs/automatic_model_conversion.md:
--------------------------------------------------------------------------------
1 | # Automatic Model Conversion
2 |
3 | ## Hash -> Model
4 |
5 | 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.
6 |
7 | ```ruby
8 | user = Volt::Model.new
9 | user._name = 'Ryan'
10 | user._profile = {
11 | twitter: 'http://www.twitter.com/ryanstout',
12 | dribbble: 'http://dribbble.com/ryanstout'
13 | }
14 |
15 | user._name
16 | # => "Ryan"
17 | user._profile._twitter
18 | # => "http://www.twitter.com/ryanstout"
19 | user._profile.class
20 | # => Volt::Model
21 | ```
22 |
23 | You can get a Ruby hash back out by calling `#to_h` on a Model.
24 |
25 | ## Array -> ArrayModel
26 |
27 | 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.
28 |
29 | ```ruby
30 | model = Volt::Model.new
31 | model._items << {name: 'item 1'}
32 | model._items.class
33 | # => Volt::ArrayModel
34 |
35 | model._items[0].class
36 | # => Volt::Model
37 | model._items[0]
38 | ```
39 |
40 |
41 | To convert a Volt::Model or a Volt::ArrayModel back to a normal hash, call .to_h or .to_a respectively.
42 | To convert them to a JavaScript Object (for passing to some JavaScript code), call `#to_n` (to native).
43 |
44 | ```ruby
45 | user = Volt::Model.new
46 | user._name = 'Ryan'
47 | user._profile = {
48 | twitter: 'http://www.twitter.com/ryanstout',
49 | dribbble: 'http://dribbble.com/ryanstout'
50 | }
51 |
52 | user._profile.to_h
53 | # => {twitter: 'http://www.twitter.com/ryanstout', dribbble: 'http://dribbble.com/ryanstout'}
54 |
55 | items = Volt::ArrayModel.new([1,2,3,4])
56 | # => #
57 |
58 | items.to_a
59 | # => [1,2,3,4]
60 | ```
61 |
62 | You can get a normal array again by calling .to_a on a Volt::ArrayModel.
63 |
--------------------------------------------------------------------------------
/en/docs/beforeafter_actions.md:
--------------------------------------------------------------------------------
1 | # Before/After Filters
2 |
3 | Often in controllers, during rendering, there is code you want to run before or after your main action runs. Volt provides ```before_action``` and ```after_action``` methods on the class that you can use to setup a "before action" or "after action". You can setup actions like below:
4 |
5 | ```ruby
6 | module Main
7 | class MainController < Volt::ModelController
8 | before_action :english_only
9 |
10 | # require login is a method in Volt::ModelController
11 | before_action :require_login, only: :about
12 |
13 | def index
14 | # Setup index...
15 | end
16 |
17 | def about
18 | # Setup about...
19 | end
20 |
21 | # Redirect somewhere if they aren't in an english locale
22 | # (just as an example)
23 | def english_only
24 | if `navigator.language` != 'en-US'
25 | redirect_to '/translations'
26 | stop_chain # see below
27 | end
28 | end
29 | end
30 | end
31 | ```
32 |
33 | Actions can also take a block instead of a symbol for the method name.
34 |
35 | ## only certain actions
36 |
37 | You can limit which actions a filter runs on by passing ```only: :some_action``` as an argument. ```only``` can be set to either a symbol or an array of symbols.
38 |
39 | # stop_chain
40 |
41 | It is common to redirect from inside of a before filter. If you no longer wish to continue with the rendering, you can call ```stop_chain``` in an action and the rendering will stop.
42 |
43 | ```stop_chain``` raises an exception that will be caught by the filter runner, so no code after ```stop_chain``` will be run.
44 |
--------------------------------------------------------------------------------
/en/docs/callbacks_and_actions.md:
--------------------------------------------------------------------------------
1 | # Controller Actions
2 |
3 | When a view 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.
4 |
5 | | action name | description |
6 | |-----------------------|-----------------------------------------------------|
7 | | before_action callbacks | All before actions are called before the main action method. If ```stop_chain``` is called, ```{action}``` will not be called and execution will be halted. |
8 | | ```{action}``` | called before anything renders. Setup data you need |
9 | | after_action callbacks | after_actions can not call ```stop_chain``` (in an after callback, it will raise an exception) |
10 | | ```{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) |
11 | | ```before_{action}_remove``` | called before the view is removed (unrendered). Cleanup any dom bindings here. |
12 | | ```after_{action}_remove``` | called after the view is removed from the dom. Cleanup anything in the controller that needs to be cleaned up. |
13 |
14 | Most of the time all you will need is the action method to setup the controller, model, etc...
15 |
16 |
--------------------------------------------------------------------------------
/en/docs/channel.md:
--------------------------------------------------------------------------------
1 | # Channel
2 |
3 | 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:
4 |
5 | | method | description |
6 | |-------------|-----------------------------------------------------------|
7 | | connected? | true if it is connected to the backend |
8 | | status | possible values: :opening, :open, :closed, :reconnecting |
9 | | error | the error message for the last failed connection |
10 | | retry_count | the number of reconnection attempts that have been made without a successful connection |
11 | | reconnect_interval | the time until the next reconnection attempt (in seconds) |
12 |
13 | ## Channel Events
14 |
15 | Sometimes you need to run code when the client connects or disconnects to/from the server. In a controller on the client you can do:
16 |
17 | ```ruby
18 | channel.on('connect') do
19 | .. connected ..
20 | end
21 |
22 | channel.on('disconnect') do
23 | .. disconnect ..
24 | end
25 | ```
26 |
--------------------------------------------------------------------------------
/en/docs/component_gems.md:
--------------------------------------------------------------------------------
1 | # Component Gems
2 |
3 | Components can easily be shared as a gem. Volt provides a scaffold command for creating component gems. In a folder (not in a volt project), simply type: ```volt generate gem {component_name}```. This will create the files needed for a new gem. Note that all volt component gems will be prefixed with ```volt-``` so that they can easily be found by others on github and rubygems. You should use underscores in the component name to follow the gem naming convention.
4 |
5 | While developing, you can use the component by placing the following in your Gemfile:
6 |
7 | ```ruby
8 | gem 'volt-{component_name}', path: '/path/to/folder/with/component'
9 | ```
10 |
11 | Once the gem is ready, you can release it to rubygems with:
12 |
13 | ```
14 | rake release
15 | ```
16 |
17 | Remove the ```path:``` option in the gemfile if you wish to use the rubygems version.
18 |
--------------------------------------------------------------------------------
/en/docs/components.md:
--------------------------------------------------------------------------------
1 | # Components
2 |
3 | Apps are made up of Components. Each folder under ```app/``` is a component. Components can also be included from gems. Apps are commonly broken up into multiple components. Components can be anything from a small reusable widget to a large section of the app. Since components can be included in other components, we recommend starting with smaller components and building up larger ones. Components that are likely to be reused can be built as [component gems](docs/component_gems.md), or you can move a component into a gem at a later time.
4 |
5 | The code inside of a component can be accessed in a few ways. Model code is accessible from anywhere in the app. Views/controllers can be accessed using tags or view bindings. See [tags](docs/tags.md) for info on how view path lookup works.
6 |
7 | The overall idea of components is to keep more parts of your code isolated so they can be independently tested and abstracted.
8 |
9 | Some example components might be:
10 |
11 | __Widgets__
12 | - A field with validations
13 | - A slider
14 | - WYSIWYG editor
15 | - file uploader
16 | - Google map
17 |
18 | __Pages__
19 | - login page
20 | - user signup/login/forgot password
21 | -
22 |
23 | __Parts of app__
24 | - blog
25 | - cms
26 | - admin area
27 |
28 | A good rule of thumb is to use more components than you think you'll need, since there is little overhead in splitting parts of your app.
29 |
30 | ## Generate a Component
31 |
32 | You can add a new component to an app with:
33 |
34 | ```bundle exec volt generate component NAME```
35 |
36 | ## Components and Routing
37 |
38 | When you visit a route, it loads all of the files in the component on the front end, so new pages within the component can be rendered without a new http request. If a URL is visited that routes to a different component, the request will be loaded as a normal page load and all of that component's files will be loaded. You can think of components as the "reload boundary" between sections of your app. [Note: currently only the "main" component is supported for initial page load, expect "reload boundry" support soon]
39 |
40 |
--------------------------------------------------------------------------------
/en/docs/content_binding.md:
--------------------------------------------------------------------------------
1 | # Content binding
2 |
3 | The most basic binding is a content binding:
4 |
5 | ```html
6 |
Hello {{ name }}
7 | ```
8 |
9 | The content binding runs the Ruby code between ```{{``` and ```}}```, then renders the return value. Any time the data a content binding relies on changes, the binding will run again and update the text. Text in content bindings is html escaped by default.
10 |
11 | ## Raw
12 |
13 | You can disable html escaping by using the ```raw``` method:
14 |
15 | ```html
16 |
Your html is {{ raw your_html }}.
17 | ```
18 |
19 | Using raw is considered dangerous because if the user controlled html is displayed to another user, they can easily inject any javascript (by using something like ``````) This is known as a Cross Site Scripting Attack. Only use raw if you understand how a Cross Site Scripting Attack works and how to avoid them.
20 |
--------------------------------------------------------------------------------
/en/docs/debugging.md:
--------------------------------------------------------------------------------
1 | # Debugging
2 |
3 | ## Sourcemaps
4 |
5 | Volt (via Opal) has sourcemaps enabled by default. In Chrome and Firefox, when you see a stack trace in the devtools, it will show the ruby filename/line numbers. You can click on the filename to be taken to the original ruby file in the devtools. You can set breakpoints and step through like you would with JavaScript. An in browser irb is in the works as well.
6 |
7 | By default in Volt 0.9.5.pre3 and greater, sourcemaps are enabled by default in Development mode. You can disable them by doing:
8 |
9 | ```MAPS=false bundle exec volt server```
10 |
11 | For performance reasons, opal and volt's code in not mapped. This saves some time on page load. You can enable mapping for all files by doing:
12 |
13 | ```MAPS=all bundle exec volt server```
14 |
15 | ### Framework Blackboxing
16 |
17 | When using sourcemaps, you may see many extra files in stack traces and while stepping. Framework Blackboxing lets you treat things like Volt and Opal like native code, so they will be ignored. You can add the following blackbox check to blackbox Volt and Opal.
18 |
19 | ```
20 | /assets/volt/volt/app\.js$|/assets/js/volt_watch\.js$|/assets/js/volt_js_polyfills\.js$
21 | ```
22 |
--------------------------------------------------------------------------------
/en/docs/delayed_rendering.md:
--------------------------------------------------------------------------------
1 | # Delayed Rendering
2 |
3 | If ```self.model = ...``` is called and the model is set to a Promise, the controller will wait until the Promsie resolves before is is rendered. Volt::ModelControllers have a ```loaded?``` method, which is checked by views when rendering. The views reactively wait until ```loaded?``` returns true before rendering. This is useful because you don't need to check if the model is loaded, if you assign the model to a Promise, you can assume it is ready before the view starts rendering
4 |
5 | For example, if you did:
6 |
7 | ```ruby
8 | module Main
9 | class MainController < Volt::ModelController
10 | def index
11 | self.model = store.posts.first
12 | end
13 | end
14 | end
15 | ```
16 |
17 | In the above example, when a view binding (or tag) started to render index.html, it would create a controller instance, then it would call ```#index``` Next the view binding would wait until the Promise resolved before rendering the index.html file. After that it would call ```#index_ready```. This makes it simple to wait on data before rendering.
18 |
--------------------------------------------------------------------------------
/en/docs/dependencies.md:
--------------------------------------------------------------------------------
1 | # Dependencies
2 |
3 | You can also use [tags](#tags) from one component in another. To do this, you must require the source component from the component you wish to use them in. This can be done in the ```config/dependencies.rb``` file. Just put
4 |
5 | ```ruby
6 | component 'component_name'
7 | ```
8 |
9 | in the file.
10 |
11 | Dependencies act just like ```require``` in ruby, but for whole components.
12 |
13 | Sometimes you may need to include an externally hosted JS file from a component. To do this, simply do the following in the dependencies.rb file:
14 |
15 | ```ruby
16 | javascript_file 'http://code.jquery.com/jquery-2.0.3.min.js'
17 | css_file '//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css'
18 | ```
19 |
20 | Note, however, that jquery and bootstrap are currently both included by default. Dependencies included with ```javascript_file``` and ```css_file``` will be mixed in with your component assets at the correct locations according to the order that they occur in the dependencies.rb files.
21 |
--------------------------------------------------------------------------------
/en/docs/each_binding.md:
--------------------------------------------------------------------------------
1 | # Each binding
2 |
3 | For iteration over objects, you can use ```.each```
4 |
5 | ```html
6 | {{ _items.each do |item| }}
7 |
{{ item }}
8 | {{ end }}
9 | ```
10 |
11 | Above, if ```_items``` is an array, the block will be rendered for each item in the array, setting ```item``` to the value of the array element.
12 |
13 | You can also call .each_with_index to place the index in a local variable within the block
14 |
15 | ```html
16 | {{ _items.each_with_index do |item, index| }}
17 |
{{ index }}. {{ item }}
18 | {{ end }}
19 | ```
20 |
21 | For the array: ```['one', 'two', 'three']``` this would print:
22 |
23 | 0. one
24 | 1. two
25 | 2. three
26 |
27 | You can do ```{{ index + 1 }}``` to correct the zero offset.
28 |
29 | When items are removed or added to the array, the ```each``` binding automatically and intelligently adds or removes the items from/to the DOM.
30 |
31 | ## With Index
32 |
33 | Each bindings support .each_with_index
34 |
35 | ```html
36 | {{ _items.each_with_index do |item, index| }}
37 |
{{ index }}. {{ item.name }}
38 | {{ end }}
39 | ```
40 |
41 | ## Current Limitations
42 |
43 | Currently .each in bindings is rather limited (we're working on it). It can only handle arrays, not hashes. To use hashes, convert them to arrays first. Also, it can only take one argument (except when using .each_with_index).
44 |
--------------------------------------------------------------------------------
/en/docs/environment_options.md:
--------------------------------------------------------------------------------
1 | # Environment Options
2 |
3 | In addition to the options in config/app.rb, some instance specific options in Volt can be configured with instance variables.
4 |
5 | | Name | Description |
6 | |------------------------|-----------------------------------------|
7 | | VOLT_ENV | Sets the value of Volt.env, which is used to control how various parts of the application. |
8 | | RACK_ENV | Also can be used to set Volt.env |
9 | | NO_MESSAGE_BUS | Disable the message bus. This will prevent updates from propagating between Volt instances, but can be useful for debugging |
10 | | NO_FORKING | The "Forking Server" is used in development on MRI to allow code reloading. (It forks a child process for connections, which are killed and reforked when code changes). Disabling forking prevents code reloading for Tasks, HttpControllers, Routes, and a few other things. |
11 | | WEBSOCKET_PING_TIME | When present, the websocket connection will send a ping every ```WEBSOCKET_PING_TIME``` seconds. |
12 | | NO_WEBSOCKET_PING | Websocket ping is only enabled by default on heroku (when the DYNO env is present), to prevent Heroku from killing idle connections. This forces a disable of the websocket ping |
13 | | SKIP_BUNDLER_REQUIRE | Disables auto-requiring files in the Gemfile. This feature is considered experimental. |
14 | | POLL_FS | In some situations, the listen gem Volt uses to track file system changes for auto-reloading will not detect changes correctly. In this situation, you can run with POLL_FS=true to have it poll the file system for changes. One place you might need this is sharing files over a network. |
15 | | DB_NAME | Same as Volt.config.db_name |
16 | | DB_HOST | Same as Volt.config.db_host |
17 | | DB_PORT | Same as Volt.config.db_port |
18 | | DB_DRIVER | Same as Volt.config.db_driver |
19 | | DB_URI | Same as Volt.config.db_uri |
20 |
21 |
--------------------------------------------------------------------------------
/en/docs/escaping.md:
--------------------------------------------------------------------------------
1 | ## Escaping
2 |
3 | When you need to use {{ and }} outside of bindings, anything in a triple mustache will be escaped and not processed as a binding:
4 |
5 | ```html
6 | {{{ bindings look like: {{this}} }}}
7 | ```
8 |
--------------------------------------------------------------------------------
/en/docs/event_bindings.md:
--------------------------------------------------------------------------------
1 | # Event Bindings
2 |
3 | In Volt views, you can bind DOM events so they call methods on the controller. Simply add an attribute named e-{eventname}:
4 |
5 | ```html
6 |
7 | ```
8 |
9 | The example above would call the alert method on the controller when the button was clicked. Volt uses jQuery under the hood, so any jQuery event is supported. Multiple events can be bound to a single tag.
10 |
11 | ```html
12 |
13 | ```
14 |
15 | You can also pass the jQuery event object that is created when the event happens by passing the ```event``` local variable into the controller.
16 |
17 | ```html
18 |
19 | ```
20 |
21 | In the controller you can get access to the jQuery event object like so:
22 |
23 | ```ruby
24 | module Main
25 | class MainController < Volt::ModelController
26 | def alert(event)
27 | event.js_event # the jQuery event
28 | end
29 | end
30 | end
31 | ```
32 |
33 | The event object will be an instance of Volt::JSEvent. It has the following methods:
34 |
35 | ### .js_event
36 |
37 | Returns the jquery event object directly. Since this is a JavaScript object and not an Opal object, you will need to use backticks or Native to work with it.
38 |
39 | ### .key_code
40 |
41 | Returns an int for the key that was pressed
42 |
43 | ### .stop!
44 |
45 | Calls stopPropagation() on the jQuery event.
46 |
47 | ### .prevent_default!
48 |
49 | Calls preventDefault() on the jQuery event.
50 |
51 | ### .target
52 |
53 | Returns the target DOM node.
54 |
--------------------------------------------------------------------------------
/en/docs/fields.md:
--------------------------------------------------------------------------------
1 | # Fields
2 |
--------------------------------------------------------------------------------
/en/docs/flash_collection.md:
--------------------------------------------------------------------------------
1 | # Flash Collection
2 |
3 | The flash collection lets you easily display information to the user on the client side. Flash contains four (default) ArrayModels, ```successes```, ```notices```, ```warnings```, and ```errors```. When these collections are appended to, the message will be displayed in a div with the classes of ```"alert alert-{{ ..collection name.. }}"```
4 |
5 | ### Example
6 |
7 | ```ruby
8 | flash._successes << "Your data has been saved"
9 | ```
10 |
11 | ```ruby
12 | flash._errors << "Unable to save because you're not on the internet"
13 | ```
14 |
15 | Strings added to any subcollection on flash will be removed after 5 seconds. By default the flash message can be clicked to clear.
16 |
17 | # Local Store Collection
18 |
19 | The ```local_store``` collection persists its data in the browser's local store.
20 |
21 | # Cookies Collection
22 |
23 | The ```cookies``` collection stores data in a browser cookie. Each assigned property gets saved to a cookie of the same name:
24 |
25 | ```ruby
26 | cookies._user_id = 520
27 |
28 | puts cookie._user_id
29 | # => "520"
30 |
31 | cookies.delete(:user_id)
32 | ```
33 |
34 | Values in the cookie collection are converted to strings. Adding expiration and other options are still on our todo list. Right now cookies default to a 1 year expiration.
35 |
36 |
37 |
--------------------------------------------------------------------------------
/en/docs/if_binding.md:
--------------------------------------------------------------------------------
1 | # If binding
2 |
3 | An ```if``` binding lets you provide basic flow control.
4 |
5 | ```html
6 | {{ if some_check? }}
7 |
render this
8 | {{ end }}
9 | ```
10 |
11 | Blocks are closed with ```{{ end }}```
12 |
13 | When the ```if``` binding is rendered, it will run the ruby code after "if". If the code is true, it will render the code in the block below. Any changes to the data in the ```if``` condition will update the rendered block.
14 |
15 | If bindings can also have ```elsif``` and ```else``` blocks.
16 |
17 | ```html
18 | {{ if condition_1? }}
19 |
34 | {{ end }}
35 | ```
36 |
--------------------------------------------------------------------------------
/en/docs/lifecycle_callbacks.md:
--------------------------------------------------------------------------------
1 | ## Lifecycle Callbacks
2 |
3 | Volt currently supports callbacks for the following serverside events:
4 |
5 | ### client_connect
6 |
7 | This event fires whenever a client starts a session on your Volt application. An example of hooking into this event might look like this:
8 | ```ruby
9 | Volt.current_app.on("client_connect") do
10 | # do something
11 | end
12 | ```
13 |
14 | ### client_disconnect
15 |
16 | This event fires whenever a client ends a session on your Volt application. An example of hooking into this event might look like this:
17 | ```ruby
18 | Volt.current_app.on("client_disconnect") do
19 | # do something
20 | end
21 | ```
22 | ### user_connect
23 | This event fires whenever a user logs in or otherwise starts a session on your Volt application with a valid session cookie. An example of hooking into this event might look like this:
24 | ```ruby
25 | Volt.current_app.on("user_connect") do |user_id|
26 | user = store.users.where(id: user_id).first.sync
27 | user._presence = "online"
28 | user._session_count += 1
29 | user._last_login = Time.now
30 | end
31 | ```
32 |
33 | ### user_disconnect
34 | This event fires whenever a user logs out, closes the browser window or otherwise navigates away from your application. You can hook into this event as follows:
35 | ```ruby
36 | Volt.current_app.on("user_disconnect") do |user_id|
37 | user = store.users.where(id: user_id).first
38 | user._presence = "offline"
39 | end
40 | ```
41 |
42 | ## Custom Events
43 | Volt also supports the ability to trigger custom server-side events. This allows you to easily expose event hooks for component gems, for example. Wherever you need to trigger a callback, you can use the following:
44 | ```ruby
45 | Volt.current_app.trigger!("custom_event_name", *args)
46 | ```
47 |
48 | A user of your component can then hook into this event as follows:
49 | ```ruby
50 | Volt.current_app.on("custom_event_name") do |*args|
51 | # do something with *args
52 | end
53 | ```
54 | Events do not need to take any arguments:
55 | ```ruby
56 | Volt.current_app.trigger!("custom_event_name")
57 |
58 | Volt.current_app.on("custom_event_name") do
59 | # do something
60 | end
61 | ```
--------------------------------------------------------------------------------
/en/docs/long_running_processes.md:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/en/docs/long_running_tasks.md:
--------------------------------------------------------------------------------
1 | # Long Running Tasks
2 |
--------------------------------------------------------------------------------
/en/docs/message_bus.md:
--------------------------------------------------------------------------------
1 | # Message Bus
2 |
3 | Volt includes a message bus interface which provides a pub/sub interface between all volt instances (server, console, runner, etc..) inside a volt cluster (any instance connected to the same database) Volt ships with a PeerToPeer message bus, but you can create or use other message bus's.
4 |
5 | The message bus is used internally in volt to push model updates between instances. The updates can then be sent to any browsers connected to the volt instance. This allows Volt to easily scale out horizontally while keeping live update push support.
6 |
7 | ## PeerToPeer Bus
8 |
9 | The default peer to peer bus uses the database to sync a list of ip's and ports for socket servers that the instances can setup. (See the generated ```config/app.rb``` code for configuration details) As long as the servers can talk to each other over the network, everything should *just work*™. (In many deployment situations, servers can talk between each other in a private cloud) If the servers only have some ports exposed, you can specify the available ports in ```config/app.rb```
10 |
11 | ## Message Bus in App Code
12 |
13 | The message bus can also be used from your app's code. The message bus provides a ```subscribe``` and ```publish``` method.
14 |
15 | **TODO: need to add more docs for using the message bus**
16 |
17 | ## Custom Message Bus
18 |
19 | You can create your own message bus implementation by implementing the ```BaseMessageBus``` class at ```lib/volt/message_bus/base_message_bus.rb``` Then you can set the ```config.message_bus.bus_name = 'name_of_class'``` where ```name_of_class``` is the underscored version of you class name. See ```base_message_bus.rb``` for details on implementing your own bus.
20 |
--------------------------------------------------------------------------------
/en/docs/middleware.md:
--------------------------------------------------------------------------------
1 | # Middleware
2 |
3 | While Volt uses websockets for database communication and tasks, it uses rack for HttpControllers and to setup the websocket connection. You can add your own middleware. In a component's config/initializers/boot.rb you can do the following:
4 |
5 | ```ruby
6 | Volt.current_app.middleware.use(SomeMiddleware)
7 | ```
8 |
9 | ```Volt.current_app.middleware``` returns a ```Volt::MiddlewareStack``` that behaves like a ```Rack::Builder``` instance. It supports the following methods:
10 |
11 | - ```use```
12 | - ```run```
13 |
14 | (more methods to reorder middleware coming soon)
15 |
16 | NOTE: Currently we don't have a way to specify where in the middleware stack middleware is loaded. (Please ping @ryanstout in gitter if you are interested in implementing this -- it should be fairly easy)
17 |
--------------------------------------------------------------------------------
/en/docs/model_classes.md:
--------------------------------------------------------------------------------
1 | ## Model Classes
2 |
3 | By default all collections use the ```Volt::Model``` class.
4 |
5 | ```ruby
6 | page._info!.class
7 | # => Volt::Model
8 | ```
9 |
10 | You can provide classes that will be loaded in place of the standard model class. Model classes should inherit from ```Volt::Model```. You can place these in any app/{component}/models folder. For example, you could add ```app/main/info.rb```:
11 |
12 | ```ruby
13 | class Info < Volt::Model
14 | end
15 | ```
16 |
17 | Now when you access any sub-collection called ```_info```, it will load as an instance of ```Info```
18 |
19 | ```ruby
20 | page._info!.class
21 | # => Info
22 | ```
23 |
24 | This lets you set custom methods and validations within collections.
25 |
26 | ## ArrayModel Classes
27 |
28 | You can also add classes in the models folder that will be loaded in place of ```Volt::ArrayModel```. Normally something like store._items would return an instance of ```Volt::ArrayModel```, however if you create a models/items.rb class that looks like the following:
29 |
30 | ```ruby
31 | class Items < Volt::ArrayModel
32 | # Custom array model code, typically this would be queries, factories, etc...
33 | end
34 | ```
35 |
36 | it will be automatically loaded when that collection is accessed.
37 |
--------------------------------------------------------------------------------
/en/docs/nil_models.md:
--------------------------------------------------------------------------------
1 | ## Nil Models
2 |
3 | As a convenience, calling something like ```page._info``` returns what's called a ```NilModel``` (assuming it isn't already initialized). NilModels are placeholders for possible future Models. NilModels allow us to bind deeply-nested values without having to initialize intermediate values.
4 |
5 | ```ruby
6 | page._info
7 | # =>
8 |
9 | page._info._name
10 | # =>
11 |
12 | page._info._name = 'Ryan'
13 | # => "Ryan"}>}>
14 | ```
15 |
16 | One gotcha with NilModels is that they are a truthy value (since only nil and false are falsy in Ruby). To make things easier, calling ```.nil?``` on a NilModel will return true.
17 |
18 | One common place we use a truthy check is in setting up default values with ```||``` (logical or). Volt provides a convenient method that does the same thing ```#or```, but that works with NilModels.
19 |
20 | Instead of:
21 |
22 | ```ruby
23 | a || b
24 | ```
25 |
26 | simply use:
27 |
28 | ```ruby
29 | a.or(b)
30 | ```
31 |
32 | Additionally, ```#and``` works the same way as ```&&```. ```#and``` and ```#or``` let you easily deal with default values involving NilModels.
33 |
34 | -- TODO: Document .true? / .false?
35 |
--------------------------------------------------------------------------------
/en/docs/provided_collections.md:
--------------------------------------------------------------------------------
1 | ## Provided Collections
2 |
3 | Above, we mentioned that Volt comes with many default collection models accessible from a controller. Each stores in a different location.
4 |
5 | | Name | Storage Location |
6 | |-------------|--------------------------------------------------------------------|
7 | | page | Temporary store that only lasts for the life of the page. |
8 | | store | Syncs data to the backend database and provides query methods. |
9 | | local_store | The browser's local storage. |
10 | | params | Stores values in the params and URL structure. Routes can be configured to change how params are shown in the URL. (See routes for more info) |
11 | | flash | Any strings assigned will be shown at the top of the page and cleared as the user navigates between pages. |
12 | | cookies | Stores each value in a cookie. You can only assign properties directly, not in sub collections. |
13 | | controller | A model for the current controller. |
14 |
15 | **More storage locations are planned.**
16 |
--------------------------------------------------------------------------------
/en/docs/provided_components.md:
--------------------------------------------------------------------------------
1 | # Provided Components
2 |
3 | Volt provides a few components to make web developers' lives easier.
4 |
5 | ## Notices
6 |
7 | Volt automatically places ```<:volt:notices />``` into views. This component shows notices for the following:
8 |
9 | 1. flash messages
10 | 2. connection status (when a disconnect happens, lets the user know why and when a reconnect will be attempted)
11 | 3. code change reloading notices (in development mode)
12 |
13 | ## Flash
14 |
15 | As part of the notices component explained above, you can append messages to any collection on the flash model.
16 |
17 | Each collection represents a different type of "flash". Common examples are ```_notices```, ```_warnings```, and ```_errors```. Using different collections allows you to change how the flash is displayed. For example, you might want ```_notices``` and ```_errors``` to show with different colors.
18 |
19 | ```ruby
20 | flash._notices << "message to flash"
21 | ```
22 |
23 | These messages will show for 5 seconds, then disappear (both from the screen and the collection).
24 |
--------------------------------------------------------------------------------
/en/docs/reactive_accessors.md:
--------------------------------------------------------------------------------
1 | ## Reactive Accessors
2 |
3 | The default ```Volt::ModelController``` proxies any missing methods to its model. Sometimes you need to store additional data reactively in the controller outside of the model. (Though often you may want to consider making another controller). In this case, you can add a ```reactive_accessor```. These behave just like ```attr_accessor``` except that the values assigned and returned are tracked reactively.
4 |
5 | ```ruby
6 | module Main
7 | class Contacts < Volt::ModelController
8 | reactive_accessor :query
9 | end
10 | end
11 | ```
12 |
13 | Now, from the view, we can bind to ```query``` while also changing in and out the model. When ```query``` is accessed it tracks that it was accessed and will rerun any computations when it changes.
14 |
--------------------------------------------------------------------------------
/en/docs/requiring_files.md:
--------------------------------------------------------------------------------
1 | # Requiring Files
2 |
3 | If a file is at, say: `my_awesome_app/app/main/mixins/my_file.rb`, where `my_awesome_app` is your application's root, and `main` is the component the file is in, you can require it in another file with:
4 |
5 | ```ruby
6 | require "main/mixins/my_file"
7 | ```
8 |
9 | That is, with the path starting at the component folder.
10 |
--------------------------------------------------------------------------------
/en/docs/routes.md:
--------------------------------------------------------------------------------
1 | # Routes
2 |
3 | Routes in Volt are very different from traditional backend frameworks. Since data is synchronized to the client using websockets, routes are used for two different reasons in Volt. Volt provides two different types of routes in the same file: ```client``` routes and http routes (```get```, ```post```, ```put```, and ```delete```)
4 |
5 | ## Client Routes
6 |
7 | Client routes are used to serialize the state of the application's ```params``` into the url in a pretty way. When a page is first loaded, the URL is parsed with the routes, and the params model's values are extracted and set from the URL. Later, if the params model is updated, the URL is updated based on the routes.
8 |
9 | This means that routes in Volt have to be able to go both from URL to params and params to URL. It should also be noted that if a link is clicked and the controller/view to render the new URL is within the current component (or an included component), the page will not be reloaded, the URL will be updated via the HTML5 history API, and the params hash will update to reflect the new URL. You can use these changes in params to render different views based on the URL.
10 |
11 | ## Http Routes
12 |
13 | To provide data to clients that need to access it via Http (a REST api for example)
14 |
--------------------------------------------------------------------------------
/en/docs/runnersprocesses.md:
--------------------------------------------------------------------------------
1 | # Runners/Processes
2 |
3 | When you have code you want to run out of the normal request cycle, you can do it one of two ways:
4 |
5 | ## 1) Runners
6 |
7 | You can put code in lib for example at ```app/main/lib/some_runner.rb```, then you can run the code by doing the following command:
8 |
9 | ```bundle exec volt app/main/lib/some_runner.rb```
10 |
11 | The runner command will load up the current app before running the code in the .rb file.
12 |
13 | ## 2) Boot the App
14 |
15 | If you need to load the volt app inside of different context. For example, using the [clockwork](https://github.com/tomykaira/clockwork) gem, or other gems that use their own command, you can boot the volt app at any time by doing:
16 |
17 | ```ruby
18 | require 'volt/boot'
19 | Volt.boot(Dir.pwd)
20 | ```
21 |
22 | ```Volt.boot``` takes a single argument, the path to the volt app directory. Be sure to run in ```bundle exec``` with the app Gemfile so that volt and its dependencies are loaded.
23 |
--------------------------------------------------------------------------------
/en/docs/sub_collections.md:
--------------------------------------------------------------------------------
1 | ## Sub Collections
2 |
3 | Like other collections, models can be nested on ```store```:
4 |
5 | ```ruby
6 | store._states.create({name: 'Montana'}).then do |montana|
7 | montana._cities << {name: 'Bozeman'}
8 | montana._cities << {name: 'Helena'}
9 | end.then do
10 | store._states.create({name: 'Idaho'}).then do |idaho|
11 | idaho._cities << {name: 'Boise'}
12 | idaho._cities << {name: 'Twin Falls'}
13 | end
14 | end
15 | ```
16 |
17 | Then we can see the models we created:
18 | ```ruby
19 | store._states
20 | # => #, #]>
21 | ```
22 | Next we can check our first state to see what cities it contains. Since ```.first``` returns a promise, calling ```._cities``` on it will also return a promise.
23 |
24 | ```ruby
25 | store._states.first._cities
26 | # => #, #]>>
27 | ```
28 |
29 | You can also create a Model first and then insert it:
30 |
31 | ```ruby
32 | montana = Volt::Model.new({name: 'Montana'})
33 |
34 | montana._cities.create({name: 'Bozeman'})
35 | montana._cities.create({name: 'Helena'})
36 |
37 | store._states.create(montana)
38 | # => #>
39 | ```
40 |
--------------------------------------------------------------------------------
/en/docs/tag_attributes.md:
--------------------------------------------------------------------------------
1 | # Tag Arguments/Attributes
2 |
3 | Like other html tags, Volt tags can be passed attributes. These attributes are then converted into an object that is passed to the initialize method of the controller. The standard Volt::ModelController's initialize will then assign the object to the ```attrs``` property which can be accessed with ```#attrs```. This makes it easy to access attributes passed in.
4 |
5 | ```html
6 | <:Body>
7 |
15 | ```
16 |
17 | Instead of passing in individual attributes, you can also assign the controllers model object with the ```model``` attribute and it will be set as the model for the controller.
18 |
19 | ```html
20 | <:Body>
21 |
22 | {{ _todos.each do |todo| }}
23 | <:todo model="{{ todo }}" />
24 | {{ end }}
25 |
34 | ```
35 |
--------------------------------------------------------------------------------
/en/docs/tags.md:
--------------------------------------------------------------------------------
1 | # Tags
2 |
3 | Tags (formerly called controls) let you render a view/controller similar to how you would with a view binding. The main difference is you can pass in attributes as arguments.
4 |
5 | Tags start with a ```:``` (colon) to differentiate them from normal html tags. Like normal html tags, they should be closed.
6 |
7 | ```html
8 | <:tag_name />
9 | ```
10 |
11 | or
12 |
13 | ```html
14 | <:tag_name>
15 | ```
16 |
17 | Refer to the View Binding section to see how tags lookup their associated view files. The above has the same lookup as ```{{ view "tag_name" }}```. Doing ```<:blog:comments />``` is the same as ```{{ view "blog/comments" }}```
18 |
19 | A tag loads the same as a template, loading the controller, calling the action method (if one exists), and rendering the view. In the next subchapters you will learn to:
20 |
21 | - Pass attributes into tags
22 | - yield inside tags
23 | - trigger events in tags and handle them.
24 |
25 |
--------------------------------------------------------------------------------
/en/docs/tasks.md:
--------------------------------------------------------------------------------
1 | # Tasks
2 |
3 | Sometimes you need to explicitly execute some code on the server. Volt solves this problem through *tasks*. You can define your own tasks by inheriting from ```Volt::Task```. Ruby files in a ```tasks``` folder, which end with ```_tasks.rb```, will be required automatically.
4 |
5 | ```ruby
6 | # app/main/tasks/logging_tasks.rb
7 |
8 | class LoggingTasks < Volt::Task
9 | def log(message)
10 | puts message
11 | end
12 | end
13 | ```
14 |
15 | Volt will automatically generate wrappers for you on the client side which will return a promise.
16 |
17 | *Note that the classes on the server side use instance methods while the wrapper classes represent those methods as class methods*. For more information on using promises in Ruby see [here](http://opalrb.org/blog/2014/05/07/promises-in-opal/).
18 |
19 | ```ruby
20 | class Contacts < Volt::ModelController
21 | def hello
22 | promise = LoggingTasks.log('Hello World!')
23 | end
24 | end
25 | ```
26 |
27 | You can use the ```#then``` method of the returned promise to get the result of the call. You can use the ```#fail``` method on the promise to get any thrown errors.
28 |
29 | ```ruby
30 | MathTasks.add(23, 5).then do |result|
31 | # result should be 28
32 | alert result
33 | end.fail do |error|
34 | puts "Error: #{error}"
35 | end
36 | ```
37 |
38 | ## Timeout
39 |
40 | Tasks by default run with a 60 second timeout. You can change the global timeout for all tasks by setting ```config.worker_timeout``` in ```config/app.rb```. You can also change the timeout per task class by calling the ```timeout``` method in the class:
41 |
42 | ```ruby
43 | class SampleTask < Volt::Task
44 | timeout 200
45 |
46 | # ...
47 | end
48 | ```
49 |
50 | You can also set the timeout to 0 to disable the timeout.
51 |
52 | ## Cookies
53 |
54 | You can set new cookies using the ```cookies``` repo from inside of tasks. Any cookie set will be sent and set on the client. NOTE: You can not read cookies from tasks, only set. (This was a performance decision)
55 |
--------------------------------------------------------------------------------
/en/docs/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Volt uses rspec by default for testing, however you can change out rspec for another testing framework by removing the rspec related gems in your projects Gemfile. Most generators generate stub specs to help you get started.
4 |
5 | The convention in a Volt project is to mirror your app directory inside of spec, so that each component gets its own folder inside of specs. If you ```require 'spec-helper'``` in your spec file, you can run ```bundle exec rspec``` to run all tests, or you can include the path to a specific spec. (Note: Volt does not use rake out of the box, so specs are normally run with rspec directly)
6 |
7 | # Helpers
8 |
9 | Volt provides methods inside of specs to access the ```page``` and ```store``` collection. Due to a naming conflict with capybara, the method to access ```page``` inside of rspec is ```the_page``` (we're working on a way around the conflict).
10 |
11 | You can access ```store``` by calling ```store``` in a spec. If ```store``` is called, after the spec runs, the database will be cleared. This makes it so no work needs to be done in the database per spec, except when the store is actually used.
12 |
13 | # Integration Specs
14 |
15 | Volt provides rspec and capybara out of the box. You can test directly against your models, controllers, etc... or you can do full integration tests via [Capybara](https://github.com/jnicklas/capybara).
16 |
17 | To make a spec run in capybara, simply add ```type: :feature``` to a description block:
18 |
19 | ```ruby
20 | describe "browser specs", type: :feature do
21 | it ...
22 | end
23 | ```
24 |
25 | The integration tests don't run by default, to run Capybara tests, you need to specify a driver. The following drivers are currently supported:
26 |
27 | 1. Phantom (via poltergeist)
28 |
29 | ```BROWSER=phantom bundle exec rspec```
30 |
31 | 2. Firefox
32 |
33 | ```BROWSER=firefox bundle exec rspec```
34 |
35 | 3. IE - coming soon
36 |
37 | Chrome is not supported due to [this issue](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges) with ChromeDriver. Feel free to go [here](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges) and pester the chromedriver team to fix it.
38 |
--------------------------------------------------------------------------------
/en/docs/url.md:
--------------------------------------------------------------------------------
1 | # Url
2 |
3 | In volt you can access information about the url via the ```url``` method, which is available in controllers. The url has the following methods, which currently are getters only (setters coming soon.)
4 |
5 | - scheme
6 | - host
7 | - port
8 | - path
9 | - query
10 | - fragment
11 |
12 | Each method will reactively update when the url changes.
13 |
--------------------------------------------------------------------------------
/en/docs/url_for_and_url_with.md:
--------------------------------------------------------------------------------
1 | # url_for and url_with
2 |
3 | If you need to generate urls using the routes, you can call ```url_for``` or ```url_with```
4 |
5 | ## url_for
6 |
7 | ```url_for``` takes a hash of params and returns a url based on the routes and passed in params.
8 |
9 | Below is an example of doing a link to change ```?page=``` on the query string. This example assumes routes exist for a todos controller.
10 |
11 | ```ruby
12 | url_for(controller: 'todos', page: 5)
13 | # => 'http://localhost:3000/todos?page=5'
14 | ```
15 | You can also create urls for [HTTP Controllers](http_controllers.md) by setting the corresponding method as first argument.
16 |
17 | ```ruby
18 | url_for(:get, controller: 'todos', action: 'index')
19 | # => 'http://localhost:3000/api/todos
20 | ```
21 |
22 | ## url_with
23 |
24 | ```url_with``` is like ```url_for```, but merges in the current params. In the example below, assume params is ```{controller: 'todos'}```
25 |
26 | ```ruby
27 | url_with(page: 5)
28 | # => 'http://localhost:3000/todos?page=5'
29 | ```
30 |
31 | Because ```url_with``` is a controller method, it can also be accessed in views:
32 |
33 | ```html
34 | page 5
35 | ```
36 |
--------------------------------------------------------------------------------
/en/docs/views.md:
--------------------------------------------------------------------------------
1 | # Views
2 |
3 | Views are files with an .html extension that can include ruby code to control how they are rendered. Volt compiles the views on the server before sending them to the client. Views might look something like this:
4 |
5 | ```html
6 |
7 | <:Title>
8 | My Page
9 |
10 | <:Body>
11 |
My Page
12 |
13 |
Welcome {{ Volt.current_user.name }}!
14 | ```
15 |
16 | # Sections
17 |
18 | Volt views have their own simple templating language. They can be broken up into sections. Sections start with a section header. A section header looks like the following:
19 |
20 | ```html
21 | <:Body>
22 | ```
23 |
24 | Section headers should start with a capital letter so as not to be confused with [tags](#tags). Section headers do not use closing tags. If no section header is provided, the ```:Body``` section is assumed.
25 |
26 | Sections help you split up different parts of the same content (title and body usually), but within the same file.
27 |
28 | # Bindings
29 |
30 | In Volt, views are written in a simple template language where ruby can be inserted anywhere between ```{{``` and ```}}```. Volt lets you use the usual flow control statements in views (```if```, ```elsif```, ```else```, and ```each```). You can also render other views using the ```view``` binding.
31 |
32 | # Controller Backing
33 |
34 | While Volt is more of a Model View ViewModel (MVVM) framework than an MVC framework, we have opted to use the controller terminology - this just means we use the term 'Controller' instead of 'ViewModel'.
35 |
36 | Any method call or instance variable lookup in a view runs in the context of such a controller.
37 |
38 | If you have a view at ```app/main/views/index/index.html``` it will load the controller at ```app/main/controller/index_controller.rb```.
39 |
--------------------------------------------------------------------------------
/en/docs/volt_helpers.md:
--------------------------------------------------------------------------------
1 | ## Logging
2 |
3 | Volt provides a helper for logging. Calling ```Volt.logger``` will return an instance of the Ruby logger. See [here](http://www.ruby-doc.org/stdlib-2.1.3/libdoc/logger/rdoc/Logger.html) for more.
4 |
5 | An example:
6 |
7 | ```ruby
8 | Volt.logger.info("Some info...")
9 | ```
10 |
11 | You can change the logger like this:
12 |
13 | ```ruby
14 | Volt.logger = Logger.new
15 | ```
16 |
17 | ## App Configuration
18 |
19 | Like many frameworks, Volt changes some default settings based on an environment flag. You can set the Volt environment with the ```VOLT_ENV``` environment variable.
20 |
21 | All files in the app's ```config``` folder are loaded when Volt boots. This is similar to the ```initializers``` folder in Rails.
22 |
23 | Volt does its best to start with useful defaults. You can configure things, like your database and app name, in the ```config/app.rb``` file. The following are the current configuration options:
24 |
25 | | name | default | description |
26 | |-----------|---------------------------|---------------------------------------------------------------|
27 | | app_name | the current folder name | This is used internally for things like logging. |
28 | | db_driver | 'mongo' | Currently mongo is the only supported driver, more coming soon|
29 | | db_name | "#{app\_name}\_#{Volt.env} | The name of the mongo database. |
30 | | db_host | 'localhost' | The hostname for the mongo database. |
31 | | db_port | 27017 | The port for the mongo database. |
32 | | compress_deflate | false | If true, will run deflate in the app server. It's better to let something like nginx do this, though. |
33 |
--------------------------------------------------------------------------------
/en/docs/volt_internals.md:
--------------------------------------------------------------------------------
1 | # Volt Internals
2 |
--------------------------------------------------------------------------------
/en/docs/yield_binding.md:
--------------------------------------------------------------------------------
1 | # Yield Binding
2 |
3 | When using [Tags](#tags), content that is generated in the caller, can be passed into the tag definition.
4 | In other words the tag definition can refer to content of the caller, which has the same logic as
5 | a yield in ruby, but is slightly different. The simple example below demonstrates.
6 |
7 | Say you had a navigation element that you wanted to reuse, a simple list item like:
8 |
9 | ```html
10 |
15 | ```
16 |
17 | This can be turned into tag easily and we could pass both link and text in with the ```attrs```
18 | approach shown. But this would be clumsy for the span element, and can be achieved much better
19 | with the yield binding:
20 |
21 | ```html
22 | <:Nav>
23 |
28 | ```
29 |
30 | To use this tag to create the output in the beginning of the page, you would write the following:
31 |
32 | ```html
33 | <:nav href="/about">About
34 | ```
35 |
36 | In the example above, "About" will be rendered in the place of ```{{ yield }}```.
37 | In general, any content that is inside the calling tag will be rendered in place of ```yield``.
38 |
39 | Lastly if you just want to get the html content as a string, you can call ```yield_html``` in the controller. This will return a string that you can ```.watch!``` on if needed and it will re-render when the content changes.
40 |
--------------------------------------------------------------------------------
/en/getting_help/README.md:
--------------------------------------------------------------------------------
1 | # Getting Help
2 |
3 | Volt is still a work in progress, but early feedback is very much appreciated. Use the following methods to communicate with the developers, and someone will get back to you very quickly:
4 |
5 | - **If you need help**: post on [stackoverflow.com](http://www.stackoverflow.com). Be sure to tag your question with `voltrb`.
6 | - **If you found a bug**: post on [github issues](https://github.com/voltrb/volt/issues)
7 | - **If you have an idea or need a feature**: post on [github issues](https://github.com/voltrb/volt/issues)
8 | - **If you want to discuss Volt**: [chat on gitter](https://gitter.im/voltrb/volt), someone from the volt team is usually online and happy to help with anything.
9 |
--------------------------------------------------------------------------------
/en/getting_help/can_i_use_opal_gems.md:
--------------------------------------------------------------------------------
1 | # Can I use opal gems?
2 |
3 | Yes. Opal has its own way of including gems. This usually means you need to require the gem itself in your MRI code before it will be added to the opal load path.
4 |
5 | For example with opal/browser, you can simply add the following to config/app.rb
6 |
7 | ```ruby
8 | require 'opal/browser'
9 | ```
10 |
11 | Then in a controller where you want to use opal-browser, add the following to the top of the file:
12 |
13 | ```ruby
14 | if RUBY_PLATFORM == 'opal'
15 | require 'browser'
16 | end
17 | ```
18 |
--------------------------------------------------------------------------------
/en/getting_help/does_volt_support_haml,_slim,_etc.md:
--------------------------------------------------------------------------------
1 | # Does Volt support Haml, Slim, etc...
2 |
3 | **Update** - Yes, volt supports slim, thanks to @ASnow: https://github.com/asnow/volt-slim
4 |
5 | We don't have HAML support yet. Below is a brief explination of what is involved and what it takes.
6 |
7 | This is a common question for those coming from Rails because in Rails is easy to add support for more template languages. In Rails a template render takes in a path to a template and an object to be used as the context. Then the result generated is **a string**.
8 |
9 | In volt however, templates are first rendered to a compiled template that can be sent to the client side. Templates aren't _rendered to a string_, they are _built to a target_. Volt currently supports two targets:
10 |
11 | - the actual dom
12 | - a string (for rendering parts of templates in tag attributes, or e-mail's, or server side html)
13 |
14 | When rendering to the actual dom, Volt tracks the locations of the rendered DOM nodes, so when any data used to render those nodes changes, the DOM can be updated without re-rendering the whole DOM. This makes for fast efficient DOM updates with a minimum number of DOM operations and no need for any diffing like in other frameworks. Volt's bindings know how to update with the least number of DOM updates.
15 |
16 | ## So what does it take to render Haml, etc...
17 |
18 | Its not too bad, but out of the box gems like haml and slim aren't designed for what Volt needs. Any template language that can compile to Volt's compiled template format can be used. The compiled template format is ruby code (that gets compiled to the client via Opal). It consists of html and bindings. The html has placeholders (currently special html comments) that show where the binding should be rendered. The bindings are ruby Procs that setup instance of the bindings. (Volt::EachBinding, Volt::ContentBinding, Volt::AttributeBinding, Volt::IfBinding, and Volt::EventBinding)
19 |
20 | To make haml or slim compile, someone will need to modify slim or haml to produce the Volt compiled template format (instead of pre-rendered html) It shouldn't be that hard, but its not trivial. If you are interested, hit up @ryanstout on our [gitter](https://gitter.im/voltrb/volt).
21 |
--------------------------------------------------------------------------------
/en/getting_help/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | * [What runs on the Client vs Server?](what_runs_on_the_client_vs_server.md)
4 | * [Can I use jQuery? (or other DOM manipulating JS)](can_i_use_jquery_or_other_dom_manipulating_js.md)
5 |
--------------------------------------------------------------------------------
/en/getting_help/is_keeping_a_persistent_connection_open_a_performance_problem.md:
--------------------------------------------------------------------------------
1 | # Is keeping a persistent connection open a performance problem?
2 |
3 | So I used to do social gaming years ago and we kept a socket connection (via flash, since this was pre-websocket) open for each of our users. We at one point had 500,000 users online at once and our dispatch server (the one that kept the connections to the client open) was barely pushing 10% cpu. The server was built with eventmachine on MRI. Eventmachine on linux can use what's called the e-poll linux api. It basically schedules all io relating to sockets. Its the same thing nginx is built on for example. Using that you can scale to millions of connections on a single machine. (Google the C10k problem, or check out http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html for example) So long story short, running an evented server should prove no problem to keep connections open and manage them. Actually pushing the io is really easy. The one issue you might run into is if you have too many people subscribed to the same large amount of data, you might end up maxing out a network connection on large updates. We're working on a distributed data bus (similar to the one in vert.x) to allow you to easily distribute updates and connections across many machines. In both thin and the goliath server, you get a thread per rack request, but all websocket requests can run in a single thread and use the evented io to manage dispatch. I would also like to integrate with vert.x on the jruby side to do similar things.
4 | Hopefully that answers some questions. There are a lot of difficult problems for Volt to solve, but I don't believe that handling the persistent connections is one of them. For the most part that's a solved problem thanks to epoll and the O(1) linux scheduler.
5 |
6 | - Ryan
7 |
--------------------------------------------------------------------------------
/en/getting_help/what_browsers_does_volt_support.md:
--------------------------------------------------------------------------------
1 | # What browsers does Volt support?
2 |
3 | Since Firefox and Chrome have been auto-updating for a while, you're probably wondering about IE. The good news is Opal supports IE way back (the rumor is IE6, because one of the core devs needs support for it). While Volt only targets IE10 at the moment, we're working on a volt-ie8to9 gem that will add back support for IE 8-9. The only thing missing at the moment is a fallback for websockets.
4 |
5 | ## Limited Features
6 |
7 | There are a few features of Volt that only work on certain browsers.
8 |
9 | 1) Binding on hidden fields.
10 | To bind on hidden fields, the browser needs mutation observer events. These are only supported in >=IE11. There is a polyfill that can be used to support IE8-10, which we will be bundling into a gem. Check back here soon.
11 |
--------------------------------------------------------------------------------
/en/getting_help/why_use_underscore_accessors_instead_of_[property].md:
--------------------------------------------------------------------------------
1 | # Why use underscore accessors instead of [:property]
2 |
3 | A common question about Volt is why we use underscore accessors. There are a few reasons that have more to do with the requirements for setting/getting properties on a model without predefining the names of the properties.
4 |
5 | ## 1. Preventing Error Swallowing
6 |
7 | While it would be possible to simply allow any method to be set on a model:
8 |
9 | ```ruby
10 | item = Volt::Model.new
11 | item.name = 'Ryan'
12 | ```
13 |
14 | The problem is in Volt we need a property that hasn't been assigned to return nil. This makes it easy to bind a property without setting it up, and the binding can handle the nil as it sees fit. (for example a bound ```value``` on a text field might assume nil means an empty string) The problem with the above is if we were to call a method that didn't exist, it will always return nil instead of returning a ```NoMethodError```
15 |
16 | ```ruby
17 | item = Volt::Model.new
18 | item.savr! # => nil
19 | # ^ meant to type .save!
20 | ```
21 |
22 | ## 2. Keeping it short/Avoiding self
23 |
24 | Accessing model properties is a really common thing. While some JS frameworks use something like ```.set```/```.get```, this is a very commmon complaint about those frameworks that it is a lot of extra typing just to access a property. In Volt we want to keep it short. Ruby would allow us to do something like:
25 |
26 | ```ruby
27 | item = Volt::Model.new
28 | item[:name] # => nil
29 | ```
30 |
31 | While that works really well in controller code, in Volt when using a ModelController, you will often want to set the controller's model to a model instance. In that case, you have to do the following in your bindings (due to the way ruby works):
32 |
33 | ```html
34 |
35 | ```
36 |
37 | While this works, we feel that it doesn't read as easy and is something that can be a source of confusion.
38 |
39 | While the _property syntax is not common in ruby, its easy to get used to. Once you do it saves a lot of typing/reading. If the above hasn't convinced you its the best solution, keep in mind you can always just use [fields](/docs/models.md).
40 |
--------------------------------------------------------------------------------
/en/introduction/README.md:
--------------------------------------------------------------------------------
1 | # Goals
2 |
3 | Volt has the following goals:
4 |
5 | 1. Developer happiness
6 | 2. Eliminate duplication by sharing of code between the client and server
7 | 3. Automatic data syncing between client and server
8 | 4. Built apps as nested components. Components can be shared (via gems), or run as services.
9 | 5. Concurrency. Volt provides tools to simplify concurrency.
10 | 6. Intelligent asset management
11 | 7. Secure (shouldn't need to be said, but it does)
12 | 8. Fast, light, and scalable
13 | 9. Understandable code base
14 |
15 | # Road Map
16 |
17 | Many of the core Volt features are implemented. We still have a bit to go before 1.0, most of it involving models.
18 |
19 | 1. Data Provider API - an abstraction to make it easy to create adaptors for any database/datastore.
20 | 2. Oauth Integration - the plan is to integrate omniauth to make it easy to use any omniauth provider.
21 | 3. Migrations to add database indexes from Volt
22 | 4. Server Side HTML Prerendering - the plan is to allow the server to render the html for a page first, then tie in the compiled client side ruby once the code is loaded.
23 |
--------------------------------------------------------------------------------
/en/roadmap/README.md:
--------------------------------------------------------------------------------
1 | # Roadmap
2 |
3 | While open source projects are tricky to predict timewise, below is the roadmap of features we want to roll out in the next six months.
4 |
5 | | Feature | Target Date | Details |
6 | |------------------------------------|------------- |----------------------------------------|
7 | | sql support/reworked model layer | October 15th | (includes eager loading) |
8 | | "Auto-rest" support | September 20th | (@jfaher said its basically done |
9 | | query restrictions API |September 30th| |
10 | | Time helpers | Nov 1st | Basically done, depends on Opal 0.9 |
11 | | has_many through & polymorphic queries | November 30st | |
12 | | omniauth integration into volt-user-templates | Dec 1st | |
13 |
14 | Further out we have some larger features planned that I don't have a timeline for yet.
15 |
16 | - RubyMotion support - I would like to integrate RubyMotion so you can use Volt (and its data syncing) to build Native iOS/Android apps as part of your Volt app. This will probably mean having a "web" folder for html views, and an "ios", and "android" folder for rubymotion code to bind between controllers and native widgets.
17 |
18 | - Server side rendering - The goal is to have the server be able to pre-render pages, so the page could be displayed before the JS loads. When the JS loads, it would hook into the bindings. The server side rendering part is basically done, what we have left to do is make it tie into the bindings that were rendered on the server. There is also a lot of edge cases we need to handle (such as components that use inline JS and do DOM manipulation). The current plan is to have a way to mark a component as not server-side friendly, then that component's rendering would be delayed.
19 |
20 |
--------------------------------------------------------------------------------
/en/tutorial/README.md:
--------------------------------------------------------------------------------
1 | # Tutorial
2 |
3 | This guide will take you through creating a basic web application in Volt. This tutorial assumes a basic knowledge of Ruby and web development.
4 |
5 | ## Setup
6 |
7 | First, let's install Volt and create an empty app. Be sure you have ruby (>2.1.0) and rubygems installed.
8 |
9 | Next install the volt gem:
10 |
11 | gem install volt
12 |
13 | Using the volt gem, we can create a new project:
14 |
15 | volt new sample_project
16 |
17 | This will setup a basic project in the sample_project folder. We can ```cd``` into the folder and run the server:
18 |
19 | bundle exec volt server
20 |
21 | Lastly, we can access the Volt console with:
22 |
23 | bundle exec volt console
24 |
25 |
--------------------------------------------------------------------------------
/es/README.md:
--------------------------------------------------------------------------------
1 | # Introducción
2 |
3 | Volt es un web framework donde tu código Ruby corre tanto en el servidor como en el cliente (por medio de [opal](https://github.com/opal/opal)). El DOM se actualiza al mismo tiempo que el usuario interactúa con la página. El estado de la página puede ser guardado en el url. Si el usuario ingresa la url directamente, el HTML se carga primero en el servidor (para una carga mas rápida y una mejor indexación en motores de búsqueda) para luego ser manejada en el cliente.
4 |
5 | En lugar de sincronizar los datos entre el cliente y el servidor por http, Volt usa una conexión permanente. Cuando los datos son actualizados en un cliente específico estos cambios se reflejan tanto en la base como en otros clientes (sin ninguna configuración adicional).
6 |
7 | El HTML se escribe en un lenguaje de templating donde puedes ingresar código ruby entre ```{{``` y ```}}```. Volt usa programación reactiva para propagar automáticamente los actualizaciones al DOM (o cualquier parte del código que necesita saber cuando los datos han sido cambiados). Cuando una parte del DOM cambia, Volt actualiza solo los nodos que necesitan ser actualizados.
8 |
9 | Adicional a la documentación, puedes obtener mas ayuda en los siguientes videos:
10 |
11 | - [Volt Todos Example](https://www.youtube.com/watch?v=KbFtIt7-ge8)
12 | - [What Is Volt in 6 Minutes](https://www.youtube.com/watch?v=P27EPQ4ne7o)
13 | - [Pagination Example](https://www.youtube.com/watch?v=1uanfzMLP9g)
14 | - [Routes and Templates](https://www.youtube.com/watch?v=1yNMP3XR6jU)
15 | - [Isomorphic App Development - RubyConf 2014](https://www.youtube.com/watch?v=7i6AL7Walc4)
16 |
17 | O revisa las aplicaciones de demostración:
18 | - https://github.com/voltrb/todomvc
19 | - https://github.com/voltrb/blog5
20 |
21 |
--------------------------------------------------------------------------------
/es/book.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "title": "Volt Introduction and Docs",
4 | "description": "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.\n\nInstead 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).\n\nPages HTML is written in a handlebars-like template language. 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."
5 | }
6 |
--------------------------------------------------------------------------------
/es/contributing/README.md:
--------------------------------------------------------------------------------
1 | # Como Contribuir
2 |
3 | Quieres contribuir? Genial! Tenemos la documentación completa de como contribuir
4 | aquí:
5 | https://github.com/voltrb/volt/blob/master/CONTRIBUTING.md
6 |
--------------------------------------------------------------------------------
/es/contributing/component_gems.md:
--------------------------------------------------------------------------------
1 | # Gemas de Componentes
2 |
3 | NOTA: Esta sección todavía está en proceso
4 |
--------------------------------------------------------------------------------
/es/deployment/apache.md:
--------------------------------------------------------------------------------
1 | # Apache
2 |
3 | Apache no cuenta con soporte para Websockets, [mira este post](https://github.com/phusion/passenger/issues/1202).
4 | Por este motivo tendrás que hacer forward-proxy con [thin](http://code.macournoyer.com/thin/)
5 |
6 | Para correr Volt con apache necesitarás los siguientes módulos habilitados:
7 | - [mod_proxy](http://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
8 | - [mod_proxy_wstunnel](http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
9 |
10 | ```
11 |
12 | ServerName YOUR.SERVER.NAME
13 | DocumentRoot /PATH/TO/APP_NAME/public
14 |
15 | ProxyRequests Off
16 | ProxyPreserveHost On
17 |
18 | # a2enmod proxy_wstunnel
19 | ProxyPass /socket ws://localhost:3001/socket
20 | ProxyPassReverse /socket ws://localhost:3001/socket
21 | ProxyPass / http://localhost:3001/
22 | ProxyPassReverse / http://localhost:3001/
23 |
24 | LogLevel warn
25 |
26 | CustomLog ${APACHE_LOG_DIR}/APP_NAME_access.log combined
27 | ErrorLog ${APACHE_LOG_DIR}/APP_NAME_error.log
28 |
29 | ```
30 |
31 | Instala esto como un servicio de thin: `thin install` y agrega la siguiente configuración dentro de `/var/thin/volt.yml`
32 |
33 | ```
34 | ---
35 | chdir: "/PATH/TO/APP_NAME"
36 | environment: production
37 | address: 0.0.0.0
38 | port: 3001
39 | timeout: 30
40 | log: "/var/log/thin-expenses.log"
41 | pid: tmp/pids/thin.pid
42 | max_conns: 1024
43 | max_persistent_conns: 100
44 | require: []
45 | wait: 30
46 | threadpool_size: 20
47 | servers: 1
48 | daemonize: true
49 | ```
50 |
51 | Luego de agregar estas instrucciones debes correr thin con el siguiente comando `sudo /etc/init.d/thin start`
52 |
--------------------------------------------------------------------------------
/es/deployment/cloud9.md:
--------------------------------------------------------------------------------
1 | # Cloud9
2 |
3 | Para empezar en cloud9, crea una imagen de rails (esta imagen contiene lo que necesitamos). Una vez encendido, elimina el proyecto:
4 |
5 | ```rm -rf *```
6 |
7 | Primero configuremos mongo (revisa la documentación completa para mongo aquí)
8 |
9 | Inicia una nueva terminal y digita lo siguiente:
10 |
11 | ```
12 | mkdir data
13 | echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest "$@"' > mongod
14 | chmod a+x mongod
15 | ```
16 |
17 | Luego puedes correr mongod con el siguiente comando:
18 |
19 | ```
20 | ./mongod
21 | ```
22 |
23 | Luego instalaremos Volt.
24 |
25 | ```gem install volt```
26 |
27 | Y crearemos un nuevo proyecto:
28 |
29 | ```volt new projectname```
30 |
31 | ingresamos al proyecto:
32 |
33 | ```cd projectname```
34 |
35 | Y arrancamos el servidor (en Cloud9, debes pasar el puerto y la ip del ENV)
36 |
37 | ```bundle exec volt server -p $PORT -b $IP```
38 |
39 | Cloud9 proveé un subdominio para cada aplicación, para visitar la aplicación has click en ```Preview``` y luego en ```Preview Running Application```
40 |
41 | En la versión gratuita de Cloud9, tu base mongo se apagará periódicamente (no de forma correcta).Puedes crear una base Mongo gratuita en www.mongolab.com. Crea una cuenta gratuita en mongolab y luego añade lo siguiente en config/app.rb
42 |
43 | ```
44 | config.db_driver = 'mongo'
45 | config.db_name = (config.app_name + '_' + Volt.env.to_s)
46 | if ENV['MONGOHQ_URL'].present?```
47 | config.db_uri = ENV['MONGOHQ_URL'] # you will have to set this on Cloud9.
48 | else
49 | config.db_host = 'localhost'
50 | config.db_port = 27017
51 | end
52 | ```
53 |
54 | NOTA: Si alguien puede crear una imagen customizada de Volt para cloud9, por favor hágamelo saber en el chat de gitter. Gracias!
55 |
--------------------------------------------------------------------------------
/es/deployment/docker.md:
--------------------------------------------------------------------------------
1 | ## Contenedor Docker para Volt
2 |
3 | Crea un Dockerfile en tu aplicación de Volt con lo siguiente:
4 |
5 | ```
6 | FROM otzy007/voltframework
7 | ```
8 |
9 | Luego de esto puedes crear tu imagen de Docker
10 |
11 | ```
12 | FROM otzy007/voltframework
13 | ```
14 |
15 | Y correrlo:
16 |
17 | ```
18 | docker run --name my-volt-app -p 3000:3000 -d my-volt-app
19 | ```
20 |
21 | Ahora ya puedes ver tu aplicación en esta dirección: http://localhost:3000
22 |
--------------------------------------------------------------------------------
/es/deployment/heroku.md:
--------------------------------------------------------------------------------
1 | ## Heroku
2 |
3 | Edita tu ```Gemfile``` y especifica tu versión de ruby, por ejemplo:
4 |
5 | ```ruby
6 | source 'https://rubygems.org'
7 |
8 | ruby "2.1.3" # specify a Ruby version
9 |
10 | gem 'volt', ~> '0.9.0'
11 | ```
12 |
13 | Añade un ```Procfile``` que use Thin
14 |
15 | web: bundle exec thin start -p $PORT -e $RACK_ENV
16 |
17 | Configura tu conección a la base de datos en ```config/app.rb```, a continuación podemos ver un ejemplo para conectar con MongoHQ. Tienes que cambiarlo para el proveedor que usarás.
18 | [MongoLab](http://www.mongolab.com) es una alternativa gratuita.
19 |
--------------------------------------------------------------------------------
/es/docs/arraymodel_events.md:
--------------------------------------------------------------------------------
1 | ## Eventos ArrayModel
2 |
3 | Los ArrayModels lanzan eventos cuando los datos son actualizados. Actualmente
4 | los modelos pueden generar dos eventos ```added``` y ```removed```. Por ejemplo:
5 |
6 | ```ruby
7 | page._items.on('added') { puts 'item added' }
8 | page._items << 1
9 | # => item added
10 |
11 | page._items.on('removed') { puts 'item removed' }
12 | page._items.delete_at(0)
13 | # => item removed
14 | ```
15 |
16 | Esto es usado internamente para los each bindings, pero puedes usarlo
17 | en tu propio código.
18 |
19 | NOTA: Los eventos de ArrayModel son por ahora un 'feature' no oficial de
20 | volt. No hay garantías de que funcione bien en todos los casos
21 |
--------------------------------------------------------------------------------
/es/docs/automatic_model_conversion.md:
--------------------------------------------------------------------------------
1 | # Conversión automática del Modelo
2 |
3 | ## Hash -> Model
4 |
5 | Por conveniencia, cuando colocamos un hash dentro de un modelo este será convertido automáticamente en otro modelo. Los modelos son similares a los hashes, pero estos tienen características adicionales como persistencia y el lanzamiento de eventos reactivos.
6 |
7 | ```ruby
8 | user = Volt::Model.new
9 | user._name = 'Ryan'
10 | user._profile = {
11 | twitter: 'http://www.twitter.com/ryanstout',
12 | dribbble: 'http://dribbble.com/ryanstout'
13 | }
14 |
15 | user._name
16 | # => "Ryan"
17 | user._profile._twitter
18 | # => "http://www.twitter.com/ryanstout"
19 | user._profile.class
20 | # => Volt::Model
21 | ```
22 |
23 | Puedes obtener un hash de vuelta llamando al método `#to_h` en el Modelo.
24 |
25 | ## Array -> ArrayModel
26 |
27 | Los arrays dentro de un modelo se transforman automáticamente en un instancia de ArrayModel. Los ArrayModels tienen las mismas características de un array normal, con la diferencia de que estos pueden estar enlazados con los datos de backend y generar eventos reactivos.
28 |
29 | ```ruby
30 | model = Volt::Model.new
31 | model._items << {name: 'item 1'}
32 | model._items.class
33 | # => Volt::ArrayModel
34 |
35 | model._items[0].class
36 | # => Volt::Model
37 | model._items[0]
38 | ```
39 |
40 | Para convertir un Volt::Model o un Volt::ArrayModel en una estructura normal de Ruby podemos llamar los métodos .to_h o to_a respectivamente. Para convertirlo a un objeto de JavaScript (y usarlo en código Javascript), puedes llamar al método `#to_n`(to native)
41 |
42 | ```ruby
43 | user = Volt::Model.new
44 | user._name = 'Ryan'
45 | user._profile = {
46 | twitter: 'http://www.twitter.com/ryanstout',
47 | dribbble: 'http://dribbble.com/ryanstout'
48 | }
49 |
50 | user._profile.to_h
51 | # => {twitter: 'http://www.twitter.com/ryanstout', dribbble: 'http://dribbble.com/ryanstout'}
52 |
53 | items = Volt::ArrayModel.new([1,2,3,4])
54 | # => #
55 |
56 | items.to_a
57 | # => [1,2,3,4]
58 | ```
59 |
60 | Puedes obtener un array normal invocando .to_a en un Volt:ArrayModel.
61 |
--------------------------------------------------------------------------------
/es/docs/beforeafter_actions.md:
--------------------------------------------------------------------------------
1 | # Filtros Before/After
2 |
3 | A menudo en los controladores, cuando estos son renderizados, existe código que se necesita correr antes o después de ciertas acciones. Volt nos provee acciones ```before_action``` y ```after_action```. Puedes configurar estas acciones de la siguiente manera:
4 |
5 | ```ruby
6 | module Main
7 | class MainController < Volt::ModelController
8 | before_action :english_only
9 |
10 | # require login is a method in Volt::ModelController
11 | before_action :require_login, only: :about
12 |
13 | def index
14 | # Setup index...
15 | end
16 |
17 | def about
18 | # Setup about...
19 | end
20 |
21 | # Redirect somewhere if they aren't in an english locale
22 | # (just as an example)
23 | def english_only
24 | if `navigator.language` != 'en-US'
25 | redirect_to '/translations'
26 | stop_chain # see below
27 | end
28 | end
29 | end
30 | end
31 | ```
32 |
33 | # stop_chain
34 |
35 | Es muy común crear un redirección desde un filtro `before`. Si no quieres continuar con el renderizado puedes llamar al método ```stop_chain``` en una acción y el renderizado se detendrá.
36 |
37 | ```stop_chain``` lanza una excepción que será tomada por el filtro, por lo que ningun código podra correr despues de que ```stop_chain``` se ejecute.
38 |
--------------------------------------------------------------------------------
/es/docs/callbacks_and_actions.md:
--------------------------------------------------------------------------------
1 | # Acciones de Controlador
2 |
3 | Cuando un binding o un tag renderiza una vista lo primero que se carga es el controlador. Existen cuatro callbacks para el renderizado. La acción tiene el mismo nombre que la vista, por lo que si renderizas la página ```about.html``` , la acción se llamará ```about```. Simplemente tienes que crear el método correcto en el controlador y será llamado en el momento indicado.
4 |
5 | | nombre acción | descipción |
6 | |-----------------------|-----------------------------------------------------|
7 | | callbacks before_action | Si ```stop_chain``` es invocado la acción no será llamada y se parará la ejecución. |
8 | | ```{action}``` | Es llamado antes de que cualquier cosa se renderize, aquí puedes inicializar los datos que necesites |
9 | | callbacks after_action | las acciones after_action's no pueden llamar a ```stop_chain``` (al ser llamados solo lanzan una excepción) |
10 | | ```{action}_ready``` | Se lo llama despues de que las vistas se han cargado. Puedes correr código en el cual tienes que manipular directamente el DOM. por ejemplo para configurar código jQuery (componentes bootstrap) |
11 | | ```before_{action}_remove``` | Es llamado antes de que la vista se removida. Aqui puedes limpiar enlaces que tengas con el DOM. |
12 | | ```after_{action}_remove``` | Llamado despues de que la vista es removida del DOM. Puedes limpiar cualquier cosa que necesite ser limpiada en el controlador. |
13 |
14 | La mayor parte del tiempo lo único que necesitarás es el método de la acción para configurar el controlador, modelo, etc...
15 |
--------------------------------------------------------------------------------
/es/docs/channel.md:
--------------------------------------------------------------------------------
1 | # Channel
2 |
3 | Los controladores proveen un método llamado `#channel` que puede ser usado para obtener el status de la conexión con el backend. Los métodos de acceso a 'Channel' son reactivos.
4 |
5 | | method | description |
6 | |-------------|-----------------------------------------------------------|
7 | | connected? | devuelve 'true' si esta conectado con el backend |
8 | | status | posibles valores: :opening, :open, :closed, :reconnecting |
9 | | error | el mensaje de error para la última conección fállida |
10 | | retry_count | el número de intentos de reconexión que se han hecho sin una conexión exitosa |
11 | | reconnect_interval | el tiempo que ha pasado desde el último intento de reconexión (en segundos) |
12 |
13 | A veces necesitas correr un código específico cuando el cliente se conecta/desconecta del servidor. En un controlador puedes hacer lo siguiente:
14 |
15 | ```ruby
16 | channel.on('connect') do
17 | .. connected ..
18 | end
19 |
20 | channel.on('disconnect') do
21 | .. disconnect ..
22 | end
23 | ```
24 |
--------------------------------------------------------------------------------
/es/docs/component_gems.md:
--------------------------------------------------------------------------------
1 | # Gemas de Componente
2 |
3 | Los competentes pueden ser fácilmente compartidos por medio de una gema de Ruby. Volt provee métodos scaffold para crear gemas de componente. En una carpeta ( no dentro de un proyecto volt) digita lo siguiente: ```volt generate gem {component_name}```. Esto creará los archivos necesarios para la nueva gema. Toma en cuenta que las gemas de componentes tendrán un prefijo ```volt-``` para que se puedan localizar fácilmente en github o rubygems. Usa la convención de usar underscores para los espacios en el nombre de la gema
4 |
5 | Ahora ya puedes usar tu componente agregando lo siguiente a tu Gemfile:
6 |
7 | ```ruby
8 | gem 'volt-{component_name}', path: '/path/to/folder/with/component'
9 | ```
10 |
11 | Una ves que la gema este lista puedes publicarla en rubygems con el siguiente comando:
12 |
13 | ```
14 | rake release
15 | ```
16 |
17 | Borra la opción ```path:``` en el gemfile si quieres usar directamente la versión guardada en rubygems.
18 |
--------------------------------------------------------------------------------
/es/docs/content_binding.md:
--------------------------------------------------------------------------------
1 | # Binding de contenido
2 |
3 | El binding mas básico es el siguiente:
4 |
5 | ```html
6 |
Hello {{ name }}
7 | ```
8 |
9 | El contenido de estos bindings corren código ruby entre ```{{``` y ```}}```, luego renderiza el valor retornado. Cuando los datos en un binding de contenido dependen de los cambios, el binding correrá nuevamente y actualizará el texto. El texto dentro del binding es escapado por defecto.
10 |
--------------------------------------------------------------------------------
/es/docs/debugging.md:
--------------------------------------------------------------------------------
1 | # Debugging
2 |
3 | ## Sourcemaps
4 |
5 | Volt (por medio de Opal) tiene sourcemaps habilitado por default. en Chrome y en Firefox, cuando tienes un stack trace en devtool, este nos mostrará el nombre/linea del archivo en ruby. Puedes hacer click en el nombre del archivo para ingresar al archivo Ruby original directamente en devtools. Puedes crear tus propios breakpoints como lo harías normalmente en JavaScript. También se está tratando de integrar irb en el navegador.
6 |
7 | Por default, a partir de la versión 0.9.5.pre3 de Volt, sourcemaps esta activado automáticamente en el ambiente de desarrollo. Puedes deshabilitarlo mediante el siguiente comando:
8 |
9 | ```MAPS=false bundle exec volt server```
10 |
11 | Por razones de rendimiento, el código de Opal y Volt no es mapeado. Esto nos ahorra algo de tiempo en la carga de páginas. Puedes habilitar mapping para todos los archivos mediante el siguiente comando:
12 |
13 | ```MAPS=all bundle exec volt server```
14 |
15 | ### Framework Blackboxing
16 |
17 | Cuando usas sourcemaps, generalmente verás muchos archivos extras en tu stack trace mientras hagas debugging. Framework Blackboxing te permitará tratar el código de Volt y Opal como código nativo, por lo que será ignorado. Puedes añadir el siguiente check para tener blackbox en Volt y Opal.
18 |
19 | ```
20 | /assets/volt/volt/app\.js$|/assets/js/volt_watch\.js$|/assets/js/volt_js_polyfills\.js$
21 | ```
22 |
--------------------------------------------------------------------------------
/es/docs/dependencies.md:
--------------------------------------------------------------------------------
1 | # Dependencias
2 |
3 | También puedes usar [tags](#tags) y llamarlos a través de componentes. Para hacer esto debes hacer `require` del componente dentro del componente desde el cual lo vas a usar. Esto puedes hacerlo mediante el archivo ```config/dependencies.rb```. Solo agrega
4 |
5 | ```ruby
6 | component 'component_name'
7 | ```
8 |
9 | dentro del archivo.
10 |
11 | Las dependencias actuan como un ```require``` normal de ruby, pero para añadir componentes.
12 |
13 | A veces necesitarás incluir un JS externo de un componente. Para hacer esto, simplemente has lo siguiente en el archivo dependencies.rb:
14 |
15 | ```ruby
16 | javascript_file 'http://code.jquery.com/jquery-2.0.3.min.js'
17 | css_file '//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css'
18 | ```
19 |
20 | Nota: De todas maneras, jquery y bootstrap están añadidos por default en Volt
21 |
--------------------------------------------------------------------------------
/es/docs/each_binding.md:
--------------------------------------------------------------------------------
1 | # Each binding
2 |
3 | Para iterar objetos, puedes usar ```.each```
4 |
5 | ```html
6 | {{ _items.each do |item| }}
7 |
{{ item }}
8 | {{ end }}
9 | ```
10 |
11 | Si ```_items``` es un arreglo, el bloque se renderizará para cada item en el arreglo, definiendo ```item``` como el elemento actual del arreglo.
12 |
13 | También puedes llamar al método ```.each_with_index``` para llamar al índice actual dentro del bloque
14 |
15 | ```html
16 | {{ _items.each_with_index do |item, index| }}
17 |
{{ index }}. {{ item }}
18 | {{ end }}
19 | ```
20 |
21 | Para el arreglo ```['one', 'two', 'three']``` se imprimirá lo siguiente:
22 |
23 | 0. one
24 | 1. two
25 | 2. three
26 |
27 | Puedes usar ```{{ index + 1 }}``` para eliminar el cero y obtener el índice correcto
28 |
29 | Cuando los items son añadidos o removidos de un array, el binding ```each``` automáticamente actualizará el DOM.
30 |
--------------------------------------------------------------------------------
/es/docs/environment_options.md:
--------------------------------------------------------------------------------
1 | # Opciones de Environment
2 |
3 | Adicionalmente a las opciones dentro de config/app.rb, algunas opciones específicas
4 | pueden ser configuradas con variables de instancia.
5 |
6 | | Name | Description |
7 | |------------------------|-----------------------------------------|
8 | | VOLT_ENV | Cambia el valor de Volt.env, el cual es usado para controlar varias partes de la aplicación. |
9 | | RACK_ENV | También es usado para cambiar el valor de Volt.env |
10 | | NO_MESSAGE_BUS | Deshabilita el bus de mensajes. Esto previene que las actualizaciones se propaguen entre las instancias de Volt, pero puede ser útil para debugging |
11 | | NO_FORKING | El "Servidor de Forking" es usado en desarrollo en MRI para permitir el reload automático de codigo. (Crea un proceso hijo para conecciones, el cual se elimina y posteriormente se crea uno nuevo cuando hay cambios en el código) |
12 | | WEBSOCKET_PING_TIME | Sirve para enviar un ping a la conexión de websocket cada cierta cantidad de segundos. |
13 | | NO_WEBSOCKET_PING | Hacer ping al websocket esta habilitado solo en heroku (cuando el DYNO env esta present), para prevenir que Heroku mate las conexiones inactivas, esta variable puede forzar a que no se realize el ping al websocket |
14 | | SKIP_BUNDLER_REQUIRE | Deshabilita la carga automática de archivos del Gemfile. Esta característica todavía es experimental. |
15 | | POLL_FS | En algunas situaciones, Volt puede fallar al momento de chequear que archivos han sido cambiados para hacer auto-reloading. En esta situación puedes usar POLL_FS=true para que recolecte información directamente del sistema de archivos. Un uso común de esta variable es cuando necesitas compartir archivos a través de una red |
16 | | DB_NAME | Lo mismo que Volt.config.db_name |
17 | | DB_HOST | Lo mismo que Volt.config.db_host |
18 | | DB_PORT | Lo mismo que Volt.config.db_port |
19 | | DB_DRIVER | Lo mismo que Volt.config.db_driver |
20 | | DB_URI | Lo mismo que Volt.config.db_uri |
21 |
22 |
--------------------------------------------------------------------------------
/es/docs/escaping.md:
--------------------------------------------------------------------------------
1 | ## Escape de Bindings
2 |
3 | Cuando necesites usar {{ and }} afuera de los bindings, cualquier texto
4 | en una llave triple no se tomara en cuenta y no sera procesado como un binding
5 |
6 | ```html
7 | {{{ bindings look like: {{this}} }}}
8 | ```
9 |
--------------------------------------------------------------------------------
/es/docs/event_bindings.md:
--------------------------------------------------------------------------------
1 | # Bindings de Eventos
2 |
3 | En las vistas se puedes enlazar eventos DOM y llamarlos en el controlador. Simplemente añade un atributo como e-{eventname}:
4 |
5 | ```html
6 |
7 | ```
8 |
9 | El código anterior llamará una método de alerta en el controlador cuando se haga click en el botón. Volt usa jQuery por debajo, se pueden usar todos los métodos disponibles en jQuery. Múltiples eventos pueden estar atados a un solo tag.
10 |
11 | ```html
12 |
13 | ```
14 |
15 | También puedes usar eventos de objeto jQuery, los cuales son creados cuando un evento ocurre pasando la variable local ```event``` dentro del controlador.
16 |
17 | ```html
18 |
19 | ```
20 |
21 | Dentro del controlador puedes acceder al evento de objeto jQuery de la siguiente manera:
22 |
23 | ```ruby
24 | module Main
25 | class MainController < Volt::ModelController
26 | def alert(event)
27 | event.js_event # the jQuery event
28 | end
29 | end
30 | end
31 | ```
32 |
33 | ### .js_event
34 |
35 | Retorna el evento objeto de jQuery directamente. Al ser estos objetos JavaScript nativos y no objetos de Opal tendrás que usar backticks o Native para utilizarlos.
36 |
37 | ### .key_code
38 |
39 | Retorna un entero para la tecla que ha sido presionada
40 |
41 | ### .stop!
42 |
43 | Llama al método stopPropagation() en el evento jQuery
44 |
45 | ### .prevent_default!
46 |
47 | Llama al método preventDefault() en el evento jQuery
48 |
49 | ### .target
50 |
51 | Retorna el nodo del DOM target.
52 |
--------------------------------------------------------------------------------
/es/docs/fields.md:
--------------------------------------------------------------------------------
1 | # Campos
2 |
--------------------------------------------------------------------------------
/es/docs/flash_collection.md:
--------------------------------------------------------------------------------
1 | # Colección Flash
2 |
3 | La colección flash te permite mostrar información al usuario(del lado del cliente) de manera mas fácil. Flash contiene 4 ArrayModel por default : ```successes``` , ```notices```, ```warnings``` y ```errors```. Cuando se añaden mensajes, estos son mostrados en un div con las clases respectivas ```"alert alert-{{ ..collection name.. }}"```
4 |
5 | ### Ejemplo
6 |
7 | ```ruby
8 | flash._successes << "Your data has been saved"
9 | ```
10 |
11 | ```ruby
12 | flash._errors << "Unable to save because you're not on the internet"
13 | ```
14 |
15 | Los strings añadidos a cualquier subcolección de flash serán removidos después de 5 segundos. El usuario puede remover el mensaje flash haciendo simplente haciendo click.
16 |
17 | # Colección de Store Local
18 |
19 | La colección ```local_store``` guarda los datos en el store local del browser
20 |
21 | # Colección de cookies
22 |
23 | La colección ```cookies``` guarda los datos en una cookie del browser. Cada propiedad asignada es guardada en el cookie de la misma forma:
24 |
25 | ```ruby
26 | cookies._user_id = 520
27 |
28 | puts cookie._user_id
29 | # => "520"
30 |
31 | cookies.delete(:user_id)
32 | ```
33 |
34 | Los valores en la colección cookie son convertidos a strings. Todavía no se puede añadir un tiempo de expiración para estos datos. Por ahora los cookies tiene un tiempo de expiración de un año.
35 |
--------------------------------------------------------------------------------
/es/docs/if_binding.md:
--------------------------------------------------------------------------------
1 | # Binding If
2 |
3 | El binding ```if``` te da un control básico del flujo en el código.
4 |
5 | ```html
6 | {{ if some_check? }}
7 |
render this
8 | {{ end }}
9 | ```
10 |
11 | Los bloques se cierran por medio de ```{{ end }}```.
12 |
13 | Cuando se llega al binding ```if``` este verificará si el predicado es verdadero. Si el código retorna ```true``` este ejecutará el código dentro del siguiente bloque. Cualquier cambio en los datos dentro de la condición de ```if``` actualizará a su vez el código cargado.
14 |
15 | Los bindings if tambien pueden incluir bloques ```elsif``` y ```else```.
16 |
17 | ```html
18 | {{ if condition_1? }}
19 |
condition 1 true
20 | {{ elsif condition_2? }}
21 |
condition 2 true
22 | {{ else }}
23 |
neither true
24 | {{ end }}
25 | ```
26 |
27 | ## Unless
28 |
29 | Unless también se encuentra incluido en Volt.
30 |
31 | ```html
32 | {{ unless some_check? }}
33 |
render this when some_check? is false
34 | {{ end }}
35 | ```
36 |
--------------------------------------------------------------------------------
/es/docs/lib.md:
--------------------------------------------------------------------------------
1 | # Lib
2 |
3 | **Nota:** Esta sección todavía esta en construcción
4 |
5 | Las gemas del Gemfile no son cargadas automáticamente en Volt. Este decisión se tomó por distintos motivos.
6 |
7 | 1. Incrementa el tiempo de carga, especialmente en aplicaciones muy grandes (una de las cosas mas criticadas en rails). Las gemas de componentes incluidas en el archivo dependencies.rb tendrá las partes de la
8 | aplicación incluidas por default.
9 | 2. De esta manera no se carga código que no vamos a utilizar.
10 |
11 | Revisa [5 razones para evitar Bundler.require](http://myronmars.to/n/dev-blog/2012/12/5-reasons-to-avoid-bundler-require)
12 |
13 | Si de todas manera quieres incluir los archivos para las gemas automáticamente, puedes incluir lo siguiente al principio de tu archivo ```config/app.rb```.
14 |
15 | ```ruby
16 | Bundler.setup
17 | ```
18 |
--------------------------------------------------------------------------------
/es/docs/message_bus.md:
--------------------------------------------------------------------------------
1 | # Bus de Mensajes
2 |
3 | Volt incluye una interfaz para el bus mensajes, el cual provee una interfase para la publicación/subscripción entre todas las instancias de volt (servidor, consola, runner, etc...) dentro de un cluster volt (cualquier instancia conectada a la misma base de datos). Volt incluye un bus de mensajes PeerToPeer , pero puedes crear o usar otro buses de mensajes.
4 |
5 | El bus de mensajes es usado internamente en volt para agregar actualizaciones del modelo entre las instancias. Luego estas actualizaciones pueden ser enviadas a cualquier browser que se encuentre conectada a una instancia de volt. Esto permite a volt escalar horizontalmente mientras se mantiene el soporte para realizar nuevas actualizaciones.
6 |
7 | # Bus PeerToPeer
8 |
9 | El bus peer to peer (el cual es usado por default) usa la base de datos para sincronizar una lista con los ips y puertos (para los servidores de sockets) que las instancias pueden configurar (Mira el archivo generado ```config/app/rb``` para mas obtener mas detalles de la configuración). Mientras el servidor pueda comunicarse con el resto a traves de la red, todo debería funcionar correctamente (En muchas situaciones de deployment, los servidores pueden comunicarse entre ellos en una una nube privada). Si los servidores solo tienen algunos puertos expuestos, puedes especificar los puertos habilitados en ```config/app.rb```
10 |
11 | ## El Bus de mensajes en el código de la Aplicación
12 |
13 | El Bus de mensajes también puede ser usado desde tu aplicación. Este proveé un método ```suscribe``` y un método ```publish```.
14 |
15 | ## Bus de mensajes customizado
16 |
17 | Puedes crear tu propio bus de mensajes implementando la clase ```BaseMessageBus``` en ```lib/volt/message_bus/base_message_bus.rb```. Luego puedes configurar el nombre del bus así: ```config.message_bus.bus_name = 'name_of_class'``` , donde ```name_of_class``` en la versión (con underscores) del nombre de tu clase. Mira ```base_message_bus.rb``` para mas detalles de como implementar tu propio bus de mensajes.
18 |
--------------------------------------------------------------------------------
/es/docs/middleware.md:
--------------------------------------------------------------------------------
1 | # Middleware
2 |
3 | Aunque Volt usa websockets para comunicarse con la base y para tasks, este también usa rack para los HttpControllers y para configurar la conexión de websocket. Puedes añadir tu propio middleware si así lo deseas . En el archivo config/initializers/boot.rb del componente puedes hacer lo siguiente:
4 |
5 | ```ruby
6 | Volt.current_app.middleware.use(SomeMiddleware)
7 | ```
8 |
9 | ```Volt.current_app.middleware``` retorna un ```Volt::MiddlewareStack``` que se comporta como una instancia ```Rack::Builder```. Este soporta los siguientes métodos:
10 |
11 | - ```use```
12 | - ```run```
13 |
14 | (métodos para reorganizar el middleware se agregarán muy pronto)
15 |
--------------------------------------------------------------------------------
/es/docs/model_classes.md:
--------------------------------------------------------------------------------
1 | ## Clases del Modelo
2 |
3 | Por default todas las colecciones usan la clase ```Volt::Model```.
4 |
5 | ```ruby
6 | page._info!.class
7 | # => Volt::Model
8 | ```
9 |
10 | Puedes creer tu propia clase base para tus modelos. Estas clases modelo deben heredar de ```Volt::Model```. Puedes guardarlas dentro del directorio app/{component}/models del componente respectivo. Por ejemplo, puedes añadir ```app/main/info.rb```:
11 |
12 | ```ruby
13 | class Info < Volt::Model
14 | end
15 | ```
16 |
17 | Ahora cuando accedas a cualquier subcolección llamando ```_info``` esta se cargará como una instancia de ```Info```
18 |
19 | ```ruby
20 | page._info!.class
21 | # => Info
22 | ```
23 |
24 | Esto nos permite crear métodos customizados y validaciones de colecciones.
25 |
--------------------------------------------------------------------------------
/es/docs/nil_models.md:
--------------------------------------------------------------------------------
1 | ## Modelos Nil
2 |
3 | Por conveniencia, al llamar a un método como ```page._info``` este nos retornará un ```NilModel``` (asumiendo que la variable aún no ha sido inicializada). Los modelos nil o NilModels nos permite enlazar métodos con muchas anidaciones sin tener que inicializar primero los valores intermedios.
4 |
5 | ```ruby
6 | page._info
7 | # =>
8 |
9 | page._info._name
10 | # =>
11 |
12 | page._info._name = 'Ryan'
13 | # => "Ryan"}>}>
14 | ```
15 |
16 | Uno de los incovenientes de NilModels es que son tratados como un valor verdadero (como valores truthy), ya que solo nil y false son tratados como valores 'falsy' en Ruby. Para facilitar un poco las cosas NilModel contiene un método ```nil?``` el cual siempre retorna true.
17 |
18 | Un uso muy común de la verificación de valores 'truthy' es al momento de crear valores por defecto por medio de ```||``` (or lógico). Volt proveé un método que hace exactamente lo mismo: ```#or``` el cual funciona con NilModels.
19 |
20 | Reemplaza esto:
21 |
22 | ```ruby
23 | a || b
24 | ```
25 |
26 | Con esto:
27 |
28 | ```ruby
29 | a.or(b)
30 | ```
31 |
32 | Adicionalmente, ```#and``` funciona igual que ```&&```
33 |
--------------------------------------------------------------------------------
/es/docs/provided_collections.md:
--------------------------------------------------------------------------------
1 | ## Colecciones Proporcionadas
2 |
3 | Hemos mencionado que Volt nos provee con varios tipos de colecciones, las cuales se pueden acceder desde el controlador.
4 |
5 | | Nombre | Ubicación de Almacenamiento |
6 | |-------------|--------------------------------------------------------------------|
7 | | page | Almacenamiento temporal de la página, esta disponible mientras no se cierre la página actual. |
8 | | store | Sincroniza los datos con la base de datos de backend y nos provee métodos de consulta. |
9 | | local_store | Almacenamiento temporal del browser. |
10 | | params | Guarda los valores en params y dentro de la estructura del URL. Las rutas pueden ser configuradas para cambiar como son mostradas en el URL. (Mira la documentación de rutas para mayor información) |
11 | | flash | Cualquier string asignado a esta colección sera mostrada en la parte superior de la página, y luego será eliminada al cambiar de página. |
12 | | cookies | Guarda cada valor en un cookie. Puedes asignar propiedades directamente, pero no lo puedes hacer dentro de subcolecciones |
13 | | controller | Un modelo para el controlador usado. |
14 |
15 | Se agregarán mas colecciones muy pronto.
16 |
--------------------------------------------------------------------------------
/es/docs/provided_components.md:
--------------------------------------------------------------------------------
1 | # Componentes por default
2 |
3 | Volt provee algunos componentes para construir nuestra aplicación de manera muy fácil.
4 |
5 | ## Notificaciones
6 |
7 | Volt automáticamente agrega ```<:volt:notices />``` en nuestras vistas. Este componente muestra notificaciones para los siguientes escenarios:
8 |
9 | 1. Mensajes flash
10 | 2. Estado de la conecciones (cuando ocurre una desconección, este muestra una alerta explicándonos el porque y el tiempo en el que se intentará una reconección)
11 | 3. Notifica reloading por cambios en el código (solo en el modo de desarrollo)
12 |
13 | ## Flash
14 |
15 | Como parte del componente de notificaciones, explicado anteriormente, puedes agregar a este cualquier mensaje dentro de cualquier colección.
16 |
17 | Cada colección representa un tipo de notificación flash. Por ejemplo puedes usar ```_notices``` y ```_errors``` para mostrar diferentes colores en las notificaciones.
18 |
19 | ```ruby
20 | flash._notices << "message to flash"
21 | ```
22 |
23 | Estos mensajes se mostrarán por 5 segundos, luego desaperecerán (de la pantalla y de la memoria).
24 |
--------------------------------------------------------------------------------
/es/docs/reactive_accessors.md:
--------------------------------------------------------------------------------
1 | ## Accessors Reactivos
2 |
3 | ```Volt::ModelController``` envia todos los llamados a métodos desconocidos al modelo asignado. A veces necesitas un store adicional (que maneje los datos reactivamente por fuera del modelo, aunque si vas a hacer esto tal vez debas considerar el crear otro controlador). En este caso, puedes añadir un ```reactive_accesor```. Este se comporta como un ```attr_accessor```, con la excepción de que los datos asignados retornan los datos reactivamente.
4 |
5 | ```ruby
6 | module Main
7 | class Contacts < Volt::ModelController
8 | reactive_accessor :query
9 | end
10 | end
11 | ```
12 |
13 | Ahora, desde la vista puedes enlazar el método ```query``` y también puedes cambiar los elementos del modelo enlazado al controlador. Cuando ```query``` es accedido el controlador toma esto en cuenta y realiza los cambios necesarios para las vistas enlazadas.
14 |
--------------------------------------------------------------------------------
/es/docs/requiring_files.md:
--------------------------------------------------------------------------------
1 | # Requiriendo Archivos
2 |
3 | Si tienes un archivo llamado `my_awesome_app/app/main/mixins/my_file.rb`, donde `my_awesome_app` es la dirección root de tu aplicación, y `main` es el componente en el cual se encuentra nuestro archivo, podemos añadirlo en otro archivo de la siguiente forma:
4 |
5 | ```ruby
6 | require "main/mixins/my_file"
7 | ```
8 |
9 | El path debe comenzar con el nombre de la carpeta del componente
10 |
--------------------------------------------------------------------------------
/es/docs/routes.md:
--------------------------------------------------------------------------------
1 | # Rutas
2 |
3 | Las rutas en Volt son muy diferentes a las de otros frameworks. Ya que los datos son sincronizados con el cliente por medio de websockets, las rutas son usadas por dos razones. Volt provee dos tipos de rutas en un mismo archivo: rutas ```client``` y rutas http (```get```, ```post```, ```put```y ```delete```)
4 |
5 | ## Rutas Cliente
6 |
7 | Para serializar el estado de una aplicación en el url de una manera lógica, cuando una página es cargada por primera vez, el url es parseado con las rutas y los valores para los parametros del modelo son tomados y configurados desde el URL. Luego, si los parámetros del modelo son actualizados el URL es actualizado en base a las rutas.
8 |
9 | Esto significa que las rutas en Volt tienen que ser capaces de ir desde el URL a los params y desde los params al URL. También hay que tomar en cuenta que si se accede a un link y el controlador/vista para cargar la nueva url se encuentra en el componente actual (o en un componente incluido), la página no se reiniciará, la URL se actualizará por medio de HTML5 history API, y el hash de parámetros se actualizará para reflejar el nuevo URL. Puedes usar los cambios en los parametros para cargar distintas vistas basadas en un URL.
10 |
11 | ## Rutas HTTP
12 |
13 | Con el objetivo de proveer datos a los clientes estos deben ser accedidos por medio de Http (un api REST, por ejemplo).
14 |
15 |
--------------------------------------------------------------------------------
/es/docs/runnersprocesses.md:
--------------------------------------------------------------------------------
1 | # Runners/Processes
2 |
3 | Si quieres correr código fuera de un request normal, puedes hacerlo de estas 2 formas:
4 |
5 | ## 1) Runners
6 |
7 | Puedes poner código dentro de la carpeta lib, por ejemplo en ```app/main/lib/some_runner.rb```, luego puedes correr el código
8 | dentro de este archivo por medio del siguiente comando:
9 |
10 | ```bundle exec volt app/main/lib/some_runner.rb```
11 |
12 | Este comando levantará la aplicación antes the correr el código dentro del archivo .rb
13 |
14 | ## 2) Arranca la aplicación con 'boot'
15 |
16 | Si necesitar corrar la aplicación dentro de otro contexto. Por ejemplo, para correr una gema como [clockwork](https://github.com/tomykaira/clockwork),
17 | la cual tiene sus propios comandos, puedes correrla por medio del siguiente código:
18 |
19 | ```ruby
20 | require 'volt/boot'
21 | Volt.boot(Dir.pwd)
22 | ```
23 | ```Volt.boot``` toma un solo argumento: el path donde se encuentra la aplicación volt. Acuerdate de usar el comando ```bundle exec``` y
24 | de tener el archivo Gemfile para poder inicializar todas las dependencias.
25 |
--------------------------------------------------------------------------------
/es/docs/sub_collections.md:
--------------------------------------------------------------------------------
1 | ## Colecciones Anidadas
2 |
3 | Como otras colecciones, los modelos pueden anidarse dentro de ```store```:
4 |
5 | ```ruby
6 | store._states.create({name: 'Montana'}).then do |montana|
7 | montana._cities << {name: 'Bozeman'}
8 | montana._cities << {name: 'Helena'}
9 | end.then do
10 | store._states.create({name: 'Idaho'}).then do |idaho|
11 | idaho._cities << {name: 'Boise'}
12 | idaho._cities << {name: 'Twin Falls'}
13 | end
14 | end
15 | ```
16 |
17 | Luego podremos observar los modelos que se han creado:
18 |
19 | ```ruby
20 | store._states
21 | # => #, #]>
22 | ```
23 | ```ruby
24 | store._states
25 | # => #, #]>
26 | ```
27 |
28 | Despues podemos ver nuestro primer estado para observar que ciudades contiene
29 |
30 | ```ruby
31 | store._states.first._cities
32 | # => #, #]>>
33 | ```
34 |
35 | Tambien puedes crear el modelo primero para luego insertar la ciudad:
36 |
37 | ```ruby
38 | montana = Volt::Model.new({name: 'Montana'})
39 |
40 | montana._cities.create({name: 'Bozeman'})
41 | montana._cities.create({name: 'Helena'})
42 |
43 | store._states.create(montana)
44 | # => #>
45 | ```
46 |
--------------------------------------------------------------------------------
/es/docs/tag_attributes.md:
--------------------------------------------------------------------------------
1 | # Argumentos/Atributos de los tags
2 |
3 | Como en otros tags html, también puedes pasar atributos a los tags de Volt. Estos atributos se convierten en un objeto que es pasado como primer argumento al método initialize del controller. El método initialize estándar de Volt::ModelController asignará el objeto a la variable ```attrs``` el cual puede ser accedida por medio del método ```#attrs```. Esto hace mucho mas fácil el acceder a los atributos guardados.
4 |
5 | ```html
6 | <:Body>
7 |
15 | ```
16 |
17 | En lugar de pasar los atributos individualmente, también puedes pasar el objeto modelo del controlador al atributo ```model``` del tag.
18 |
19 | ```html
20 | <:Body>
21 |
22 | {{ _todos.each do |todo| }}
23 | <:todo model="{{ todo }}" />
24 | {{ end }}
25 |
34 | ```
35 |
--------------------------------------------------------------------------------
/es/docs/tags.md:
--------------------------------------------------------------------------------
1 | # Tags
2 |
3 | Tags (formalmente llamados controls) te permiten renderizar una vista/controlador de forma similar a como se renderiza un view binding. La principal diferencia es que con tags puedes enviar atributos como argumentos.
4 |
5 | Los tags empiezan con un ```:``` (colon) para diferenciarlos de tags html normales. Al igual que los tags html normales, estos deben ser cerrados.
6 |
7 | ```html
8 | <:tag_name />
9 | ```
10 |
11 | o
12 |
13 | ```html
14 | <:tag_name>
15 | ```
16 |
17 | Revisa la sección bindings de vistas para saber como los tags buscan las vistas asociadas. El código anterior tiene el mismo lookup que ```{{ view "tag_name" }}```. Llamar al método ```<:blog:comments />``` es equivalente a ```{{ template "blog/comments" }}```
18 |
19 | Un tag se carga igual que un template, llamando al controlador, llamando al método de la acción (si existe) y cargando la vista. También puedes pasar atributos a los tags
20 |
--------------------------------------------------------------------------------
/es/docs/tasks.md:
--------------------------------------------------------------------------------
1 | # Tasks
2 |
3 | A veces necesitas ejecutar explícitamente una parte del código en el servidor. Volt nos permite hacer esto por medio de tasks. Puedes definir tus propios tasks heredando de la clase ```Volt::Task```. Los archivos de Ruby dentro de la carpeta ```tasks``` (y que terminen en ```_tasks.rb```), serán cargados automáticamente.
4 |
5 | ```ruby
6 | # app/main/tasks/logging_tasks.rb
7 |
8 | class LoggingTasks < Volt::Task
9 | def log(message)
10 | puts message
11 | end
12 | end
13 | ```
14 |
15 | Volt crea automáticamente wrappers de estos tasks en el cliente, los cuales retornarán un promise.
16 |
17 | *Hay que tomar en cuenta que el código de los tasks en el cliente usan métodos de instancia mientras las clases wrapper representan estos métodos como métodos de clase*, para mas información de como usar promesas revisa el código de Opal [Aqui](http://opalrb.org/blog/2014/05/07/promises-in-opal/).
18 |
19 | ```ruby
20 | class Contacts < Volt::ModelController
21 | def hello
22 | promise = LoggingTasks.log('Hello World!')
23 | end
24 | end
25 | ```
26 |
27 | Puedes usar el método ```#then``` de la promesa para obtener el resultado de llamar a ese método. Puedes usar ```#fail``` en la promesa para obtener los errores obtenidos.
28 |
29 | ```ruby
30 | MathTasks.add(23, 5).then do |result|
31 | # result should be 28
32 | alert result
33 | end.fail do |error|
34 | puts "Error: #{error}"
35 | end
36 | ```
37 |
--------------------------------------------------------------------------------
/es/docs/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Volt usa rspec para las pruebas, pero puedes cambiar a otra librería de testing removiendo todo las gemas relacionadas con rspec en el Gemfile de tu proyecto. La mayoría de generadores crearán tests de prueba para que puedes empezar a escribir tus propios tests.
4 |
5 | La convención en Volt es tener la misma estructura del directorio app en la carpeta spec, así cada componente tendrá su carpeta dentro de spec. Si cargas el archivo spec-helper ```require 'spec-helper'``` en tu test, puedes correr ```bunde exec rspec``` para correr todos tus tests o puedes incluir el path para correr un test específico. (Nota: Volt no usa rake por defecto, por lo que los tests se corren con directamente con rspec).
6 |
7 | # Helpers
8 |
9 | Volt nos proveé con métodos dentro de los specs para acceder a la página ```page``` y a la colección ```store```. Por un conflicto con capybara el método para acceder al método ```page``` dentro de rspec es ```the_page``` (estamos trabajando en una solución para esto).
10 |
11 | Puedes acceder al store llamando al método ```store``` en un spec. Si ```store``` es llamado después de correr los tests la base de datos se limpiará automáticamente. Esto facilita el no tener que configurar el limpiado de la base de datos para cada test.
12 |
13 | # Pruebas de Integración
14 |
15 | Volt provee rspec y capybara por default. Puedes también probar tus modelos, controladores, etc.... o puedes crear pruebas de completas de integración por medio de capybara.
16 |
17 | Para hacer que un spec corra en capybara, simplemente añade
18 | ```type: :feature``` dentro del bloque 'describe' del test
19 |
20 | ```ruby
21 | describe "browser specs", type: :feature do
22 | it ...
23 | end
24 | ```
25 |
26 | Las pruebas de integración no corren por default, para correr los tests de capybara tienes que especificar un driver. Los siguientes drivers son soportados:
27 |
28 | 1. Phantom (por medio de poltergeist)
29 |
30 | ```BROWSER=phantom bundle exec rspec```
31 |
32 | 2. Firefox
33 |
34 | ```BROWSER=firefox bundle exec rspec```
35 |
36 | 3. IE - muy pronto
37 |
38 | Chrome no es soportado por este [problema](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges)h en ChromeDriver.
39 |
40 |
--------------------------------------------------------------------------------
/es/docs/url.md:
--------------------------------------------------------------------------------
1 | # Url
2 |
3 | En Volt, puedes acceder a información sobre el url por medio del método ```url```, el cual puedes usarlo en los controladores. El url tiene los siguientes métodos, los cuales son getters (métodos setters serán implementados muy pronto)
4 |
5 | - scheme
6 | - host
7 | - port
8 | - path
9 | - query
10 | - fragment
11 |
12 | Cada método se actualizará reactivamente cuando el url cambie.
13 |
--------------------------------------------------------------------------------
/es/docs/url_for_and_url_with.md:
--------------------------------------------------------------------------------
1 | # url_for y url_with
2 |
3 | Si necesitas generar urls usando los routes, puedes llamar a los métodos ```url_for``` o ```url_with```
4 |
5 | ## url_for
6 |
7 | ```url_for``` toma un hash de parámetros y retorna un url basado en las rutas
8 |
9 | El siguiente es un ejemplo de como crear un link para cambiar ```?page=``` en el string del query. Este ejemplo asume que la ruta existe para el controller 'todos'.
10 |
11 | ```ruby
12 | url_for(controller: 'todos', page: 5)
13 | # => 'http://localhost:3000/todos?page=5'
14 | ```
15 |
16 | ## url_with
17 |
18 | ```url_with``` es parecido a ```url_for``` con la diferencia de que combina los parámetros que existen actuálmente en una página. En el ejemplo siguiente se asume que los parametros son ```{controller: 'todos'}```
19 |
20 | ```ruby
21 | url_with(page: 5)
22 | # => 'http://localhost:3000/todos?page=5'
23 | ```
24 |
25 | Por el hecho de que ```url_with``` es un método de controlador, este también se puede acceder dentro de la vista:
26 |
27 | ```html
28 | page 5
29 | ```
30 |
--------------------------------------------------------------------------------
/es/docs/views.md:
--------------------------------------------------------------------------------
1 | # Vistas
2 |
3 | Las vistas son archivos .html que pueden incluir código ruby para controlar como renderizamos la pagina. Volt compila los archivos de vista primero en el
4 | servidor antes de enviarla hacia el cliente. Vistas pueden lucir de la siguiente manera:
5 |
6 | ```html
7 |
8 | <:Title>
9 | My Page
10 |
11 | <:Body>
12 |
My Page
13 |
14 |
Welcome {{ Volt.current_user.name }}!
15 | ```
16 |
17 | # Secciones
18 |
19 | Las vistas en Volt tienen su propia sintaxis. También pueden ser separadas en secciones, estas empiezan con un header de sección. Un header de sección luce
20 | de la siguiente manera:
21 |
22 | ```html
23 | <:Body>
24 | ```
25 |
26 | Los secciones de cabecera deben empezar con una letra mayúscula (así no los confundiremos con [tags](#tags)). Estos no tienen que ser cerrados como los tags normales. Si no se provee con un cabecera de sección volt asumirá que estás en la sección ```:Body```.
27 |
28 | Las secciones nos ayudan a separar diferentes partes de un mismo contenido (usualmente el título y el body del html), pero dentro del mismo archivo
29 |
30 | # Bindings
31 |
32 | Las vistas usan un lenguaje sencillo de templating, donde el código ruby es insertado entre ```{{``` y ```}}```. Volt también nos permite crear un control de flujo en las vistas por medio de los statements usuales: (```if```, ```elsif```, ```else``` y ```each```). También puedes cargar otras vistas usando el binding ```view```.
33 |
34 | # Controlador
35 |
36 | Aunque Volt es mas un framework Modelo-Vista-VistaModelo (MVVM) que un framework MVC, hemos decidido usar la terminología MVC y el término controlador - esto solo significa que usarás el término 'Controller' en vez de 'ViewModel'.
37 |
38 | Cualquier llamado a un método o una variable de instancia en una vista se la hará en el contexto de este controlador.
39 |
40 | Si tienes una vista en ```app/main/views/index/index.html``` esta cargará el controlador ```app/main/controller/index_controller.rb```.
41 |
--------------------------------------------------------------------------------
/es/docs/volt_helpers.md:
--------------------------------------------------------------------------------
1 | ## Logging
2 |
3 | Volt nos provee un helper para almacenar nuestros loggings. Podemos llamar al método ```Volt.logger```, el cual nos retornará una instancia del logger de Ruby. Mira [aquí](http://www.ruby-doc.org/stdlib-2.1.3/libdoc/logger/rdoc/Logger.html) para obtener mas información.
4 |
5 | Un ejemplo:
6 |
7 | ```ruby
8 | Volt.logger.info("Some info...")
9 | ```
10 |
11 | Puedes cambiar el logger de la siguiente forma:
12 |
13 | ```ruby
14 | Volt.logger = Logger.new
15 | ```
16 |
17 | ## Configuración del App
18 |
19 | Como en muchos frameworks, Volt puede cambiar los settings por default basado en el flag de environment. Puedes cambiar el environment de volt por medio de la variable ```VOLT_ENV```.
20 |
21 | Todos los archivos en la carpeta ```config``` de la aplicación son cargados cuando se inicia la aplicación. Este comportamiento es similar al de la carpeta ```initializers``` de Rails.
22 |
23 | Volt se inicializa con las configuraciones mas útiles. Puedes configurar cosas como tu base de datos o el nombre de tu aplicación, por ejemplo, dentro del archivo ```config/app.rb```. Actualmente volt cuenta con las siguientes opciones de configuracion:
24 |
25 | | nombre | default | descripcion |
26 | |-----------|--------------------------------|--------------------------------------------------------------------------------|
27 | | app_name | el nombre de la carpeta actual | Este es usado internamente para logging, por ejemplo. |
28 | | db_driver | 'mongo' | Por el momento mongo es el unico driver compatible, se añadirán mas muy pronto |
29 | | db_name | "#{app\_name}\_#{Volt.env} | El nombre de la base de datos mongo. |
30 | | db_host | 'localhost' | El hostname de la base de datos mongo. |
31 | | db_port | 27017 | El puerto de la base de datos mongo. |
32 | | compress_deflate | false | Si el valor es true. este correrá la opción deflate en el servidor del app. Aunque es mejor que un servidor web como nginx se encarge de esto |
33 |
--------------------------------------------------------------------------------
/es/docs/volt_internals.md:
--------------------------------------------------------------------------------
1 | # Volt Internamente
2 |
--------------------------------------------------------------------------------
/es/docs/yield_binding.md:
--------------------------------------------------------------------------------
1 | # Binding Yield
2 |
3 | Cuando usas [Tags](#tags), el contenido que es generado al momento de llamarlo sera pasado en la definición de este tag.
4 | En otras palabras, la definición del tag podrá hacer referencia al contenido del 'caller', el cual tiene casi el mismo que el
5 | keyword `yield` en ruby.
6 |
7 | Supongamos que tenemos un elemento del navbar que queremos reutilizar, en nuestro caso una simple elemento de una lista:
8 |
9 | ```html
10 |
15 | ```
16 |
17 | Podemos convertir este pedazo de html en un tag fácilmente, incluso podemos pasar el link y el texto de este por
18 | medio de ```attrs```, aunque no seria del todo intuitivo hacerlo para el texto dentro de span, en este caso podemos
19 | usar el binding yield:
20 |
21 | ```html
22 | <:Nav>
23 |
28 | ```
29 |
30 | Para usar el output de este tag en nuestra página, lo hariamos con el siguiente tag:
31 |
32 | ```html
33 | <:nav href="/about">About
34 | ```
35 |
36 | En el ejemplo anterior, "About" se cargara en lugar ```{{ yield }}```. Por lo general, cualquier contenido dentro del tag que llama a la definición se encargara de ligar ```yield```
37 |
38 | Por último, si solo quieres obtener el contenido html como un string, puedes llamar al método ```yield_html``` en el controlador. Esto retornará un string en el cual puedes invocar el método ```.watch!``` en el caso de que lo necesites y este cargará de nuevo el contenido en el caso de que existan cambios.
39 |
--------------------------------------------------------------------------------
/es/getting_help/README.md:
--------------------------------------------------------------------------------
1 | # Obteniendo Ayuda
2 |
3 | Volt es todavía un trabajo en progreso, pero todo el feedback que nos puedan dar nos será de mucha ayuda. Puedes usar los siguientes recursos para mantenerte en contacto con los desarrolladores, de seguro alguien te responderá de inmediato
4 |
5 | - *****Si necesitas ayuda**: postealo eh [stackoverflow.com](http://www.stackoverflow.com). Asegurate de agregar `voltrb` como tag a tu pregunta.
6 | - **Si encontraste un error**: postealo en [github issues](https://github.com/voltrb/volt/issues)
7 | - **Si tienes una idea o necesitas nuevas funcionalidades**: postealo en [github issues](https://github.com/voltrb/volt/issues)
8 | - **Si quieres discutir acerca de Volt**: [chat de gitter](https://gitter.im/voltrb/volt), siempre encontrarás a alguien conectado y que estará feliz de ayudarte.
9 |
--------------------------------------------------------------------------------
/es/getting_help/can_i_use_opal_gems.md:
--------------------------------------------------------------------------------
1 | # Puede usar gemas de opal?
2 |
3 | Si. Opal tiene su propia forma de incluir gemas. Esto generalmente significa que tienes que incluir la gema en tu código MRI antes de que sea añadida al load path de opal.
4 |
5 | Por ejemplo con opal/browser, puede simplemente añadir lo siguiente en config/app.rb
6 |
7 | ```ruby
8 | require 'opal/browser'
9 | ```
10 |
11 | Luego añade lo siguiente en el controlador (al principio del archivo) en el cual usaremos opal-browser:
12 |
13 | ```ruby
14 | if RUBY_PLATFORM == 'opal'
15 | require 'browser'
16 | end
17 | ```
18 |
--------------------------------------------------------------------------------
/es/getting_help/does_volt_support_haml,_slim,_etc.md:
--------------------------------------------------------------------------------
1 | # Soporta Volt Haml, Slim..
2 |
3 | Actualización: Si, volt cuenta ahora con soporte para slim, gracias a @ASnow: https://github.com/asnow/volt-slim
4 |
5 | Todavía no contamos con soporte para HAML, a continuación una breve explicación del porque y que es necesario hacer
6 |
7 | Esta es una pregunta muy común sobre todo por parte de quienes han usado Rails , donde resulta muy fácil añadir soporte para varios lenguajes de templating. En Rails el renderizado de un template toma la ubicación del template y un objeto, el cual se usará como contexto. Luego el resultado se genera como un string.
8 |
9 | En volt, por el contrario, los templates primero se renderizan como un template compilado que puede ser enviado al cliente. Los templates no son generados como strings, son contruidos para un escenario específico. Volt contempla dos escenarios:
10 |
11 | - El dom
12 | - Un string (para renderizar parte de los templates en tags, email o html usado en el servidor)
13 |
14 | # Entonces que hace falta para poder renderizar con Haml, etc...
15 |
16 | No todo es malas noticias, pero haml y slim no fueron diseñados exactamente para las necesidades de volt en mente. Cualquier lenguaje de template que puede compilar el código al formato generado por volt puede ser usado. El formato del template es código ruby (el cual es compilado hacia el cliente por medio de Opal). Este consiste de html y bindings. El html contiene placeholders (por ahora comentarios especiales de html) que nos muestran donde deben ser generados los bindings. Los bindings son ruby Procs que muestran el tipo de binding que representan. (Volt::EachBinding, Volt::ContentBinding, Volt::AttributeBinding, Volt::IfBinding y Volt::EventBinding)
17 |
18 | Para lograr compilar a haml o slim, necesariamente se debe modificar el código fuente de cualquiera de los dos para que puedan compilar al formato especial de volt. Si estas interesado en ayudar puedes contactarte con @ryanstout o por medio de [gitter](https://gitter.im/voltrb/volt).
19 |
--------------------------------------------------------------------------------
/es/getting_help/faq.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | * [Qué corre en el servidor vs el cliente ?](what_runs_on_the_client_vs_server.md)
4 | * [Puedo usar jQuery? (u otras librerías para la manipulación del DOM?)](can_i_use_jquery_or_other_dom_manipulating_js.md)
5 |
--------------------------------------------------------------------------------
/es/getting_help/is_keeping_a_persistent_connection_open_a_performance_problem.md:
--------------------------------------------------------------------------------
1 | # Al mantenerse una conexión permanente podrían ocurrir problemas de rendimiento?
2 |
3 | Trabajé en juegos para redes sociales algunos años atrás y solíamos abrir conexiones de socket (por medio de flash, ya que no existían aun los websockets) para cada uno de nuestros usuarios. En un punto llegamos a tener hasta 500.000 usuarios en linea al mismo tiempo y nuestro servidor de envío (el que mantenía las conexiones abiertas para los clientes) usaba apenas el 10% del cpu. El servidor fue construido con un eventmachine sobre MRI. Eventmachine en linux puede usar el api de e-poll. Este básicamente registra todas las operaciones de io por sockets. Por dar un ejemplo, Nginx está construido de una manera parecida. Usando esto podemos escalar a millones de conexiones en una sola máquina.(Google el problema del C10k , o entra a http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html) en resumen, correr un servidor con eventos debería manejar múltiples conecciones abiertas sin problemas. La parte de manejar el IO es la parte fácil, uno de los problemas con los que te puedes encontrar es cuando tienes muchos usuarios suscritos a un misma cantidad de datos, ya que podrías terminar saturando la conexión de red en actualización demasiado grandes. Estamos trabajando en un bus de datos distribuido (similar al que existe en vert.x) para permitir actualizaciones distribuidas y conexiones a través de varias máquinas. En los servidores thin y goliath puedes obtener un thread por cada request de rack, pero todos los requests de websockets pueden correr en un solo thread y usar un io por eventos para manejar el envío de resultados. También me gustaría integrar vert.x con jruby para hacer cosas similares.
4 | Espero que esto halla respondido algunas de sus preguntas. Existen muchos problemas difíciles en Volt por resolver, pero pienso que manejar la persistencia de las conexiones no es uno de ellos. Para la mayoría de los casos esto es resuelto gracias a epoll y el O(1) linux scheduler.
5 |
6 | - Ryan
7 |
--------------------------------------------------------------------------------
/es/getting_help/what_browsers_does_volt_support.md:
--------------------------------------------------------------------------------
1 | # Que navegadores son compatibles con Volt?
2 |
3 | Descartando Firefox y Chrome, los cuales siempre están actualizados, seguramente te preguntarás por IE. La buena noticia es que opal soporta IE desde la versión 6. Volt solo soporta la versión 10 de IE por el momento, pero estamos trabajando en la gema volt-ie8to9 que dara soporte a las versiones 8 y 9. Lo único que nos falta es un fallback para websockets.
4 |
5 | ## Características limitadas
6 |
7 | Existen algunas características de Volt que solo funcionan para ciertos navegadores
8 |
9 | 1) Binding de campos ocultos.
10 | Para crear un bind en un campo oculto, el navegador necesita eventos mutables observer. Estos solo se encuentran soportados para >=IE11. Existe un polyfill que puede ser usado para obtener soporte en IE8-10, para el cual crearemos un gema muy pronto
11 |
--------------------------------------------------------------------------------
/es/introduction/README.md:
--------------------------------------------------------------------------------
1 | # Objetivos
2 |
3 | Volt tiene los siguientes objetivos:
4 |
5 | 1. La felicidad del desarrollador
6 | 2. Eliminar código duplicado entre el cliente y el servidor
7 | 3. Sincronización de datos automática entre cliente y servidor
8 | 4. Construir aplicaciones como componentes anidados. Los componentes pueden ser compartidos (por medio de gemas), o correrlos como servicios
9 | 5. Concurrencia. Volt provee herramientas para simplificar la concurrencia
10 | 6. Manejo inteligente de assets
11 | 7. Seguridad
12 | 8. Rápido, Liviano y Escalable
13 | 9. Código base entendible
14 |
15 | # Camino a seguir
16 |
17 | Muchas de las características principales se encuentran implementadas. Todavía
18 | nos falta un poco para llegar a la versión 1.0, la mayoría con respecto a
19 | modelos.
20 |
21 | 1. API de datos - Una abstracción que permitirá crear adaptadores para cualquier tipo de base de datos o datastore.
22 | 2. Integración Oauth - El plan es integrar omniauth para hacer mas fácil el uso de cualquier proveedor omniauth
23 | 3. Migraciones para añadir índices de bases de datos desde Volt
24 | 4. Prerenderizado de HTML desde el servidor - El plan es permitir que el servidor renderice el html de una página primero, para luego atarlo al código ruby compilado del cliente una vez que el código se ha cargado
25 |
--------------------------------------------------------------------------------
/es/tutorial/README.md:
--------------------------------------------------------------------------------
1 | # Tutorial
2 |
3 | Este tutorial te guiará en la creación una aplicación web básica en Volt. Esta guía asume un conocimiento básico del lenguaje Ruby y de desarrollo web. Este tutorial todavía es un trabajo en progreso :)
4 |
5 | # Configuracion
6 |
7 | Primero, instalemos Volt y creemos una aplicación vacía. Asegúrate de que tener una versión de ruby mayor a 2.1.0 y de que rubygems este instalado
8 |
9 | Luego instala la gema de volt:
10 |
11 | gem install volt
12 |
13 | Con la gema que acabamos de instalar podemos crear un nuevo proyecto:
14 |
15 | volt new sample_project
16 |
17 | Esto creará una aplicación básica dentro de la carpeta sample_project. Podemos hacer ```cd``` dentro de la carpeta y correr el servidor:
18 |
19 | bundle exec volt server
20 |
21 | Por último, podemos acceder a la consola de Volt por medio del siguiente comando:
22 |
23 | bundle exec volt console
24 |
--------------------------------------------------------------------------------
/ja/README.md:
--------------------------------------------------------------------------------
1 | # Voltとは
2 |
3 | Volt は Ruby の Web フレームワークで、サーバーサイドとクライアントサイドの両方のコードを Ruby で記述できることが特徴です。(クライアント側では [opal](https://github.com/opal/opal) を利用します)。Volt では、ユーザーがページに対して行った操作に応じて自動的に DOM が更新されます。ページの状態は URL として保持されるので、ブックマークによって以前と同じ状態に戻ることが可能です。
4 |
5 | Volt では、HTTP を介してクライアントとサーバー間のデータを同期するのではなく、永続的なコネクションを利用します。したがって、ある1つのクライアント上でデータが更新されたときには、データベース、および他のリスニング中のクライアント上でも更新が行われます。(しかも、そのために設定を行う必要はありません)データの更新をコントローrルするためにパーミションとバリデーションを構成することが可能です。
6 |
7 | ページの HTML はテンプレート言語で記述し、```{{```と```}}``` で囲むことで Ruby のコードを直接書くことができます。Volt は、DOM (および値が変更されたことを検知したい他のすべてのコード)に対して、自動的に、かつ正確に変更を伝えるために、データフロー/リアクティブプログラミングを利用します。 DOM に何らかの変更があった場合に、Volt は変更が必要なノードだけを正しく更新することができます。
8 |
9 | 文章のドキュメントだけでなく、デモの動画も用意しています。
10 |
11 | - [Volt Todos Example](https://www.youtube.com/watch?v=KbFtIt7-ge8)
12 | - [What Is Volt in 6 Minutes](https://www.youtube.com/watch?v=P27EPQ4ne7o)
13 | - [Pagination Example](https://www.youtube.com/watch?v=1uanfzMLP9g)
14 | - [Routes and Templates](https://www.youtube.com/watch?v=1yNMP3XR6jU)
15 | - [Isomorphic App Development - RubyConf 2014](https://www.youtube.com/watch?v=7i6AL7Walc4)
16 |
17 | デモアプリケーションも用意しています。
18 | - https://github.com/voltrb/todomvc
19 | - https://github.com/voltrb/blog5
20 |
21 |
--------------------------------------------------------------------------------
/ja/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Volt Introduction and Docs",
3 | "description": "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.\n\nInstead 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).\n\nPages HTML is written in a handlebars-like template language. 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."
4 | }
--------------------------------------------------------------------------------
/ja/contributing/README.md:
--------------------------------------------------------------------------------
1 | # Volt への貢献
2 |
3 | Volt に貢献したい?それは素晴らしい!ありがとうございます!コントリビュートの方法は以下をご覧ください。
4 |
5 | https://github.com/voltrb/volt/blob/master/CONTRIBUTING.md
6 |
--------------------------------------------------------------------------------
/ja/contributing/component_gems.md:
--------------------------------------------------------------------------------
1 | # コンポーネント Gem
2 |
3 | メモ: この章は現在作成中です。
4 |
5 | Gem に関しては [こちら]("../docs/lib.html") をご覧ください。
6 |
7 | ## コンポーネントがロードされる順序
8 |
9 | -
10 |
--------------------------------------------------------------------------------
/ja/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voltrb/docs/9e8b414a9e2209a82b4d3451d734a4b5e7c15fd2/ja/cover.jpg
--------------------------------------------------------------------------------
/ja/cover_small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/voltrb/docs/9e8b414a9e2209a82b4d3451d734a4b5e7c15fd2/ja/cover_small.jpg
--------------------------------------------------------------------------------
/ja/deployment/README.md:
--------------------------------------------------------------------------------
1 | # Volt のデプロイ
2 |
3 | ## production 環境での実行
4 |
5 | アプリケーションをデプロイする場合は、VOLT_ENV=production の環境変数を設定することを推奨します。これによってコードのリローディングとソースマップが無効になり、いくつかのパフォーマンスを向上させる設定が有効になります (ロードに要する時間は増加します) 。
6 |
7 | ## アセットのプリコンパイル
8 |
9 | Volt では、すべてのアプリケーションのアセットを /public にプリコンパイルすることが可能です。プリコンパイルにおいて、Volt は以下のことを行います。
10 |
11 | 1. すべての Opal ファイルのプリコンパイル
12 | 2. JS/Opal JS の minify ([uglifier](https://github.com/mishoo/UglifyJS2) を利用)
13 | 3. CSS の minify ([csso](https://github.com/css/csso) を利用)
14 | 4. CSS と JavaScirpt をそれぞれ単一のファイルに結合する (クライアント上でのリクエスト回数を減らすため)
15 | 5. すべての画像の非可逆圧縮とメタデータの除去 ([image-optim](https://github.com/toy/image_optim) の様々なツールを利用)
16 | 6. 永久的なキャッシュのための fingerprint を用いたアセットのリネーム(ファイルに変更があれば、新しい fingerprint が生成されて紐付けられる)
17 |
18 | すべてのアセットは /public フォルダにコンパイルされ、[Nginx](http://nginx.org/) などが直接サーブすることが可能です。プリコンパイルを行った結果、最初のページ読み込み速度をはっきりと向上させ、ブラウザからのリクエスト数を減少させることができます。
19 |
20 | アプリケーションのアセットをプリコンパイルするには、単純に以下を実行します。
21 |
22 | ```VOLT_ENV=production bundle exec volt precompile```
23 |
24 | ### アセットのキャッシュ
25 |
26 | アセットのプリコンパイルによって、css/sass/html ファイルから参照される画像をコンポーネントから public フォルダにコピーします。すべてのアセットは、プリコンパイルの際に fingerprint のハッシュが末尾に追加された名前 (```profile-``` など) にリネームされることに気がつくでしょう。これによって、public フォルダ内のすべての画像やフォントなどを永久的にキャッシュすることができるようになっています。ファイルの中身が変更された場合は、新しいハッシュが割り当てられます。(これは Rails で行われるプロセスと同様です。詳しくは、[こちらのより詳細なドキュメント](http://guides.rubyonrails.org/asset_pipeline.html)を参照してください) 。
27 |
28 | アセットを正しく示すための画像のタグや CSS などについては、[アセット](docs/assets.md)のセクションを参照してください。
29 |
30 | ### カスタム Socket URL
31 |
32 | Volt は、すべてのデータベースへの問い合わせや更新、そしてタスクの呼び出しなどを、[websocket](https://en.wikipedia.org/wiki/WebSocket) の通信によって行います。Websockets は既存の HTTP コネクションを「アップグレード」することによって作られます。通常、Volt は既存の HTTP コネクションを利用して websocket のコネクションをセットアップします。しかし、異なるポートやドメインなどを使って websocket に接続したいケースもあるでしょう。(一般的に、メインのアプリケーションが websocket に非対応なプロキシサーバーの背後で動作している場合に必要となります) 。websocket の URL は ```config/app.rb``` で以下のように設定可能です。
33 |
34 | ```ruby
35 |
36 | Volt.configure do |config|
37 | # ...
38 |
39 | config.public.websocket_url = 'websocket.mysite.com/socket'
40 | ...
41 | end
42 | ```
43 |
44 | Volt は、指定がない場合は、自動的に ws:// もしくは wss:// を URL の先頭に追加します。
45 |
46 | ## ホスティングサービス
47 |
48 | この章の残りでは、有名なクラウドサービスへのデプロイ方法に焦点を当てて説明します。
49 |
--------------------------------------------------------------------------------
/ja/deployment/apache.md:
--------------------------------------------------------------------------------
1 | # Apache
2 |
3 | Websockets をサポートしていません。[詳しくはこの投稿を参照](https://github.com/phusion/passenger/issues/1202)してください。
4 | したがって、Apache を [thin](http://code.macournoyer.com/thin/) に対するフォワードプロキシとして扱う必要があります。
5 | Apache に対して、以下のモジュールを有効にしてください。
6 | - [mod_proxy](http://httpd.apache.org/docs/2.4/mod/mod_proxy.html)
7 | - [mod_proxy_wstunnel](http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html)
8 |
9 | ```
10 |
11 | ServerName YOUR.SERVER.NAME
12 | DocumentRoot /PATH/TO/APP_NAME/public
13 |
14 | ProxyRequests Off
15 | ProxyPreserveHost On
16 |
17 | # a2enmod proxy_wstunnel
18 | ProxyPass /socket ws://localhost:3001/socket
19 | ProxyPassReverse /socket ws://localhost:3001/socket
20 | ProxyPass / http://localhost:3001/
21 | ProxyPassReverse / http://localhost:3001/
22 |
23 | LogLevel warn
24 |
25 | CustomLog ${APACHE_LOG_DIR}/APP_NAME_access.log combined
26 | ErrorLog ${APACHE_LOG_DIR}/APP_NAME_error.log
27 |
28 | ```
29 |
30 | `thin install` でサービスとしてインストールし、`/var/thin/volt.yml` に以下の構成ファイルを追加してください。
31 |
32 | ```
33 | ---
34 | chdir: "/PATH/TO/APP_NAME"
35 | environment: production
36 | address: 0.0.0.0
37 | port: 3001
38 | timeout: 30
39 | log: "/var/log/thin-expenses.log"
40 | pid: tmp/pids/thin.pid
41 | max_conns: 1024
42 | max_persistent_conns: 100
43 | require: []
44 | wait: 30
45 | threadpool_size: 20
46 | servers: 1
47 | daemonize: true
48 | ```
49 |
50 | その後、`sudo /etc/init.d/thin start` で thin を起動してください。
51 |
--------------------------------------------------------------------------------
/ja/deployment/cloud9.md:
--------------------------------------------------------------------------------
1 | # Cloud9
2 |
3 | Cloud9 で開発したい場合は、Rails のイメージを起動します。(Rails イメージには、必要なものがすべて含まれています)イメージが起動したら、既存のプロジェクトを削除します:
4 |
5 | ```rm -rf *```
6 |
7 | まず Mongo のセットアップをしましょう (Mongo の動作に関するドキュメントはこちらを参照してください(訳注:リンク漏れ?要確認)) 。
8 |
9 | 新しいターミナルを起動し、以下を入力してください:
10 |
11 | ```
12 | mkdir data
13 | echo 'mongod --bind_ip=$IP --dbpath=data --nojournal --rest "$@"' > mongod
14 | chmod a+x mongod
15 | ```
16 |
17 | そして、以下で mongod を起動します:
18 |
19 | ```
20 | ./mongod
21 | ```
22 |
23 | 次に、Volt をインストールします。
24 |
25 | ```gem install volt```
26 |
27 | 新しいプロジェクトを作成します。
28 |
29 | ```volt new projectname```
30 |
31 | `cd` でプロジェクトのディレクトリに移動します:
32 |
33 | ```cd projectname```
34 |
35 | それではサーバーを起動しましょう (Cloud9 では、ENV でポート番号とIPアドレスを指定する必要があります)
36 |
37 | ```bundle exec volt server -p $PORT -b $IP```
38 |
39 | Cloud9 はそれぞれのアプリケーションに対してサブドメインを割り当てます。起動しているアプリケーションを開く場合は、```Preview``` メニューをクリックし、```Preview Running Application``` を選択してください。
40 |
41 | Cloud9 の無償バージョンでは、mongoDB は定期的にシャットダウンしてしまいます。その対策として、www.mongolab.com で代替の無償の Mongo ストレージセットアップすることが可能です。まずアカウントを登録し、```config/app.rb``` に以下を追加してください。
42 |
43 | ```
44 | config.db_driver = 'mongo'
45 | config.db_name = (config.app_name + '_' + Volt.env.to_s)
46 | if ENV['MONGOHQ_URL'].present?
47 | config.db_uri = ENV['MONGOHQ_URL'] # Cloud9 ではこの行が必要です。
48 | else
49 | config.db_host = 'localhost'
50 | config.db_port = 27017
51 | end
52 | ```
53 |
54 |
55 | ※もし Cloud9 にカスタム Volt イメージを構築したい人がいたら、Gitter で @ryanstout にお知らせください。どうもありがとうございます!
56 |
--------------------------------------------------------------------------------
/ja/deployment/docker.md:
--------------------------------------------------------------------------------
1 | ## Volt の Docker コンテナ
2 |
3 | Volt アプリケーションに Dockerfile を作成し、以下を記載してください。
4 |
5 | ```
6 | FROM otzy007/voltframework
7 | ```
8 |
9 | これで、Docker イメージをビルドすることができます。
10 |
11 | ```
12 | docker build -t my-volt-app .
13 | ```
14 |
15 | 以下のように起動します。
16 |
17 | ```
18 | docker run --name my-volt-app -p 3000:3000 -d my-volt-app
19 | ```
20 |
21 | Web ブラウザーで http://localhost:3000 にアクセスできます。
22 |
--------------------------------------------------------------------------------
/ja/deployment/heroku.md:
--------------------------------------------------------------------------------
1 | ## Heroku
2 |
3 | 以下のように、```Gemfile``` に Ruby のバージョンを指定します。
4 |
5 | ```ruby
6 | source 'https://rubygems.org'
7 |
8 | ruby "2.1.3" # Ruby バージョンの指定
9 |
10 | gem 'volt', ~> '0.9.0'
11 | ```
12 |
13 | ```Procfile``` を追加し、Thin を利用するように指定します。
14 |
15 | web: bundle exec thin start -p $PORT -e $RACK_ENV
16 |
17 | ```/config/app.rb``` にデータストアの接続設定を記載します。
18 | 以下は MongoHQ の場合の設定例です。利用するプロバイダーにあわせて適宜変更してください。
19 | [MongoLab](http://www.mongolab.com) はとても素晴らしい無償のソリューションです。
20 |
21 | ```ruby
22 | config.db_driver = 'mongo'
23 | config.db_name = (config.app_name + '_' + Volt.env.to_s)
24 |
25 | if ENV['MONGOHQ_URL'].present?
26 | config.db_uri = ENV['MONGOHQ_URL'] # Heroku ではこの行が必要です
27 | else
28 | config.db_host = 'localhost'
29 | config.db_port = 27017
30 | end
31 | ```
32 |
--------------------------------------------------------------------------------
/ja/docs/README.md:
--------------------------------------------------------------------------------
1 | # Volt のドキュメント
2 |
3 | ここでは、Volt のすべての機能をドキュメント化するつもりです。最終的に機能を決定するのはプログラムのコード自体ですが、可能な限りドキュメントを最新の状態に保つようにします。
4 |
5 | ## アプリケーションのレイアウト
6 |
7 | 新規の Volt アプリケーションには、はじめからいくつかのフォルダ/ファイルが含まれています。
8 |
9 |
10 | | 名前 | 詳細 |
11 | |-----------------|------------------------------------------------------------------|
12 | | app | アプリケーションの[コンポーネント](docs/components.md)をサブフォルダに含みます |
13 | | config | アプリケーションの設定と、起動時に実行されるコード (initializer) を含みます |
14 | | config.ru | [Rack](http://rack.github.io/) 互換サーバーがアプリケーションを起動するのに使用する特別なファイルです |
15 | | spec | すべての Rspec のテスト (specs) を含みます|
16 | | Gemfile | プロジェクトが依存するすべての Gem を指定します |
17 | | Gemfile.lock | [Bundler](http://bundler.io/) によって生成され、Gem のバージョンを追跡するためのファイルです |
18 | | README.md | プロジェクトのための Markdown ファイルです |
19 |
20 | ほとんどのアプリケーションのコードは app 内のコンポーネントのフォルダに存在します。アプリケーションは、再利用性やテストのために、独立したコンポーネントに分割することができます。デフォルトでは、Volt は「main」という1つのコンポーネントを生成します。Volt を学ぶ際には、すべてを「main」に入れることが可能です。
21 |
22 | ## コンポーネント
23 |
24 | コンポーネントはいくつかの標準的な構成のフォルダを含みます。
25 |
26 | | 名前 | 詳細 |
27 | |-----------------|------------------------------------------------------------------|
28 | | assets | CSS/JS/画像/フォントなどの静的なアセット |
29 | | config | コンポーネント特有の設定と依存関係の管理 |
30 | | controllers | UI の表示や、そのモデルへの接続を構成するクラス |
31 | | lib | コンポーネントに必要な追加の Ruby コード |
32 | | models | データ、パーミッション、バリデーション、そしてビジネスロジックを管理するクラス |
33 | | views | ブラウザ上でレンダリングされてアプリケーションを表示するための HTML ファイル |
34 |
35 | これから、コンポーネントのより詳細な内容の前に、コンポーネントの各パートについて記載します。
36 |
--------------------------------------------------------------------------------
/ja/docs/arraymodel_events.md:
--------------------------------------------------------------------------------
1 | ## ArrayModel イベント
2 |
3 | ArrayModel はデータが更新されたときにイベントをトリガーします。現在、モデルは ```added``` と ```removed``` の2つのイベントを発生させます。例:
4 |
5 | ```ruby
6 | page._items.on('added') { puts 'item added' }
7 | page._items << 1
8 | # => item 追加
9 |
10 | page._items.on('removed') { puts 'item removed' }
11 | page._items.delete_at(0)
12 | # => item 削除
13 | ```
14 |
15 | イベントはバインディングにおいて内部的に利用されるものですが、自分のコードで使うことも可能です。
16 |
17 | 注意: ArrayModel イベントは現在のところ非公式な機能としての扱いとなっています。すべてのケースで動作の保証はされません。
18 |
--------------------------------------------------------------------------------
/ja/docs/attribute_bindings.md:
--------------------------------------------------------------------------------
1 | # 属性バインディング
2 |
3 | バインディングは属性の内部にも配置することができます。
4 |
5 | ```html
6 |