├── .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 |

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 is supported as well. 30 | 31 | ```html 32 | {{ unless some_check? }} 33 |

render this when some_check? is false

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 |
    8 | {{ _todos.each do |todo| }} 9 | <:todo name="{{ todo._name }}" /> 10 | {{ end }} 11 |
12 | 13 | <:Todo> 14 |
  • {{ attrs.name }}
  • 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 |
    26 | 27 | <:Todo> 28 |
  • 29 | {{ _name }} - 30 | {{ if _complete }} 31 | Complete 32 | {{ end }} 33 |
  • 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 |
  • 11 | 12 | About 13 | 14 |
  • 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 |
  • 24 | 25 | {{ yield }} 26 | 27 |
  • 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 |
      8 | {{ _todos.each do |todo| }} 9 | <:todo name="{{ todo._name }}" /> 10 | {{ end }} 11 |
    12 | 13 | <:Todo> 14 |
  • {{ attrs.name }}
  • 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 |
    26 | 27 | <:Todo> 28 |
  • 29 | {{ _name }} - 30 | {{ if _complete }} 31 | Complete 32 | {{ end }} 33 |
  • 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 |
  • 11 | 12 | About 13 | 14 |
  • 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 |
  • 24 | 25 | {{ yield }} 26 | 27 |
  • 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 |

    Text

    7 | ``` 8 | 9 | ## 双方向の属性バインディング 10 | 11 | 要素を「双方向バインディング」とするためのいくつかの機能があります。 12 | 13 | ```html 14 | 15 | ``` 16 | 17 | 上記で、もし ```_name``` が変更された場合、テキストボックスの値も更新されます。コントローラーで ```_name``` を実行すると、「name」の値を得ることができます。ユーザーがテキストボックスに入力したとき、コントローラーでは同等のセッターメソッドが呼び出されます。この場合は、コントローラー上で ```_name=``` が実行され、新しいフィールドの値が渡されます。これが双方向バインディングの効果です。ただ、データの更新のしかたは、異なるセッターメソッドを定義することで変更することができます。このことによって、単一方向/双方向バインディングともに利便性を高めることができると考えています。 18 | 19 | ## チェックボックス 20 | 21 | 上記の例で、```_name``` が変更された場合にはフィールドも更新されます。逆に、フィールドが更新された場合には ```_name``` も変更されます。 22 | 23 | ```html 24 | 25 | ``` 26 | 27 | この例では、checked属性の値が ```true``` であるとき、チェックボックスはチェックされた状態になります。そして、「チェックされた or チェック解除された」という状態の変化に応じて、値が ```true``` または ```false``` に更新されます。 28 | 29 | ## ラジオボタン 30 | 31 | ラジオボタンも checked の状態に対してバインドすることができますが、```true``` or ```false``` の代わりに、与えられたフィールドの値がセットされます。 32 | 33 | ```html 34 | 35 | 36 | ``` 37 | 38 | ラジオボタンがチェックされたとき、checked には常にフィールドの値が設定されるようにバインドされます。checked にバインドされた値が変更されたとき、ラジオボタンのバインドされた値にマッチするすべてのフィールドがチェックされた状態になります。メモ: ラジオボタンに対しては、この振る舞いがもっとも利便性が高いと考えています。 39 | 40 | ## セレクトボックス 41 | 42 | セレクトボックスは値に対してバインドすることができます。(これは技術的には正しくありませんが、Volt では利便性のためにこのような振る舞いを追加しています) 43 | 44 | ```html 45 | 52 | ``` 53 | 54 | 選択されたオプションが変更されると、それに合うように ```_rating``` が変更されます。```_rating``` が変更された場合には、それにマッチする最初のオプションが選択された状態になります。マッチするオプションが存在しなかった場合には、セレクトボックスは未選択の状態になります。 55 | 56 | ## 現在の制限事項 57 | 58 | 現在のところ、バインディングは属性の内部でのみ可能です。タグ内や、属性の外側でも利用できるようにすることを検討中です。 59 | -------------------------------------------------------------------------------- /ja/docs/automatic_model_conversion.md: -------------------------------------------------------------------------------- 1 | # 自動モデル変換 2 | 3 | ## Hash -> Model 4 | 5 | 利便性のために、ある Model (モデル) の中にハッシュを入れた場合には、自動的に Model に変換されるようになっています。Model はハッシュに似ていますが、例えば永続化の機能を持っている点や、イベントをトリガできる点が異なります。 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 | Model をハッシュに戻したい場合には、`#to_h` を実行してください。 24 | 25 | ## Array -> ArrayModel 26 | 27 | Model の中のアレイは自動的に ArrayModel のインスタンスに変換されます。ArrayModel は通常のアレイと同様に振る舞いますが、バックエンドのデータにバインドしたり、リアクティブなイベントを発生させたりできる点が異なります。 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 | Volt::Model や Volt::ArrayModel を通常のハッシュに戻したい場合には、それぞれ .to_h と .to_a を実行してください。 42 | (JavaScript のコードに渡すために) JavaScript のオブジェクトに変換したい場合には、`#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 | Volt::ArrayModel に対して .to_a を実行することで通常の配列を得ることができます。 63 | -------------------------------------------------------------------------------- /ja/docs/beforeafter_actions.md: -------------------------------------------------------------------------------- 1 | # Before/After フィルター 2 | 3 | コントローラーでレンダリングを行う際に、アクションが実行される前後に何らかの処理を実行したい場面がしばしばあります。Voltは```before_action```と```after_action```のメソッドを提供しており、それらを使うことで「before アクション」と「after アクション」を設定することが可能です。以下のようにして設定します。 4 | 5 | ```ruby 6 | module Main 7 | class MainController < Volt::ModelController 8 | before_action :english_only 9 | 10 | # require_loginはVolt::ModelControllerのメソッドです 11 | before_action :require_login, only: :about 12 | 13 | def index 14 | # indexの設定… 15 | end 16 | 17 | def about 18 | # aboutの設定… 19 | end 20 | 21 | # ロケールが英語でなければリダイレクト 22 | # (あくまでも例です) 23 | def english_only 24 | if `navigator.language` != 'en-US' 25 | redirect_to '/translations' 26 | stop_chain # 詳細は後述 27 | end 28 | end 29 | end 30 | end 31 | ``` 32 | 33 | アクションはメソッド名のシンボル以外にブロックをとることもできます。 34 | 35 | ## 特定のアクションにのみ適用 36 | 37 | 特定のアクションのみにフィルターを適用させたい場合は、```only: :some_action``` を引数に指定します。```only``` はシンボルかシンボルの配列のいずれかを設定することが可能です。 38 | 39 | # stop_chain 40 | 41 | beforeフィルターでリダイレクトを実行する方法はごく一般的に使われます。レンダリングを途中で停止したい場合は、アクションで```stop_chain```を呼び出せば、そこでレンダリングは停止します。 42 | 43 | ```stop_chain``` はfilter runnerによって補足される例外を発生させますので、```stop_chain```以降のコードが実行されることはありません。 44 | -------------------------------------------------------------------------------- /ja/docs/buffers.md: -------------------------------------------------------------------------------- 1 | ## バッファ 2 | 3 | Volt のすべてのモデルは、変更を自動的にその persistor に対しても保存します。例えば、```store``` 上のモデルに対して、その ```name``` プロパティの変更を行ったとき、その変更は自動的にデータベースと他のクライアントに同期されます。他の多くのフレームワークと異なり、明示的に save を実行する必要はありません。モデルはプロパティの変更に応じて即座に同期されます。 4 | 5 | ```ruby 6 | store._items.first.then do |item| 7 | item._name = 'New Item Name' 8 | # ...syncs back to db 9 | end 10 | ``` 11 | 12 | もう1つ例をあげます。パラメータの ```index``` プロパティに変更を加えた際、index の変更に応じて即座に URL も更新されます: 13 | 14 | ```ruby 15 | params._index = 20 16 | # ...url 更新 17 | ``` 18 | 19 | ストアコレクションは自動的にバックエンドと同期するため、モデルのプロパティに対する更新は、他のクライアントにも即座に反映されます。しかし、この動作が望ましくない場合もあるでしょう。[CRUD](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete)アプリケーションの構築を容易にするため、Voltは"バッファ"という方法を的供します。バッファはモデルに対して作成することが可能で、```save!``` を実行するまでは、そのバッファの元になったモデル(バックエンドのモデル)に反映されることはありません。これを利用することで、submit ボタンが押されるまでは保存されないフォームを作成することが可能になります。 20 | 21 | ```ruby 22 | store._items << {name: 'Item 1'} 23 | 24 | store._items[0].then do |item1| 25 | item1_buffer = item1.buffer 26 | 27 | item1_buffer._name = 'Updated Item 1' 28 | item1_buffer._name 29 | # => 'Updated Item 1' 30 | 31 | item1._name 32 | # => 'Item 1' 33 | 34 | item1_buffer.save! 35 | 36 | item1_buffer._name 37 | # => 'Updated Item 1' 38 | 39 | item1._name 40 | # => 'Updated Item 1' 41 | end 42 | ``` 43 | 44 | なお、バッファに対して ```#save!``` を実行したときの戻り値は [promise](http://opalrb.org/blog/2014/05/07/promises-in-opal/) です。promise はデータがサーバーに保存された時点で解決 (resolve) されます。 45 | 46 | ```ruby 47 | item1_buffer.save!.then do 48 | puts "Item 1 saved" 49 | end.fail do |err| 50 | puts "Unable to save because #{err}" 51 | end 52 | ``` 53 | 54 | 既存のモデルに対して .buffer を実行した場合の戻り値は、そのモデルのインスタンスのバッファになります。また、Volt::ArrayModel に対して .buffer を実行した場合には、そのコレクションの新しい要素のバッファを取得します。.save! を実行すると、```<<``` または ```create``` で要素をコレクションにプッシュするかのように、その要素をサブコレクションに追加することができます。 55 | -------------------------------------------------------------------------------- /ja/docs/callbacks_and_actions.md: -------------------------------------------------------------------------------- 1 | # コントローラーのアクション 2 | 3 | ビューバインディングもしくはタグがビューをレンダリングする際には、まず始めにコントローラーが読み込まれます。レンダリングに関係するコールバックは4つあります。```{action}``` はビューファイルの名前と同一です。したがって、```about.html``` がレンダリングされたときには、```about``` がアクションとなります。コントローラーに正しくメソッドを定義しておくだけで、それらは対応するタイミングで実行されます。 4 | 5 | | アクション名 | 詳細 | 6 | |-----------------------|-----------------------------------------------------| 7 | | before_action コールバック | すべての before action はメインのアクションメソッドの前に実行されます。もし ```stop_chain``` が呼び出された場合は、```{action}``` は呼び出されず、実行は中断されます。| 8 | | ```{action}``` | レンダリングの前に実行されます。必要なデータのセットアップに利用してください。 | 9 | | after_action コールバック | after_action は ```stop_chain``` を呼び出すことができません (もし呼び出された場合には例外が発生します)。 | 10 | | ```{action}_ready``` | ビューがレンダリングされた後に実行されます。DOM に直接バインドする必要があればそのコードをここで実行します。例えば (bootstrap に必要な) jQuery の設定コードなどです。 | 11 | | ```before_{action}_remove``` | ビューが削除される (レンダリングが解かれる) ときに実行されます。ここで DOM バインディングの後始末をします。| 12 | | ```after_{action}_remove``` | ビューが DOM から削除された後に実行されます。コントローラーに後始末が必要なものがあれば、ここで後始末をします。| 13 | 14 | ほとんどの場合、これらのアクションを利用して、コントローラーやモデルなどをセットアップすることになるでしょう。 15 | 16 | -------------------------------------------------------------------------------- /ja/docs/channel.md: -------------------------------------------------------------------------------- 1 | # チャンネル 2 | 3 | コントローラーは `#channel` メソッドを持っていて、それを使うことでバックエンドへの接続の状態を知ることができます。チャンネルのアクセスメソッドはリアクティブであるため、状態が変わったときには監視中の評価が再度トリガーされます。利用できるメソッドは以下の通りとなります: 4 | 5 | | メソッド | 詳細 | 6 | |-------------|-----------------------------------------------------------| 7 | | connected? | バックエンドに接続されていれば true となる | 8 | | status | これらのいずれかの値となる :opening, :open, :closed, :reconnecting | 9 | | error | 最後に失敗した接続のエラーメッセージ | 10 | | retry_count | 再接続を試行した回数 (成功した接続は除く)| 11 | | reconnect_interval | 次に再接続を試行するまでの時間 (秒) | 12 | 13 | ## チャンネルイベント 14 | 15 | クライアントが「サーバーに接続したとき」または「サーバーから切断したとき」に処理を実行したい場合があるでしょう。その場合、クライアントのコントローラーで以下のようにすることができます: 16 | 17 | ```ruby 18 | channel.on('connect') do 19 | .. connected .. 20 | end 21 | 22 | channel.on('disconnect') do 23 | .. disconnect .. 24 | end 25 | ``` 26 | -------------------------------------------------------------------------------- /ja/docs/component_gems.md: -------------------------------------------------------------------------------- 1 | # コンポーネント Gem 2 | 3 | コンポーネントは gem で簡単に共有することができます。Volt は コンポーネントの gem を作成するための scaffold コマンドを提供します。(Volt プロジェクト以外の) フォルダーの中で、```volt generate gem {コンポーネント名}``` を実行してください。すると、gem が必要とするファイル群を生成することできます。すべての Vott コンポーネントの gem の名前には ```volt-``` が付きます。これによって、github や rubygems で見つけやすくなります。Gemの命名規約にしたがって、コンポーネント名はアンダースコア区切りにする必要があります。 4 | 5 | 開発中は、Gemfile に以下のように記載することで、そのコンポーネントを使用することができます: 6 | 7 | ```ruby 8 | gem 'volt-{コンポーネント名}', path: '/path/to/folder/with/component' 9 | ``` 10 | 11 | gem の準備が整ったら、以下のようにして rubygems にリリースすることができます。 12 | 13 | ``` 14 | rake release 15 | ``` 16 | 17 | Rubygems のバージョンを利用する場合には、Gemfile の ```path:``` オプションを削除してください。 18 | -------------------------------------------------------------------------------- /ja/docs/components.md: -------------------------------------------------------------------------------- 1 | # コンポーネント 2 | 3 | アプリケーションはコンポーネントから成り立っています。```app/``` 以下のすべてのフォルダーはコンポーネントです。コンポーネントはGemに含めることも可能です。一般的に、アプリケーションは複数のコンポーネントに分割することができます。どんなものでもコンポーネントとすることができます。再利用可能な小さなウィジェットから、アプリケーションの大きなセクションまでがコンポーネントとなります。コンポーネントは他のコンポーネントに含めることも可能なので、最初は小さなコンポーネントを作ることから始めて、少しずつ大きなコンポーネントを構築していくことを推奨します。再利用することを目的としたコンポーネントであれば、[コンポーネントGem](docs/component_gems.md)としてビルドすることができます。また、後からコンポーネントをGem化することも可能です。 4 | 5 | コンポーネント内のコードにはいくつかの方法でアクセスすることができます。モデルのコードはアプリケーションのどこからでもアクセス可能です。ビュー/コントローラーはタグやビューバインディングを使ってアクセスできます。ビューのパスをどのように探索するかについては、[タグ](docs/tags.md) を参照してください。 6 | 7 | コンポーネントは、コードをパートごとに疎結合にして、独立してテストを実行したり抽象化することを目的として用意されたアイデアです。 8 | 9 | 例えば、コンポーネントは以下のようなものが考えられるでしょう: 10 | 11 | __ウィジェット__ 12 | - バリデーションが設定されたフィールド 13 | - スライダー 14 | - WYSIWYGエディター 15 | - ファイルアップローダー 16 | - Google map 17 | 18 | __ページ__ 19 | - ログインページ 20 | - ユーザーのサインアップ/ログイン/パスワードを忘れた 21 | 22 | __アプリケーションの一部分__ 23 | - ブログ 24 | - CMS 25 | - 管理者エリア 26 | 27 | 経験上、必要だと考える以上に多くのコンポーネントを使うことが良いやり方です。なぜなら、アプリケーションを分割することによるオーバーヘッドはほとんどないからです。 28 | 29 | ## コンポーネントの生成 30 | 31 | 新しいコンポーネントは以下で生成します。 32 | 33 | ```bundle exec volt generate component NAME``` 34 | 35 | ## コンポーネントとルーティング 36 | 37 | あるルートにアクセスしたとき、フロントエンド側でそのコンポーネントに含まれるすべてのファイルが読み込まれます。したがって、コンポーネント内の新しいページのレンダリングにおいて新規の http リクエストは発生しません。異なるコンポーネントへのルートの URL にアクセスした場合には、リクエストは通常のページ読み込みとして処理され、そのコンポーネントのすべてのファイルが読みこまれます。したがって、コンポーネントを「再読み込みの境界線 (reload boundary)」を表すものとして捉えておくとよいでしょう。[注意: 現在のところ、ページの初回読み込み時には「main」コンポーネントだけがサポートされます。近日中に「reload boundry」がサポートされる予定です。] 38 | 39 | -------------------------------------------------------------------------------- /ja/docs/content_binding.md: -------------------------------------------------------------------------------- 1 | # コンテンツバインディング 2 | 3 | もっとも基本的なバインディングはコンテンツバインディングです。 4 | 5 | ```html 6 |

    Hello {{ name }}

    7 | ``` 8 | 9 | コンテンツバインディングとは、```{{``` と ```}}``` の間の Ruby コードを実行し、その戻り値をレンダリングするものです。バインディングされているコンテンツのデータが変更を監視されていれば、その変更に応じてテキストが更新されます。コンテンツバインディングされたテキストは、デフォルトでエスケープされます。 10 | 11 | ## Raw 12 | 13 | ```raw``` メソッドを使うと、HTML エスケープを無効にすることが可能です。 14 | 15 | ```html 16 |

    Your html is {{ raw your_html }}.

    17 | ``` 18 | 19 | raw の利用には危険が伴います。なぜなら、もしユーザーの操作によって生じる HTML が他のユーザーに対しても表示される場合、容易に悪意のある JavaScript を (例えば `````` のように) 仕込むことができるからです。これはクロスサイトスクリプティング攻撃と呼ばれます。クロスサイトスクリプティング攻撃について理解し、それを回避することができる場合にのみ、raw を利用するようにしてください。 20 | -------------------------------------------------------------------------------- /ja/docs/controllers.md: -------------------------------------------------------------------------------- 1 | # コントローラー 2 | 3 | Volt では、コントローラーがどのクラスであっても構いません。しかし、通常は ```Volt::ModelController``` を継承したクラスとします。コントローラーはコンポーネント名の名前空間の中に配置されます。そのモデルコントローラーを使うことで、コントローラーによって利用されるモデルが明確になります。これは Volt で一般的に使われるパターンです。コントローラーが利用するモデルを設定するには以下のいずれかの方法を使います。 4 | 5 | 1. コレクションモデルの名前を示すシンボル: 6 | 7 | ```ruby 8 | module Main 9 | class TodosController < Volt::ModelController 10 | model :page 11 | # ... 12 | end 13 | end 14 | ``` 15 | 16 | 2. メソッド内での `self.model=` の呼び出し: 17 | 18 | ```ruby 19 | module Main 20 | class TodosController < Volt::ModelController 21 | def initialize(*args) 22 | # 必ず *args を設定し、super を呼び出してください 23 | super 24 | 25 | self.model = :page 26 | end 27 | end 28 | end 29 | ``` 30 | 31 | モデルが設定されると、存在しないメソッドの呼び出しはすべてそのモデルに対してプロキシされます。これによって、ビューの中でバインディングを行う際に、毎回モデルのオブジェクトを指定しなくても済むようになっています。また、現在設定されているモデルから変更したときにビューが自動的に更新されるのも、この仕組みがあるためです。 32 | 33 | ModelController 内で `#model` を実行したときの戻り値は現在設定されているモデルとなります。 34 | 35 | [提供するコレクション](提供するコレクション) の節に、利用可能なコレクションモデルのリストが記載されています。 36 | 37 | また、自分で作成したオブジェクトをモデルとして提供することも可能です。 38 | 39 | 上記した例において、TodosController に定義されていないメソッドは、設定されているモデルにそのまま送られます。```views/{コントローラー名}``` フォルダのすべてのビューにおいて、そのバインディングの中にある Ruby コードを実行する対象はこのコントローラーとなります。このことは、```self``` に対する呼び出しは (それが暗黙であっても、```self``` をつけて明示したものであっても)、(コントローラーを経由して) モデルを対象とすることを意味しています。このことによって、モデルの扱いに関するメソッドをコントローラーに追加したり、ビューに対して追加のメソッドを提供することが可能になっています。 40 | 41 | Volt は MVC アーキテクチャよりも MVVM アーキテクチャに近いものです。そこでのコントローラーとは、ビューへのデータの受け渡しを行うものではなく、ビューのコンテキストを表すものだと言えます。```Volt::ModelController``` を使うと、コントローラーは自分の扱うことのできないメソッドを自動的にモデルに引き継ぎます。このことは利便性を高めてくれます。なぜなら、コントローラーにモデルをセットし、バインディングのメソッドから直接そのプロパティにアクセスすることが可能であるからです。例えば、```{{ model._name }}``` と書くのではなく、```{{ _name }}``` とすることができます。 42 | -------------------------------------------------------------------------------- /ja/docs/debugging.md: -------------------------------------------------------------------------------- 1 | # デバッグ 2 | 3 | ## ソースマップ 4 | 5 | Volt は (Opal によって) ソースマップがデフォルトで有効になっています。そのため、Chrome や Firefox の開発者ツールでスタックトレースを確認することが可能で、Ruby のファイル名と行番号が表示されます。ファイル名をクリックすることで、オリジナルの Ruby ファイルを確認することができます。また、通常の JavaScript の場合と同じように、ブレークポイントを設定してステップ実行することが可能です。ブラウザ内の irb も動作します。 6 | 7 | Volt 0.9.5.pre3 以降では、development モードではソースマップがデフォルトで有効になっています。もしこれを無効にしたい場合は以下のようにします: 8 | 9 | ```MAPS=false bundle exec volt server``` 10 | 11 | パフォーマンス上の理由から、Opal と Volt のコードはマッピングされません。これはページの読み込み時間の短縮のためです。すべてのファイルに対してマッピングを有効にしたい場合は以下のようにします: 12 | 13 | ```MAPS=all bundle exec volt server``` 14 | 15 | ### フレームワークのブラックボックス化 16 | 17 | ソースマップを利用するとき、ステップ実行の際に大量の余計なファイルがスタックトレースに現れることがあります。フレームワークのブラックボックス化によって、Volt や Opal をネイティブコードのように扱うことができるので、それらのファイルを無視することができます。以下のブラックボックスのチェックを追加すれば、Volt と Opal がブラックボックス化されます。 18 | 19 | ``` 20 | /assets/volt/volt/app\.js$|/assets/js/volt_watch\.js$|/assets/js/volt_js_polyfills\.js$ 21 | ``` 22 | -------------------------------------------------------------------------------- /ja/docs/delayed_rendering.md: -------------------------------------------------------------------------------- 1 | # 遅延レンダリング 2 | 3 | ```self.model = ...``` が呼び出され、モデルが Promise にセットされると、コントローラーはレンダリングされる前に Promise が解決されるのを待ちます。Volt::ModelControllers には ```loaded?``` というメソッドがあり、レンダリングされる際にビューからそれがチェックされます。レンダリングする前に、ビューは ```loaded?``` が true を返すまで待ちます。これによって、モデルがロードされたかどうかをチェックする必要がなくなり便利です。モデルを Promise にアサインしたときには、準備ができているかどうかについてビューがレンダリングを開始する前に把握することができます。 4 | 5 | 例えば、以下のようにしたとします。 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 | 上記の例で、ビューバインディングが (もしくはタグ) が index.html のレンダリングを開始したとき、コントローラーのインスタンスを生成し、それから ```#index``` を呼び出します。次に、ビューバインディングは、index.html ファイルをレンダリングする前に、Promise が解決されるのを待ちます。その後、```#index_ready``` が実行されます。これによって、レンダリングの前にデータを待つことをシンプルに行えるようになっています。 18 | -------------------------------------------------------------------------------- /ja/docs/dependencies.md: -------------------------------------------------------------------------------- 1 | # 依存関係 2 | 3 | 別のコンポーネントから [タグ](#tags) (詳しくは後述) を利用することができます。そのためには、そのソースコンポーネントを、使用したいコンポーネント側から require しておく必要があります。これは ```config/dependencies.rb``` ファイルで指定します。単純に 4 | 5 | ```ruby 6 | component 'component_name' 7 | ``` 8 | 9 | のようにファイルに追加してください。 10 | 11 | 依存関係は Ruby の ```require``` と同様の働きをしますが、コンポーネント全体を対象とする点が異なります。 12 | 13 | 外部にホストされている JS ファイルをコンポーネントからインクルードしたいことがあるかもしれません。その場合は、以下のように 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 | 実際には、現在のところ jquery と bootstrap はデフォルトでインクルードされるようになっていることに注意してください。```javascript_file``` と ```css_file``` でインクルードされた依存関係は、dependencies.rb ファイルに記載されている順序にしたがって、正しい場所にあるコンポーネントのアセットに mix-in されます。 21 | -------------------------------------------------------------------------------- /ja/docs/each_binding.md: -------------------------------------------------------------------------------- 1 | # Each バインディング 2 | 3 | オブジェクトのイテレーション操作のために、```each``` バインディングを利用することができます。 4 | 5 | ```html 6 | {{ _items.each do |item| }} 7 |

    {{ item }}

    8 | {{ end }} 9 | ``` 10 | 11 | 上記では、```_item``` が配列だった場合、```item``` に配列の各要素の値がセットされ、ブロックはその要素それぞれに対してレンダリングを行います。 12 | 13 | .each_with_index を実行すると、ブロック内のローカル変数としてインデックス値を利用できます。 14 | 15 | ```html 16 | {{ _items.each_with_index do |item, index| }} 17 |

    {{ index }}. {{ item }}

    18 | {{ end }} 19 | ``` 20 | 21 | 例えば、```['one', 'two', 'three']``` という配列の場合であれば、以下のように出力されます。 22 | 23 | 0. one 24 | 1. two 25 | 2. three 26 | 27 | ゼロオフセットを修正したければ ```{{ index + 1 }}``` としてください。 28 | 29 | 配列の要素が追加または削除された場合には、```each``` バインディングは自動的に要素を DOM に追加、もしくは DOM から削除します。 30 | 31 | ## インデックスの利用 (with index) 32 | 33 | バインディングはそれぞれ .each_with_index をサポートしています。 34 | 35 | ```html 36 | {{ _items.each_with_index do |item, index| }} 37 |

    {{ index }}. {{ item.name }}

    38 | {{ end }} 39 | ``` 40 | 41 | ## 現在の制限事項 42 | 43 | 現在のところ、バインディングの .each には多くの制限があります。(それに対して対応中です) 配列のみを扱うことができて、ハッシュを扱うことはできません。ハッシュを使いたい場合は、まず配列に変換する必要があります。また、引数を1つしかとることができません (.each_with_index の場合を除く) 。 44 | -------------------------------------------------------------------------------- /ja/docs/environment_options.md: -------------------------------------------------------------------------------- 1 | # Environment オプション 2 | 3 | config/app.rb で指定するオプションに加えて、Volt では、インスタンス変数を利用して、いくつかのインスタンスに固有のオプションを構成することができます。 4 | 5 | | 名前 | 詳細 | 6 | |------------------------|-----------------------------------------| 7 | | VOLT_ENV | Volt.env の値を設定します。この値はアプリケーションの様々な箇所で利用されます。| 8 | | RACK_ENV | これも、Volt.env を設定するのに利用します。 | 9 | | NO_MESSAGE_BUS | メッセージバスを無効にします。これにより、Volt インスタンス間で更新を伝え合うことができなくなりますが、デバッグの際に有用です。 | 10 | | NO_FORKING | "フォークサーバー" は MRI での開発でコードの再読み込みをするために使用します。(コネクションのために子プロセスをフォークし、コードの変更時に再度フォークして kill されます)。フォークを無効にすると、タスク、HttpController、ルーティングなどでのコードの再読み込みができなくなります。| 11 | | WEBSOCKET_PING_TIME | 有効な場合、WebSocket のコネクションは ```WEBSOCKET_PING_TIME``` ごとに ping を送信します。| 12 | | NO_WEBSOCKET_PING | WebSocket ping は (DYNO env が有効な) Heroku のみで有効で、Heroku がアイドル状態のコネクションを切断することを回避します。これは、WebSocket ping を強制的に無効にします。 | 13 | | SKIP_BUNDLER_REQUIRE | Gemfile の自動 require を無効にします。この機能は現在 experimental です。| 14 | | POLL_FS | Volt はリッスン用の Gem を利用して自動更新のためにファイルシステムの変更検知を行いますが、変更が正しく検知できない場合があります。そのような場合には、POLL_FS=true を設定することで変更を poll することが可能です。例えば、ネットワーク越しにファイルを共有している場合などにこの状況が発生します。| 15 | | DB_NAME | Volt.config.db_name と同様 | 16 | | DB_HOST | Volt.config.db_host と同様 | 17 | | DB_PORT | Volt.config.db_port と同様 | 18 | | DB_DRIVER | Volt.config.db_driver と同様 | 19 | | DB_URI | Volt.config.db_uri と同様 | 20 | 21 | -------------------------------------------------------------------------------- /ja/docs/escaping.md: -------------------------------------------------------------------------------- 1 | ## エスケープ 2 | 3 | {{ と }} をバインディングの目的以外で使いたい場合には、3連の波括弧で囲んでください。その中ではエスケープが行われるため、バインディングとして処理されることはありません。 4 | 5 | 6 | ```html 7 | {{{ bindings look like: {{this}} }}} 8 | ``` 9 | -------------------------------------------------------------------------------- /ja/docs/event_bindings.md: -------------------------------------------------------------------------------- 1 | # Event バインディング 2 | 3 | Volt のビューでは、DOM にイベントをバインドすることができるので、コントローラー側でメソッドを実行することが可能です。そのためには、e-{イベント名} の属性を付与してください: 4 | 5 | ```html 6 | 7 | ``` 8 | 9 | 上記の例では、ボタンがクリックされた際にコントローラーの alert メソッドが実行されます。Volt は内部的には jQuery を利用していますので、jQuery のイベントがサポートされています。1つのタグに対して複数のイベントをバインドすることも可能です。 10 | 11 | ```html 12 | 13 | ``` 14 | 15 | ```event``` というローカル変数を渡すことで、発生した jQuery イベントのオブジェクトをコントローラーに渡すこともできます。 16 | 17 | ```html 18 | 19 | ``` 20 | 21 | コントローラー側では、以下のようにして jQuery イベントのオブジェクトにアクセスします: 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 | イベントのオブジェクトは Volt::JSEvent のインスタンスとなります。そのインスタンスは以下のメソッドを持ちます: 34 | 35 | ### .js_event 36 | 37 | jQuery イベントのオブジェクトをそのまま返します。返されるオブジェクトは JavaScript のオブジェクトで Opal のオブジェクトではないので、使用する場合はバッククォート (アクサングラーヴ) か Native を使う必要があります。 38 | 39 | ### .key_code 40 | 41 | 押されたキーに対応する int の値を返します。 42 | 43 | ### .stop! 44 | 45 | jQuery イベントに対して stopPropagation() を実行します。 46 | 47 | ### .prevent_default! 48 | 49 | jQuery イベントに対して preventDefault() を実行します。 50 | 51 | ### .target 52 | 53 | 対象の DOM ノードを返します。 54 | -------------------------------------------------------------------------------- /ja/docs/fields.md: -------------------------------------------------------------------------------- 1 | # フィールド 2 | -------------------------------------------------------------------------------- /ja/docs/flash_collection.md: -------------------------------------------------------------------------------- 1 | # Flash コレクション 2 | 3 | Flash コレクションを使うと、クライアント側のユーザーに対して簡単に情報を表示することができます。Flash は (デフォルトで) ```successes```、```notices```、```warnings```、そして ```errors``` と 4種類の ArrayModel を含んでいます。これらのコレクションが追加されたとき、```"alert alert-{{ ..コレクション名..}}"``` というクラスの div 要素にメッセージが表示されます。 4 | 5 | ### 例 6 | 7 | ```ruby 8 | flash._successes << "Your data has been saved" 9 | ``` 10 | 11 | ```ruby 12 | flash._errors << "Unable to save because your not on the internet" 13 | ``` 14 | 15 | Flash のサブコレクションに追加された文字列は、5秒後に削除されます。デフォルトでは、クリックすることで flash メッセージを消すことも可能です。 16 | 17 | # Local Store コレクション 18 | 19 | ```local_store``` コレクションは、データをブラウザーのローカルストレージに永続化します。 20 | 21 | # Cookies コレクション 22 | 23 | ```cookies``` コレクションは、データをブラウザーの cookie に保存します。割り当てられたプロパティはそれぞれ、同盟の cookie に保存されます: 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 | Cookie コレクションでは、値は文字列に変換されます。説明の追加などのオプション機能については todo 項目としてあがっています。現在のところ、cookie の有効期間は1年間に設定されています。 35 | 36 | 37 | -------------------------------------------------------------------------------- /ja/docs/forking_server.md: -------------------------------------------------------------------------------- 1 | # Forking Server 2 | 3 | development モードにおいて、Volt はアプリケーションのコードが変更された際にリロードする方法を必要とします。変更を検知するために、Volt は ```listen``` gem を使って、OS のファイル変更 API を利用し、変更に対してリッスンしています。development 環境、そして Linux または OS X で、かつ MRI を使用している場合は、Volt は ForkingServer としてアプリケーションを実行します。ForkingServer は Volt の Rack アプリケーションの背後で動作し、あらゆる Rack Web サーバー (thin、puma など) と一緒に動作することが可能です。 4 | 5 | ## 仕組み 6 | 7 | Forking Server の背景となっているのは、アプリケーションに必要な依存関係にあるほとんどのもの (Ruby、Volt、Gem) をロードし、それから、分離した「子」プロセスにフォークする、という発想です。子プロセスの中で、アプリケーションのコードが読み込まれます。リクエストが親サーバーに届くと、それを子プロセスに (現在は DRb を利用して) 渡します。子プロセスはリクエストに対して返答し、その結果を親サーバーに返し、それが最終的にはブラウザーに送られます。 8 | 9 | コードを変更した場合、その変更は親プロセスによって検知されます。もしその変更によってコードのリロードが必要であれば、親プロセスは子プロセスを kill します。それから、親プロセスは再度自分自身をフォークし、新しい子プロセスを生成します。それによって、アプリケーションのコードが再度ロードされます。 10 | 11 | ## なぜ速いのか 12 | 13 | アプリケーションのコードは、Ruby や Volt、そしてすべての依存関係にある Gem と比較すると小さいものなので、変更後のアプリケーションの起動は非常に高速です。「重たい」ところはすでにロード済みです。Linux と OS X はどちらも「コピーオンライト」のフォークをサポートしています。これは、プロセスのフォークの際に、元プロセスのメモリの完全なコピーを作るのではなく、メモリのブロックが変更されるまではコピーされないことを意味しています。アプリケーションコードのメモリの大部分は変更されないので、フォークは非常に高速に行えます。 14 | 15 | ## 利点 16 | 17 | フォークによるリローディングが他の方法より優れている主な点は、コードのリロードによって失われるものがない点です。例えば Rails では、クラスは定数の定義を消すことによってアンロードされ、それから改めてファイルを require します。これが正しく動作するためには、require するファイルが、期待する命名規則にしたがっている必要があります。しかし、主な問題として、クラスの再読み込みが副作用を伴う、というものがあります。Ruby では、その副作用が目に見えないことも多いです (例えば、クラスの継承を行うと ```#inherited``` が呼び出されます) 。Forking Server を使うと、アプリケーションは、まるで0の状態から起動したときのように (ただし、その何分の1という時間で)、常に同じ状態になります。 18 | 19 | ## 他のプラットフォームやランタイム 20 | 21 | ForkingServer の大きな制限は、フォークの存在しない Windows や Jruby では動作しないということです。Windows と Jruby をサポートするための代替のリローディング機構について計画中です。 22 | -------------------------------------------------------------------------------- /ja/docs/getting_view_dom_nodes.md: -------------------------------------------------------------------------------- 1 | # ビューの DOM ノードを取得する 2 | 3 | Volt のバインディングだけで数多くのことができます。例えば、ビューの DOM を直接変更したいことがあるでしょう。DOM の直接操作は2つのパートに分けられます。 4 | 5 | - 処理開始のタイミング 6 | - コンテナの取得 7 | 8 | ## 処理開始のタイミング 9 | 10 | Volt はクライアント上でページをレンダリングするため、jQuery で ```$(document).ready``` などを利用することはできません。(※Volt は jQuery を同梱しています) その代わりに、{action}_ready メソッドを使用してください。(詳細は [コールバックとアクション](callbacks_and_actions.md) を参照してください) 大きなビューの各パートに対してトリガーを設定するには、複数のコントローラー/ビューを使うようにビューを分割する必要があります (また、そうすべきです)。 11 | 12 | ## DOM ノードの取得 13 | 14 | 他の多くのフレームワークと異なり、Volt のビューはルートに複数のノードを持つことができます。 15 | 16 | ```html 17 | <:Item> 18 | {{ label }} 19 | Edit 20 | ``` 21 | 22 | ### ビューの DOM レンジ 23 | 24 | 以下のケースでは、ビューの「ノード」を単純に取得することができません。その代わりに、Volt は [Dom レンジ](https://developer.mozilla.org/en-US/docs/Web/API/Range) を利用してビュー内のノードを表現します。ビューのノードのレンジを得るには、コントローラー上で ```dom_nodes``` を実行してください。 25 | 26 | ### コンテナノード 27 | 28 | しかしながら、DOM レンジを扱うのは厄介です。理由は、(jQuery などの) ほとんどのライブラリはノードを扱うようになっているからです。近接しているノードを取得するには、コントローラー内で ```container``` を使用してください。(より役立つメソッドもありますので、もう少し読み進めてください)。 29 | 30 | ### 最初の要素 31 | 32 | 上記の例には2つの TD がありましたが、これはテーブルを返します。テーブルは、ビューに1つ以上の「ルート」ノードがある例において唯一の共通のノードです。以下のように、ビューのルートに1つのノードしかない場合を考えてください: 33 | 34 | ```html 35 | <:Post> 36 |
    37 |

    {{ title }}

    38 |

    {{ body }}

    39 |
    40 | ``` 41 | 42 | この例では、section タグがビュー全体の単一のルートノードです。しかし、空白文字の影響によって、厳密にはそれ以外のノードも存在します。したがって、```container``` は section の上位ノードを返します。もし、ビューに1つのノードしかないことがわかっているのなら、```first_element``` を使って、ビューの最初の要素のノードを取得できます。(要素のノードはタグです) 43 | 44 | 45 | -------------------------------------------------------------------------------- /ja/docs/if_binding.md: -------------------------------------------------------------------------------- 1 | # If バインディング 2 | 3 | ```if``` バインディングは、基本的な制御文を提供します。 4 | 5 | ```html 6 | {{ if some_check? 7 |

    render this

    8 | {{ end }} 9 | ``` 10 | 11 | ブロックは ```{{ end }}``` で閉じます。 12 | 13 | ```if``` バインディングがレンダリングされるときは、「if」 に続く Ruby コードが実行されます。そして、そのコードが真である場合にのみ、後続のコードがレンダリングされます。```if``` 条件に含まれるデータの変更はすべて、レンダリングされるブロックを更新します。 14 | 15 | また、If バインディングは ```elsif``` と ```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 もサポートしています。 30 | 31 | ```html 32 | {{ unless some_check? 33 |

    render this when some_check? is false

    34 | {{ end }} 35 | ``` 36 | -------------------------------------------------------------------------------- /ja/docs/lib.md: -------------------------------------------------------------------------------- 1 | # Lib 2 | 3 | Volt クライアントとサーバー両方のためのフレームワークです。Gem はクライアントとサーバーの両方で利用されますが、多くの Gem はクライアントとサーバーで互換性がありません。この理由 (および、以下に記載する理由) のために、Volt が起動時にすべての Gem を require することはありません。 4 | 5 | ### クライアントとサーバー両方で使う Gem 6 | 7 | いつも通りに Gemfile と Bundler を使用してください。ただ、上記したように、明示的に Gem を **require** する必要があります。 8 | クライアント **と** サーバー **の両方** で動作する Gem は、```config/app.rb``` で require するのがよいでしょう。 9 | 10 | ### クライアントのみで使う Gem 11 | 12 | ブラウザー上で利用できる Gem もどんどん増えています。Opal の Gem は通常、opal- でプレフィクスされています。 13 | 例えば、ブラウザーや DOM の API を利用するための opal-browser や opal-jquery が良い例でしょう。また、opal-pixi や opal-phantom もあります。 14 | 15 | opal-browser などの Gem を利用するには、以下のようにして条件ブロックの中で require してください。そのためには以下のように記述します。 16 | 17 | ```ruby 18 | if RUBY_PLATFORM == 'opal' 19 | require "browser" 20 | end 21 | 22 | ``` 23 | 24 | また、```config/initializers/client/gems.rb``` といった initializer を用意することも可能です。 25 | 26 | ```ruby 27 | require "browser" 28 | ``` 29 | 30 | プラットフォームテストを省略できる場合にはこの方法が有効でしょう。 31 | 32 | #### Opal のロードパス 33 | 34 | クライアントのみで使用する Gem の場合、Opal に Gem のソースを探す場所を教える必要があります。これは、 ```config/dependencies.rb``` で以下のようにします。 35 | 36 | ```ruby 37 | Opal.use_gem("browser") 38 | ``` 39 | 40 | ### クライアントのみで使う Gem 41 | 42 | ブラウザーでは動作しない Gem もあります。例えば、Opal は C エクステンションを一切サポートしていません。また、タスクで利用される Gem もサーバー側でのみ読み込まれるべきです。クライアントがネットワークの帯域を余計に利用することを避ける意味でも、ブラウザーが不要な Gem の読み込みを避けるのは好ましいものです。 43 | 44 | クライアントの場合と同様に、条件ブロックの中で require してください。 45 | 46 | ```ruby 47 | if RUBY_PLATFORM != 'opal' 48 | require "nokogiri" 49 | end 50 | ``` 51 | 52 | ```config/initializers/server/gems.rb``` のような initializer を利用することも可能です。 53 | 54 | ```ruby 55 | require "nokogiri" 56 | ``` 57 | 58 | ### Bundler の設定 59 | 60 | Gemfileに書かれたGemが自動的にVoltにrequireされることはありません。この動作は以下の理由によるものです。 61 | 62 | 1. 起動時のパフォーマンスに非常に大きな影響を与えるからです。特にこれは規模が大きくなるにしたがって顕著になります。(これはRailsに対する不満として最もよく耳にするものの1つです)。 dependencies.rbに含まれるコンポーネントGemは、デフォルトでアプリケーションにインクルードされます。 63 | 2. 不要なコードが読み込まずに済むからです。 64 | 3. どの Gem がクライアントのみで利用されるか、ということを指示することが不可能であるためです。 65 | 66 | 更なる理由を知りたければ、[5 reasons to avoid Bundler.require](http://myronmars.to/n/dev-blog/2012/12/5-reasons-to-avoid-bundler-require) を参照してください。 67 | 68 | どうしてもGemを自動的にrequireしたい場合には、```config/app.rb``` の先頭に以下を記載してください。 69 | 70 | ```ruby 71 | Bundler.setup 72 | ``` 73 | -------------------------------------------------------------------------------- /ja/docs/long_running_processes.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ja/docs/long_running_tasks.md: -------------------------------------------------------------------------------- 1 | # Long Running Tasks 2 | -------------------------------------------------------------------------------- /ja/docs/message_bus.md: -------------------------------------------------------------------------------- 1 | # メッセージバス 2 | 3 | Volt は、ある Volt クラスター (同一のデータベースに接続しているインスタンス) のすべての Volt インスタンス (server/console/runner) 間の pub/sub インターフェースを提供するメッセージバスを持っています。Volt は PeerToPeer のメッセージバスを持っていますが、他のメッセージバスを作成したり、利用することができます。 4 | 5 | メッセージバスは、インスタンス間でモデルの更新をプッシュするために Volt が内部的に使用しています。更新は、Volt インスタンスに接続しているすべてのブラウザーに送信されます。これによって Volt は、ライブアップデートのプッシュ機能を維持したまま、スケールアウトすることを容易にしています。 6 | 7 | ## PeerToPeer バス 8 | 9 | デフォルトの peer to peer バスはデータベースを利用して、インスタンスが構成するソケットサーバーの IP とポーとのリストを同期します。(※構成の詳細は、生成された ```config/app.rb``` のコードを参照してください) サーバーがネットワーク越しに疎通可能な限り、すべては「*just work*™」するはずです。(※多くのデプロイ環境で、プライベートクラウド内でサーバーは相互に通信できます) もしサーバーの限られたポートしか開かれていない場合は、```config/app.rb``` で利用するポートを指定することができます。 10 | 11 | ## アプリケーションコードでのメッセージバス 12 | 13 | メッセージバスはアプリケーションのコードで使用することもできます。メッセージバスは ```subscribe``` と ```publish``` のメソッドを提供します。 14 | 15 | **TODO: メッセージバスについての記載を追加する** 16 | 17 | ## カスタムメッセージバス 18 | 19 | ```lib/volt/message_bus/base_message_bus.rb``` に ```BaseMessageBus``` クラスを実装することで、独自のメッセージバスを用意することができます。それを ```config.message_bus.bus_name = 'name_of_class'``` として設定します。```name_of_class``` はクラス名をアンダースコア表記にしたものです。独自バスの実装に関する詳細は ```base_message_bus.rb``` を参照してください。 20 | -------------------------------------------------------------------------------- /ja/docs/middleware.md: -------------------------------------------------------------------------------- 1 | # ミドルウェア 2 | 3 | Volt はデータベースとの通信やタスクに WebSocket を利用しますが、HttpController には Rack を利用して WebSocket のコネクションを設定しています。独自のミドルウェアを追加することが可能です。コンポーネントの config/initializers/boot.rb で、以下を設定することができます: 4 | 5 | ```ruby 6 | Volt.current_app.middleware.use(SomeMiddleware) 7 | ``` 8 | 9 | ```Volt.current_app.middleware``` は ```Rack::Builder``` のインスタンスのように振る舞う ```Volt::MiddlewareStack``` を返します。また、以下のメソッドをサポートしています: 10 | 11 | - ```use``` 12 | - ```run``` 13 | 14 | (※ミドルウェアの順序を設定するためのメソッドが追加される予定です) 15 | 16 | 注意: 現在のところ、ミドルウェアスタックのどこでミドルウェアがロードされているかを特定する方法がありません。(もしこの機能の実装に興味があれば、Gitter で @ryanstout にお知らせください。おそらく難しいものではないでしょう) 17 | -------------------------------------------------------------------------------- /ja/docs/model_classes.md: -------------------------------------------------------------------------------- 1 | ## Model クラス 2 | 3 | デフォルトでは、すべてのコレクションは ```Volt::Model``` クラスを使用します。 4 | 5 | ```ruby 6 | page._info!.class 7 | # => Volt::Model 8 | ``` 9 | 10 | 標準の Model クラスの代わりに、自分でクラスを用意してそれを読み込むことも可能です。このとき、モデルとするクラスは ```Volt::Model``` を継承している必要があります。クラスは /app/{component}/models フォルダに格納します。例えば、```app/main/info.rb``` などです。 11 | 12 | ```ruby 13 | class Info < Volt::Model 14 | end 15 | ``` 16 | 17 | これで、```_info``` というサブコレクションにアクセスすることができます。それは ```Info``` のインスタンスとして読み込まれるものです。 18 | 19 | ```ruby 20 | page._info!.class 21 | # => Info 22 | ``` 23 | 24 | これによって、コレクションにカスタムメソッドやバリデーションを設定することが可能です。 25 | 26 | ## ArrayModel クラス 27 | 28 | ```Volt::ArrayModel``` の代わりに読み込まれるクラスをモデルのフォルダに追加することもできます。通常、store._items のような操作は ```Volt::ArrayModel``` のインスタンスを返しますが、もし models/items.rb クラスを作る場合は以下のようになります。 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 | コレクションへのアクセスがあったとき、上記が自動的にロードされます。 37 | -------------------------------------------------------------------------------- /ja/docs/model_states.md: -------------------------------------------------------------------------------- 1 | # モデルの状態 2 | 3 | モデルはクライアント上で動作しますが、クライアントとサーバー間にはレイテンシーが存在しているため、Volt では、モデルがサーバーに同期されているかを確認するためのいくつかの「状態 (state)」メソッドを用意しています。バッファーから保存した場合、.save! が返す Promise はデータがサーバー側に保存されてから解決されます。したがって、以下の状態メソッドは主に、ユーザーに対して状況を知らせるために使います。 4 | 5 | ## 保存状態 6 | 7 | すべてのストアモデル (もしくはバッファ) に対して、.saved_state を実行することができます。その結果は以下です: 8 | 9 | | 状態 | 詳細 | 10 | |-----------|-----------------------------------------------------------------------| 11 | | not_saved | モデルはサーバーに保存されていません | 12 | | saving | モデルは保存処理中です | 13 | | saved | モデルはサーバーに保存され、クライアントのデータは最新の状態です | 14 | 15 | ## 読み込み状態 16 | 17 | | 状態 | 詳細 | 18 | |-----------|-----------------------------------------------------------------------| 19 | | not_loaded| ArrayModel は読み込まれておらず、読み込むためにモデルに依存しているものもありません (これは Volt の内部状態なので外から見ることはありません) | 20 | | loading | ArrayModel はデータを読み込み中です | 21 | | loaded | データは読み込まれ、サーバーと同期しています | 22 | | dirty | データは読み込まれていますが、サーバーと同期されていません。この状態は、バインディングがデータをリアクティブにリッスンしていない場合や、データが何も発生させない場合に発生します | 23 | 24 | ## 例 25 | 26 | モデルがロードされているかどうかは、以下のように確認できます。 27 | 28 | ```html 29 | {{ if todo.load_state == :loading }} 30 |

    Loading Todo...

    31 | {{ elsif todo.load_state == :loaded }} 32 |

    {{ todo.label }}

    33 | {{ end }} 34 | ``` 35 | 36 | また、Volt は読み込み状態が```:loaded``` であるかをチェックするための便利なメソッドを提供しています。 37 | 38 | ```html 39 | {{ if todo.loaded? }} 40 |

    {{ todo.label }}

    41 | {{ end }} 42 | ``` 43 | 44 | ## モデルの遅延レンダリング 45 | 46 | コントローラーで ```self.model = ``` を Promise と設定した場合、ビューは Promise が解決されるまではレンダリングされないことを覚えておいてください。(詳細は[遅延レンダリング](docs/delayed_rendering.md) for more info)を参照してください。 47 | -------------------------------------------------------------------------------- /ja/docs/nil_models.md: -------------------------------------------------------------------------------- 1 | ## Nilモデル 2 | 3 | 利便性を高めるために、例えば ```page._info``` を実行した時には ```NilModel``` を返すようになっています。(このとき、. _info はまだ設定されていないものとします。)NilModel は将来的に利用するモデルのプレースホルダーです。NilModel があることによって、わざわざ中間の値を初期化することなく、深くネストされた値のバインドをすることが可能になっています。 4 | 5 | ```ruby 6 | page._info 7 | # => 8 | 9 | page._info._name 10 | # => 11 | 12 | page._info._name = 'Ryan' 13 | # => "Ryan"}>}> 14 | ``` 15 | 16 | ただし、1つ注意しておくべきことは、NilModel は「真」の値であるということです。(Ruby では nil と false のみが false として扱われます。)分かりやすくするために、NilModel に対して ```.nil?``` を実行すると true を返すようになっています。 17 | 18 | 真偽チェックを利用するよくあるケースとして、```||``` (論理和) を使ってデフォルト値を設定するものがあります。Volt はこれと同様の働きをするメソッド ```#or``` を提供します。これは NilModel に対しても有効です。 19 | 20 | 以下のようには書きません。 21 | 22 | ```ruby 23 | a || b 24 | ``` 25 | 26 | 以下のように書きます。 27 | 28 | ```ruby 29 | a.or(b) 30 | ``` 31 | 32 | 加えて、```#and``` は ```&&``` と同様に働きます。```#and``` と ```#or``` によって、NilModel も含めて、初期値の扱いを簡単にすることができます。 33 | 34 | -- TODO: Document .true? / .false? 35 | -------------------------------------------------------------------------------- /ja/docs/provided_collections.md: -------------------------------------------------------------------------------- 1 | ## 提供するコレクション 2 | 3 | 前述の通り、Volt にはコントローラーからアクセス可能な、豊富なコレクションモデルがデフォルトで用意されています。そして、そのそれぞれが異なる場所に保存されます。 4 | 5 | | 名前 | 保存場所 | 6 | |-------------|--------------------------------------------------------------------| 7 | | page | page は一時的なデータ保存場所を提供します。そのページが存在している間だけ残ります。| 8 | | store | store はバックエンドのデータベースと同期し、クエリメソッドを提供します。| 9 | | local_store | ブラウザのローカルストレージです。| 10 | | params | パラメータと URL の構造を保存しています。どのように URL に表示するかはルーティングの設定によります。(詳細は「ルート」を参照してください) | 11 | | flash | 代入された文字列がページの先頭に表示され、ユーザーによるページの移動で消去されます。| 12 | | cookies | cookie に値を保存します。直接プロパティをアサインすることはできますが、サブコレクションに含めてアサインすることはできません。| 13 | | controller | 現在のコントローラーのためのモデルです。| 14 | 15 | **上記以外のストレージについても計画中です。** 16 | -------------------------------------------------------------------------------- /ja/docs/provided_components.md: -------------------------------------------------------------------------------- 1 | # 提供するコンポーネント 2 | 3 | Volt は、Web 開発を楽に進めるためにいくつかのコンポーネントを提供しています。 4 | 5 | ## Notices (通知) 6 | 7 | Volt は ```<:volt:notices />``` を自動的にビューに設定します。このコンポーネントによって、以下の「通知」を表示することができます: 8 | 9 | 1. flash メッセージ 10 | 2. 試行接続状態。(接続が切れた場合に、「なぜ接続断が発生したのか」と「再接続を試行する時間」をユーザーに通知します)。 11 | 3. (developmentモードでの) コードの変更による再読み込み通知 12 | 13 | ## Flash 14 | 15 | Flash モデルのどのコレクションに対してもメッセージを追加することができます。Flash モデルは、上記の notices (通知) コンポーネントの一部として提供されています。 16 | 17 | それぞれのコレクションが異なるタイプの「flash」を表しています。一般的なものとして ```_notices```、```_warnings```、そして ```_errors``` があります。そして、各コレクションはそれぞれ、flash の表示させ方を変更することができます。例えば、```_notices``` と ```_errors``` を別の色で表示させたいなどの場合が考えられます。 18 | 19 | ```ruby 20 | flash._notices << "message to flash" 21 | ``` 22 | 23 | メッセージは5秒間表示された後に (画面からもコレクションからも) 消えます。 24 | -------------------------------------------------------------------------------- /ja/docs/reactive_accessors.md: -------------------------------------------------------------------------------- 1 | ## リアクティブ アクセサ 2 | 3 | デフォルトの ```Volt::ModelController``` は、自分に見つからないメソッドをそのモデルにプロキシします。しかし時には、追加のデータをリアクティブな状態で、かつコントローラーに保持させて、モデルの外側に持っておく必要があるかもしれません。(普通であれば、別のコントローラーの実装を検討するときかもしれませんが)。こういった場合、```reactive_accessor``` を使用します。それらは ```attr_accessor``` と同様の振る舞いをします。ただし、追跡して評価されるので、代入される値と戻り値はリアクティブに評価された結果となります。 4 | 5 | ```ruby 6 | module Main 7 | class Contacts < Volt::ModelController 8 | reactive_accessor :query 9 | end 10 | end 11 | ``` 12 | 13 | これで、モデルの内外どちらでの変更に対しても```query``` をビューからバインドすることができます。query へのアクセスは追跡され、変更があった際には評価が実行されます。 14 | -------------------------------------------------------------------------------- /ja/docs/requiring_files.md: -------------------------------------------------------------------------------- 1 | # ファイルの require 2 | 3 | もし、`my_awesome_app` がアプリケーションのルートであったとして、`my_awesome_app/app/main/mixins/my_file.rb` というファイルがあって、`main` がコンポーネントである場合、他のファイルからは以下のようにして require することができます。 4 | 5 | ```ruby 6 | require "main/mixins/my_file" 7 | ``` 8 | 9 | つまり、コンポーネントのフォルダからのパスとなります。 10 | -------------------------------------------------------------------------------- /ja/docs/routes.md: -------------------------------------------------------------------------------- 1 | # ルート 2 | 3 | Volt におけるルートは、伝統的なバックエンドのフレームワークのそれとは全く異なるものです。Volt ではデータは Websocket で同期されるため、ルートは2つの異なる理由のために利用されます。Volt は、同一のファイルの中で、2つの異なるタイプのルーティングを提供します。それは ```client``` ルートと HTTP ルート (```get```、 ```post```、 ```put```、 と ```delete```) です。 4 | 5 | ## Client ルート 6 | 7 | Client ルートは、アプリケーションの状態をシリアライズして、分かりやすい形で URL として表現することに使用されます。ページが最初に読み込まれたとき、その URL はルートによってパースされて、パラメータのモデルの値が展開され、その URL にしたがって設定されます。後からパラメータのモデルが更新された場合には、ルートにしたがって URL が更新されます。 8 | 9 | このことは、Volt におけるルートは、「URL からパラメータへ」と「パラメータから URL へ」の双方向で働くものでなければならないことを意味しています。また、リンクがクリックされたとき、新しい URL のレンダリングを行うコントローラーとビューが現在のコンポーネント内 (もしくはインクルードされているコンポートネント内) にあった場合には、そのページの読み込みが行われないことを覚えておいてください。URL は HTML5 history API を使って更新され、パラメータのハッシュはその新しい URL を反映したものになります。パラメータを変更することで、同じ URL に対して異なるビューをレンダリングすることも可能です。 10 | 11 | ## HTTP ルート 12 | 13 | HTTP ルートは、(REST API などのような) HTTP でのアクセスをクライアントに提供するために利用されます。 14 | -------------------------------------------------------------------------------- /ja/docs/routes_file.md: -------------------------------------------------------------------------------- 1 | ## ルートファイル 2 | 3 | ルートは、```config/routes.rb``` ファイルの中で、コンポーネントを基準にして指定します。ルートとは、単純に URL をパラメータにマッピングするものです。 4 | 5 | ```ruby 6 | client "/todos", {view: 'todos'} 7 | ``` 8 | 9 | ルートはパスとパラメータの2つの引数を取ります。新しい URL が読み込まれて、そのパスがルートにマッチしたとき、パラメータはルートに与えるパラメータとして設定されます。特定のパラメータのハッシュは制約として働きます。例えば、空のハッシュであれば、どの URL にもマッチします。マッチしなかったパラメータはクエリパラメータとして設定されます。 10 | 11 | パラメータが変更された場合には、そのパラメータのハッシュがマッチするルートにしたがって URL を設定します。 12 | 13 | また、ルートのパスは、パラメータのコレクションマッピングされるバインディングを含むことができます: 14 | 15 | ```ruby 16 | client "/todos/{{ index }}", view: 'todos' 17 | ``` 18 | 19 | 上記の場合、/todos/* (* はスラッシュ以外のすべて) にマッチする URL はすべて有効なルートとなります。```params._view``` は「todos」に設定され、```params._index``` はパスに含まれる値として設定されます。 20 | 21 | もし ```params._view``` が「todos」であり、かつ ```params._index``` が存在していれば、それはルートにマッチします。 22 | 23 | ルートは、ルートファイル上で上から下に順番にマッチングされます。 24 | 25 | 26 | ### HTTP エンドポイントのためのルート 27 | 28 | [HTTP コントローラー](http_controllers.md) によってHTTPエンドポイントを設定する場合、```get```/```post```/```put```/```patch```/```delete``` キーワードによってルートを指定する必要があります。また、HTTP エンドポイントのルートには「コントローラー」と「アクション」をパラメーターとして指定する必要があります。 29 | 30 | ```ruby 31 | get "/api/todos", controller: 'todos', action: 'index' 32 | ``` 33 | 34 | 上記の場合、TodosController の ```index``` メソッドを実行します。詳しくは [HTTP コントローラー](http_controllers.md)を参照してください。 35 | 36 | RESTful なリソースを作成するためには、下記のルートを設定する必要があります。 37 | 38 | ```ruby 39 | get "/api/todos", controller: 'todos', action: 'index' 40 | post "/api/todos", controller: 'todos', action: 'create' 41 | get "/api/todos/{{ id }}", controller: 'todos', action: 'show' 42 | put "/api/todos/{{ id }}", controller: 'todos', action: 'update' 43 | patch "/api/todos/{{ id }}", controller: 'todos', action: 'update' 44 | delete "/api/todos/{{ id }}", controller: 'todos', action: 'destroy' 45 | ``` 46 | 47 | 追加のパラメーターはコントローラーに渡されます。 48 | 49 | ```ruby 50 | delete "/api/todos/{{ id }}", controller: 'todos', action: 'destroy', safe: true 51 | ``` 52 | 53 | 上記では、```id```/```controller```/```action```/```safe``` パラメーターのハッシュとしてコントローラーに渡されます。 54 | 55 | 「method」を HTTP GET または POST パラメーターとして指定すれば、実際の HTTP メソッドを上書きすることも可能です。 56 | -------------------------------------------------------------------------------- /ja/docs/runnersprocesses.md: -------------------------------------------------------------------------------- 1 | # ランナー/プロセス 2 | 3 | 通常のリクエストのサイクルの外で実行したいコードがあるときには、以下の2つの方法のいずれかで可能です。 4 | 5 | ## 1) ランナー 6 | 7 | 例えば ```app/main/lib/some_runner.rb``` のように lib にコードを格納し、以下のコマンドでそのコードを実行することができます。 8 | 9 | ```bundle exec volt app/main/lib/some_runner.rb``` 10 | 11 | ランナーのコマンドは、.rb ファイルのコード実行する前に、現在のアプリケーションの設定を読み込みます。 12 | 13 | ## 2) アプリケーションの起動 14 | 15 | もし Volt アプリケーションを別のコンテキストでロードする必要がある場合です。例えば、[clockwork](https://github.com/tomykaira/clockwork) Gem を利用する場合や、独自のコマンドを使う Gem を利用する場合は、以下のようにしていつでも Volt アプリケーションを起動できます。 16 | 17 | ```ruby 18 | require 'volt/boot' 19 | Volt.boot(Dir.pwd) 20 | ``` 21 | 22 | ```Volt.boot``` の引数は1つで、Volt アプリケーションのディレクトリのパスを指定します。実行するアプリケーションの Gemfile を使って ```bundle exec``` で実行してください。そうすれば、Volt とその依存関係も読み込むことができます。 23 | -------------------------------------------------------------------------------- /ja/docs/sub_collections.md: -------------------------------------------------------------------------------- 1 | ## サブコレクション 2 | 3 | 他のコレクションと同じように、 モデルは ```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 | 以下のモデルが作成されたことが確認できます。 18 | 19 | ```ruby 20 | store._states 21 | # => #, #]> 22 | ``` 23 | 24 | では、最初の state が含んでいる city が何か確認してみましょう。.first は promise を返すので、._cities の呼び出しも同様に promise を返します。 25 | 26 | ```ruby 27 | store._states.first._cities 28 | # => #, #]>> 29 | ``` 30 | 31 | 先にモデルを作って、後からそれを挿入することも可能です: 32 | 33 | ```ruby 34 | montana = Volt::Model.new({name: 'Montana'}) 35 | 36 | montana._cities.create({name: 'Bozeman'}) 37 | montana._cities.create({name: 'Helena'}) 38 | 39 | store._states.create(montana) 40 | # => #> 41 | ``` 42 | -------------------------------------------------------------------------------- /ja/docs/tag_attributes.md: -------------------------------------------------------------------------------- 1 | # タグの引数と属性 2 | 3 | 他の html タグと同様に、Voltのタグには属性を指定することができます。指定した属性はオブジェクトに変換され、コントローラーの initialize メソッドの第一引数として渡されます。標準的な Volt::ModelController の initialize は、そのオブジェクトを ```#attrs``` でアクセス可能な```attrs``` プロパティに代入します。これによって指定した属性へ容易にアクセスすることが可能になっています。 4 | 5 | ```html 6 | <:Body> 7 |
      8 | {{ _todos.each do |todo| }} 9 | <:todo name="{{ todo._name }}" /> 10 | {{ end }} 11 |
    12 | 13 | <:Todo> 14 |
  • {{ attrs.name }}
  • 15 | ``` 16 | 17 | 属性を個別に指定する代わりに、```model``` 属性に Model オブジェクトを指定することもできます。そのモデルはコントローラーの利用するモデルとして設定されます。 18 | 19 | ```html 20 | <:Body> 21 |
      22 | {{ _todos.each do |todo| }} 23 | <:todo model="{{ todo }}" /> 24 | {{ end }} 25 |
    26 | 27 | <:Todo> 28 |
  • 29 | {{ _name }} - 30 | {{ if _complete }} 31 | Complete 32 | {{ end }} 33 |
  • 34 | ``` 35 | -------------------------------------------------------------------------------- /ja/docs/tags.md: -------------------------------------------------------------------------------- 1 | # タグ 2 | 3 | タグ (以前はコントロールと呼ばれていたものです) によって、ビューをバインディングするのと同じように、ビューとコントローラーをレンダリングすることができます。ただし、属性を引数として設定できるという点で大きく異なります。 4 | 5 | タグは ```:``` (コロン) で始まることで、通常の html タグと区別されます。通常の html タグと同様に、タグは閉じる必要があります。 6 | 7 | ```html 8 | <:tag_name /> 9 | ``` 10 | 11 | または 12 | 13 | ```html 14 | <:tag_name> 15 | ``` 16 | 17 | タグが関係するビューのファイルをどのように探すかについては、ビューバインディングの項を参照してください。上記の場合であれば、```{{ view "tag_name" }}```と同様です。また、 ```<:blog:comments />``` は ```{{ view "blog/comments" }}``` と同様です。 18 | 19 | タグはテンプレートと同様に読み込まれて、コントローラーを読み込み、(存在すれば) アクションメソッドを実行し、ビューをレンダリングします。次の節では以下について記載します: 20 | 21 | - タグに属性を渡す 22 | - タグの内部での yield 23 | - タグでイベントをトリガーしそれをハンドリングする 24 | 25 | -------------------------------------------------------------------------------- /ja/docs/tasks.md: -------------------------------------------------------------------------------- 1 | # タスク 2 | 3 | 明示的にサーバー上でコードを実行したいこともあるでしょう。Volt では *タスク* を使ってこの問題を解決します。タスクは ```Volt::Task``` を継承することで定義できます。```tasks``` フォルダーに格納された ```_tasks.rb``` で終わる名前の Ruby ファイルは自動的に require されます。 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 は自動的に、promise を返すラッパーをクライアントサイドで生成します。 16 | 17 | *サーバーサイドのクラスはインスタンスメソッドを使いますが、ラッパークラスにおいては、それらのメソッドがクラス・メソッドとなることに注意してください。* Ruby で promise を利用することについてのより詳しい情報は [こちら](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 | 戻り値の promise に対して ```#then``` メソッドを実行すると、その呼び出しの結果を得ることができます。また、スローされたエラーを取得したければ、promise に対して ```#fail``` を実行します。 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 | ## タイムアウト 39 | 40 | デフォルトでは、タスクには60秒のタイムアウトが設定されています。すべてのタスクに対するグローバルなタイムアウト時間を設定したい場合には、```config/app.rb``` で ```config.worker_timeout``` を設定してください。また、タスクごとにタイムアウト時間を変更したい場合は、そのクラスで ```timeout``` メソッドを実行します。 41 | 42 | ```ruby 43 | class SampleTask < Volt::Task 44 | timeout 200 45 | 46 | ... 47 | end 48 | ``` 49 | 50 | タイムアウト時間を0にすることでタイムアウトを無効にすることが可能です。 51 | 52 | ## Cookies 53 | 54 | タスク内で```cookies``` を利用すると、新しい cookie を設定することができます。設定された cookie はクライアントに送信され設定されます。注意: タスクの中では cookie のセットのみが可能で、読み込むことはできません。(これはパフォーマンス上の理由による仕様です) 55 | -------------------------------------------------------------------------------- /ja/docs/testing.md: -------------------------------------------------------------------------------- 1 | # テスト 2 | 3 | Voltのテストは、デフォルトでRspecを使用しますが、プロジェクトのGemfileからRspec関連のgemを削除することで、別のテストフレームワークを利用することも可能です。ほとんどのジェネレーターはスタブのspecを生成するため、テストを始めやすくなっています。 4 | 5 | Voltプロジェクトの規約では、specディレクトリの中にappディレクトリのミラーを用意します。したがって、コンポーネントはそれぞれspecの中にフォルダを持つことになります。もし ```require 'spec-helper'``` をspecファイルに記載していれば、```bundle exec rspec``` によってすべてのテストを実行できます。また、特定のspecのパスを指定することも可能です。(注意: Voltは初期状態ではrakeを利用しません。したがって、通常は直接rspecを実行します。) 6 | 7 | # ヘルパー 8 | 9 | Voltは、spec内で ```page``` と ```store``` コレクションにアクセスするためのメソッドを提供しています。名前がCapybaraで定義されているものと被らないように、rspecでは```page```は```the_page```とします (コンフリクトを回避するための方法を検討中です)。 10 | 11 | spec内で```store``` にアクセスする場合には ```store``` を使用します。```store``` が呼び出された場合、specが実行された後にデータベースはクリアされます。これによって、実際にstoreを利用している場合を除いては、specごとにデータベースの準備を行う必要がなくなります。 12 | 13 | # インテグレーションspec 14 | 15 | Volt は最初から rspec と capybara を提供しています。モデルやコントローラーを直接テストすることもできますし、[Capybara](https://github.com/jnicklas/capybara) を使った結合テストも可能です。 16 | 17 | Capybaraでspecを実行したい場合は、describeブロックに```type: :feature``` を追加します。 18 | 19 | ```ruby 20 | describe "browser specs", type: :feature do 21 | it ... 22 | end 23 | ``` 24 | 25 | インテグレーションテストはデフォルトでは動作しません。Capybaraのテストを実行する場合は、ドライバーを指定する必要があります。現在、以下のドライバーをサポートしています。 26 | 27 | 1. Phantom (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 は、ChromeDriver に関する[この問題](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges) が存在するため、サポートしていません。[このページ](https://code.google.com/p/chromedriver/issues/detail?id=887#makechanges)から、修正してくれるように chromedriver チームにアピールをお願いします! 38 | -------------------------------------------------------------------------------- /ja/docs/url.md: -------------------------------------------------------------------------------- 1 | # Url 2 | 3 | Volt では、URL 情報にアクセスしたい場合、コントローラー上で使うことができる```url``` メソッドを利用します。url は以下のメソッドを持っています。それぞれ、現在のところは getter のみです (setter も近くサポートする予定)。 4 | 5 | - scheme 6 | - host 7 | - port 8 | - path 9 | - query 10 | - fragment 11 | 12 | それぞれのメソッドは url の変更にしたがってリアクティブに更新されます。 13 | -------------------------------------------------------------------------------- /ja/docs/url_for_and_url_with.md: -------------------------------------------------------------------------------- 1 | # url_for と url_with 2 | 3 | ルートの設定を利用して URL を生成したい場合には、```url_for``` または ```url_with``` を使用します。 4 | 5 | ## url_for 6 | 7 | ```url_for``` はパラメータ (params) のハッシュを引数にとり、ルートの設定 (と渡されたパラメータ) にしたがって URL を返します。 8 | 9 | 以下の例は、クエリストリングに ```?page=``` を与えたリンクの例です。この例では todos というコントローラーのルート設定にしたがいます。 10 | 11 | ```ruby 12 | url_for(controller: 'todos', page: 5) 13 | # => 'http://localhost:3000/todos?page=5' 14 | ``` 15 | 16 | [HTTPコントローラー](http_controllers.md) のためのURLを設定する場合は、対応するメソッドを第1引数に指定してください。 17 | 18 | ```ruby 19 | url_for(:get, controller: 'todos', action: 'index') 20 | # => 'http://localhost:3000/api/todos 21 | ``` 22 | 23 | ## url_with 24 | 25 | ```url_with``` は ```url_for``` と似ていますが、現在のパラメータ (params) とマージされる点が異なります。以下の例では、パラメータが ```{controller: 'todos'}``` であるとして URL を返します。 26 | 27 | ```ruby 28 | url_with(page: 5) 29 | # => 'http://localhost:3000/todos?page=5' 30 | ``` 31 | 32 | ```url_with``` はコントローラーのメソッドなので、ビューからもアクセスすることが可能です。 33 | 34 | ```html 35 | page 5 36 | ``` 37 | -------------------------------------------------------------------------------- /ja/docs/views.md: -------------------------------------------------------------------------------- 1 | # ビュー 2 | 3 | ビューとは、拡張子が .html のファイルで、レンダリングされ方をコントロールするための Ruby コードを記述できるものです。Volt はサーバー側でビューをコンパイルし、クライアントに送信します。ビューは以下のようなものになります。 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 | 17 | ``` 18 | 19 | Voltでは、ビューは専用のシンプルなテンプレート言語で記載します。ビューはセクションに分割することができます。セクションはセクションヘッダーから始まります。例えば、セクションヘッダーは以下のようになります。 20 | 21 | ```html 22 | <:Body> 23 | ``` 24 | 25 | セクションヘッダーは先頭が大文字で始まる必要があります。[タグ](#tags)と混同しないようにしてください。また、セクションヘッダーに閉じタグは使いません。もしセクションヘッダーを書かなかった場合は、```:Body``` セクションであるとして扱います。 26 | 27 | セクションは同じファイル上のコンテンツの異なるパーツ(タイトルと本文など)を区別するのに役立ちます。 28 | 29 | # バインディング 30 | 31 | Volt では、ビューはシンプルなテンプレート言語で記述し、 ```{{``` と ```}}``` で囲むことで、どこにでも Ruby のコードを挿入することができます。また、Volt では、一般的な制御文 (```if```、```elsif```、```else```、```each```) をビューに記述することが可能です。更に、```view``` バインディングを使うことで、他のビューをレンダリングすることもできます。 32 | 33 | # ビューの裏にあるコントローラー 34 | 35 | Volt は MVC フレームワークと言うより、モデル - ビュー - ビューモデル (MVVM) のフレームワークに近いですが、「コントローラー」という言葉を使っています。これは、「ビューモデル」という言葉の代わりに「コントローラー」という言葉を使っていることを意味します。 36 | 37 | ビューにおけるすべてのメソッド呼び出しやインスタンス変数の探索は、上記した「コントローラー」のコンテキストで実行されます。 38 | 39 | もしビューが ```app/main/views/index/index.html``` であるならば、```app/main/controller/index_controller.rb``` をコントローラーとして読み込みます。 40 | -------------------------------------------------------------------------------- /ja/docs/volt_helpers.md: -------------------------------------------------------------------------------- 1 | ## ロギング 2 | 3 | Volt はロギングのためのヘルパーを提供しています。```Volt.logger``` を実行すると、Ruby の logger のインスタンスを返します。詳細は [ここ](http://www.ruby-doc.org/stdlib-2.1.3/libdoc/logger/rdoc/Logger.html) を参照してください。 4 | 5 | 例: 6 | 7 | ```ruby 8 | Volt.logger.info("Some info...") 9 | ``` 10 | 11 | logger を変更したい場合は以下のようにします。 12 | 13 | ```ruby 14 | Volt.logger = Logger.new 15 | ``` 16 | 17 | ## アプリケーションの構成 18 | 19 | Volt は他の多くのフレームワークと同様に、環境 (environment) フラグによっていくつかのデフォルト設定を変更することができます。Volt の環境を設定するには ```VOLT_ENV``` 環境変数を使用します。 20 | 21 | アプリケーションの ```config``` フォルダーにあるすべてのファイルは、Volt の起動時にすべて読み込まれます。これは Rails の ```initializers``` フォルダーに似ています。 22 | 23 | Volt には、初めからいくつかのデフォルト構成が設定されているため、すぐに使用を開始することができます。データベースやアプリケーション名などの構成は ```config/app.rb``` ファイルで設定することができます。以下が、現時点で用意されている構成オプションです: 24 | 25 | | オプション名 | デフォルト値 | 詳細 | 26 | |-----------|---------------------------|---------------------------------------------------------------| 27 | | app_name | 現在のフォルダー名 | ロギングなどの用途で内部的に使用されます。| 28 | | db_driver | 'mongo' | 現在サポートしているドライバーは mongo のみですが、近いうちに追加される予定です。 | 29 | | db_name | "#{app\_name}\_#{Volt.env} | mongo のデータベース名です。| 30 | | db_host | 'localhost' | mongo のデータベースのためのホスト名です。| 31 | | db_port | 27017 | mongo のデータベースのためのポートです。| 32 | | compress_deflate | false | true の場合、アプリケーションサーバーで圧縮を行います。(ただ、これは Nginx などに任せた方が良いでしょう)| 33 | -------------------------------------------------------------------------------- /ja/docs/volt_internals.md: -------------------------------------------------------------------------------- 1 | # Volt Internals 2 | -------------------------------------------------------------------------------- /ja/docs/yield_binding.md: -------------------------------------------------------------------------------- 1 | # Yield バインディング 2 | 3 | [タグ](#tags)を使用する場合、呼び出し元が生成したコンテンツをタグの定義に渡すことができます。 4 | 言い換えると、タグの定義は呼び出し元のコンテンツを参照することができます。これは Ruby の yield と同様のロジックですが、わすかに異なるところがあります。以下にシンプルな例を紹介します。 5 | 6 | シンプルなリストのナビゲーションアイテムがあって、それを再利用したいとします。 7 | 8 | ```html 9 |
  • 10 | 11 | About 12 | 13 |
  • 14 | ``` 15 | 16 | これは簡単にタグに変換することが可能で、リンクとテキストを ```attrs``` を利用することで渡すことができます。しかし、これは span 要素の場合にはイマイチです。そういった場合には、 yield バインディングを利用する方がより良い方法です。 17 | 18 | ```html 19 | <:Nav> 20 |
  • 21 | 22 | {{ yield }} 23 | 24 |
  • 25 | ``` 26 | 27 | このタグをページの最初のアウトプットとして追加したい場合は以下のようにします。 28 | 29 | ```html 30 | <:nav href="/about">About 31 | ``` 32 | 33 | 上記の例で、"About" は ```{{ yield }}``` の場所にレンダリングされます。 34 | 通常、タグに含まれるコンテンツはすべて ```yield``` の場所にレンダリングされます。 35 | 36 | もし、HTMLのコンテンツを単純に文字列として取得したい場合には、コントローラーで```yield_html```を実行してください。これは、必要に応じて```.watch!```を設定することが可能な文字列を返します。そして、コンテンツの更新にしたがって再度レンダリングされます。 37 | -------------------------------------------------------------------------------- /ja/getting_help/README.md: -------------------------------------------------------------------------------- 1 | # ヘルプが必要なとき 2 | 3 | Volt はまだ開発中ですが、早期のフィードバックは大歓迎です。開発者とコンタクトを取りたいときには、以下を使ってください。誰かが素早く返答してくれることでしょう: 4 | 5 | - **ヘルプが必要なときには**: [stackoverflow.com](http://www.stackoverflow.com) に投稿してください。質問に `voltrb` タグを付けるのを忘れないように。 6 | 7 | - **バグを見つけたときには**: [github issues](https://github.com/voltrb/volt/issues) に投稿してください。 8 | - **Volt への提案がある、こんな機能が欲しい**: [github issues](https://github.com/voltrb/volt/issues) に投稿してください。 9 | - **Volt について議論したいときには**: [gitterのチャット](https://gitter.im/voltrb/volt) 通常、Volt チームは誰かがオンラインです。喜んで助けになります。 10 | -------------------------------------------------------------------------------- /ja/getting_help/can_i_use_opal_gems.md: -------------------------------------------------------------------------------- 1 | # Opal の Gem を利用できますか? 2 | 3 | はい。Opal は独自の方法で Gem を include します。このことは、通常、Opal のロードパスに追加される前に、MRI コードで Gem を require する必要があることを意味しています。 4 | 5 | 例えば opal/browser を例にすると、単純に以下のように config/app.rb に追加することが可能です。 6 | 7 | ```ruby 8 | require 'opal/browser' 9 | ``` 10 | 11 | そして、opal-browser を利用したいコントローラーで、ファイルの先頭に以下を追加します: 12 | 13 | ```ruby 14 | if RUBY_PLATFORM == 'opal' 15 | require 'browser' 16 | end 17 | ``` 18 | -------------------------------------------------------------------------------- /ja/getting_help/does_volt_support_haml,_slim,_etc.md: -------------------------------------------------------------------------------- 1 | # Volt で Haml や Slim などを利用できますか? 2 | 3 | **更新** - はい、Volt は Slim をサポートします。@ASnow ありがとう! https://github.com/asnow/volt-slim 4 | 5 | HAML はまだサポートされていません。以下は、関連する内容や必要なことを簡単に説明するものです。 6 | 7 | テンプレート言語の追加が容易な Rails を使っていた人にとって、この質問は気になるところだと思います。Rails では、テンプレートのレンダリングというものは、コンテキストに利用するテンプレートやオブジェクトを見つける処理です。その結果生成されるものは **1つの文字列** です。 8 | 9 | しかし Volt では、クライアントに送信するために、テンプレートはまず「コンパイルされたテンプレート」にレンダリングされます。テンプレートは _文字列にレンダリングされる_ わけではありません。_ターゲットに対して構成_ されます。Volt が現在サポートしているのは以下の2つのターゲットです。 10 | 11 | - 実際の DOM 12 | - 文字列 (タグ属性の中のテンプレートのパートのレンダリングや、E-mail、そしてサーバーサイドの html のため) 13 | 14 | 実際の DOM をレンダリングするとき、Volt はレンダリングされた DOM ノードの場所を探索します。したがって、それらのノードをレンダリングするためのデータに変更があった場合は、すべての DOM 全体を再レンダリングすることなく DOM を更新できます。これは、データ更新時の DOM に対する操作を最小限に抑え、DOM の更新を高速にすることに効果があります。他のフレームワークのように差分をチェックする必要もありません。Volt のバインディングは、DOM の更新を最小限の更新だけで行うことができます。 15 | 16 | ## では、Haml や Slim などをレンダリングするためには... 17 | 18 | それは実現できないほど困難、というわけではありませんが、Haml や Slim の Gem はそのままでは Volt で使えるようには設計されていません。Volt のコンパイルされたテンプレートフォーマットにコンパイル可能なテンプレート言語はであればすべて利用することができます。その、コンパイルされたテンプレートフォーマットというのは Ruby のコードです (Opal 経由でクライアントにコンパイルされます)。それは HTML と バインディングから構成されています。HTML はプレースホルダー (現在、特殊なコメントとして実装) を持っており、バインディングがレンダリングされるべき場所を示しています。バインディングは Ruby の Proc であり、バインディングのインスタンスをセットアップします。(Volt::EachBinding, Volt::ContentBinding, Volt::AttributeBinding, Volt::IfBinding, and Volt::EventBinding) 19 | 20 | Haml や Slim をコンパイルするためには、Haml や Slim が (レンダリング済みの HTML ではなく) Volt のコンパイルされたテンプレートのフォーマットを生成するように改修する必要があります。もし興味がある方がいれば、ぜひ [gitter](https://gitter.im/voltrb/volt) で @ryanstout までお知らせください。 21 | -------------------------------------------------------------------------------- /ja/getting_help/faq.md: -------------------------------------------------------------------------------- 1 | # FAQ 2 | 3 | * [どこで何が動いている?クライアント VS サーバー](what_runs_on_the_client_vs_server.md) 4 | * [jQuery やその他の DOM 操作の JS を使うことはできますか?](can_i_use_jquery_or_other_dom_manipulating_js.md) 5 | -------------------------------------------------------------------------------- /ja/getting_help/is_keeping_a_persistent_connection_open_a_performance_problem.md: -------------------------------------------------------------------------------- 1 | # 永続的な接続を維持することでパフォーマンス上問題がありますか? 2 | 3 | 私はかつてソーシャルゲームに関わっていました。そのとき、ソケット通信 (WebSocket 以前の話なので Flash 経由) はそれぞれのユーザーに対して常に開かれていました。500,000人のユーザーが同時にオンラインの状態で、それでも我々のディスパッチサーバー (クライアントとの接続を維持するためサーバー) の CPU 負荷は10%に満たないものでした。そのサーバーは MRI で EventMachine を使って構築されていました。Linux 上では EventMachine は e-poll という Linux の API を利用することができます。それはソケットに対応する IO をスケジューリングするためのものです。これは、Nginx の構成と同じだと言えます。単一のマシン上で数百万のコネクションにまでスケール可能です。(もっと知りたければ、C10k 問題というものをググってみるか、http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html を参照ください) 結論だけ言えば、イベントサーバーはコネクションを維持し管理することに問題はない、ということです。IO へのプッシュはとても簡単です。ただ、1つ問題があるとすれば、ある非常に大きいデータを多くの人が参照したとき、その大きな更新によってネットワーク接続がいっぱいいっぱいになってしまう可能性があります。現在、多くのマシンにまたがる接続や更新の分配を容易にするため、distributed data bus (vert.x と同様のものです) を実装しようとしています。Thin と Goliath の両方のサーバーで、1つの Rack リクエストに対して1つのスレッドが割り当てられますが、すべての WebSocket はシングルスレッドで稼働し、ディスパッチの管理にイベント IO を使います。JRuby では、同様のことを実現するために vert.x と連携したいとも考えています。 4 | 上記がいくつかの疑問点に対して回答になれば、と思います。Volt が解決しなければならない困難な問題は多くありますが、コネクションの永続化は問題とはならないと考えています。これは、epoll と O(1) linux scheduler のおかげだと言えます。 5 | 6 | - Ryan 7 | -------------------------------------------------------------------------------- /ja/getting_help/what_browsers_does_volt_support.md: -------------------------------------------------------------------------------- 1 | # Volt はどの Web ブラウザをサポートしていますか? 2 | 3 | Firefox と Chrome は自動的に最新版に更新されるので、おそらく気になるのは IE に関してでしょう。喜ばしいことに、Opal は IE を過去のバージョンまでサポートします (コア開発者の1人が IE6 のサポートを必要としているらしいです)。 Volt は今のところ、IE10 のみをターゲットにしていますが、IE8-9 のサポートを追加するための volt-ie8-9 という Gem を開発中です。現在、WebSocket の代わりになるものだけが不足しています。 4 | 5 | ## 機能制限 6 | 7 | Volt のいくつかの機能は、特定のブラウザのみでしか動作しません。 8 | 9 | 1)hidden フィールドのバインディング 10 | hidden フィールドにバインドするためには、ブラウザが mutation observer イベントをサポートしている必要があります。これは IE11 以降でのみサポートされています。IE8-10 をサポートするための polyfill が存在するので、Gem にバンドルする予定です。また改めてチェックしてもらえればと思います。 11 | -------------------------------------------------------------------------------- /ja/getting_help/whats_the_difference_between_volt_and_meteor.md: -------------------------------------------------------------------------------- 1 | # Volt と Meteor の違いは? 2 | 3 | Volt と Meteor は多くの点で類似しています。その理由は主に、どちらも同じ問題を解決しようとするものだからです。Volt が Ruby を使って、Meteor が JavaScript を使うという違いの他にも、いくつかの大きな違いがあります: 4 | 5 | ## コンポーネント 6 | 7 | 大きな違いの1つは、Volt アプリケーションがコンポーネントから構築されるということです。このことは、コードの (Gem としての) 再利用性を高め、モジュラー化を推進するものだと考えています。また、このことによって、「ページの読み込みの境界」を設定することができ、「シングルページアプリケーション (SPA)」を構築することが可能になります。これは、最初のページの読み込み時に、クライアント側でアプリケーションすべてを読み込む必要がないことを意味しています。あるパートにおいて、ブラウザが通常の get リクエストを発行し、他のセクションを読み込む、ということができます。 8 | 9 | ## クライアント側のデータベースアクセス 10 | 11 | Meteor では、データベースを直接操作します (insert, create, etc...) が、Volt ではオブジェクトとして扱います。クラスは Volt::Model を継承して作ることができます。オブジェクトの設定にしたがって、どこにデータが永続化されるかが決定されます。オブジェクト自体が直接永続化機構になっているわけではないので (リポジトリパターンを想像してください)、個別にテストをすることが可能です。また、オブジェクトに関連するビジネスロジックを配置する場所を提供し、それらのロジック (主にバリデーションやパーミッション) が侵されることを防止します。 12 | 13 | ## データハンドリング 14 | 15 | もう1つの大きな違いは、データをハンドリングする方法です。Meteor では、publish によってページがロードされたとき、クライアントは必要データを要求します。それに応じて、クライアント側でデータを subscribe します。subscribe で publish のオプションを渡すことも可能ですが、これは私の考えだとちょっとトリッキーに感じます。このようにすべき主な理由は、コールバックを待つことなく、クライアント上でデータを操作することができるようにするためです。そして、このことの問題点は、多くのケースにおいて、サーバーとのラウンドトリップを待つ必要があることです。例としてはユニーク性のバリデーションがあげられます。これは確認のためにサーバーへのアクセスが必要になります。Volt では、データの読み込みは「どれがリアクティブに監視されているか」によって決定されます。したがって、save などは promise を返し、結果を待つ必要があればそれを利用して待つことができます。IcedCoffeeScript のような Opal の機能拡張を追加し、async/await スタイルのシンタックスを提供することで、promise の API を透過的、かつ同期的に扱えるようにすることを予定しています。(まだ対応中の段階です)。Meteor アプリケーションでよく見られることとして、クライアント側で mini-mongo を利用するのをやめて、すべてを Meteor のメソッドで処理する、というものです。これは mongo のデータの扱いに難しい問題があることを示していると思います。もう1つは、読み込み時にどのデータが必要を判断するのが難しいため、大量のデータがクライアントに送信されるということです。Volt の方法が完璧だと言うつもりはありませんが、Meteor のやり方の問題のいくつかは解決することができると思っています。 16 | 17 | ## その他 18 | 19 | その他の異なる点をざっとあげます。いくつか小さな違いがあります。 20 | 21 | - Meteor と比較して、 Volt は規約やファイルの構成をより多く利用します。 22 | - Volt のルーターは完全に異なるものになっています。 23 | - Volt は VC から $11MM の融資を受けていません :-) 24 | 25 | さらに多くの違いはありますが、現時点で頭に入れておいてほしいものは以上です。 26 | -------------------------------------------------------------------------------- /ja/getting_help/why_use_underscore_accessors_instead_of_[property].md: -------------------------------------------------------------------------------- 1 | # なぜ [:property] のかわりにアンダースコアアクセサを使うのか? 2 | 3 | Volt に関するよくある質問として、「なぜアンダースコア アクセサ」を使うのか、というものがあります。これは、プロパティ名を事前に定義することなく、モデルが set/get プロパティを利用できるようにするために必要となるいくつかの理由があるためです。 4 | 5 | ## 1. 予期しないエラーの防止 6 | 7 | 単純に、モデルにどんなメソッドでも設定できるようにすることは可能です。 8 | 9 | ```ruby 10 | item = Volt::Model.new 11 | item.name = 'Ryan' 12 | ``` 13 | 14 | しかし、このときの問題は、Volt では、アサインされていないプロパティは nil を返す必要があるということです。そうすることで、事前の設定なしにプロパティをバインドすることが可能になり、バインディングは nil を適切に扱うことができるようになります。(例えば、テキストフィールドにバインドされた ```value``` は nil を空文字列であるとして扱います) 上記した問題というのは、もし存在しないメソッドを呼び出した場合にも、```NoMethodError``` の代わりに常に nil が返される、ということです。 15 | 16 | ```ruby 17 | item = Volt::Model.new 18 | item.savr! # => nil 19 | # ※意図していたのは .save! 20 | ``` 21 | 22 | ## 2. 簡潔であること/self なし 23 | 24 | モデルのプロパティへのアクセスは非常によくある操作です。いくつかの JS フレームワークは ```.set```/```.get``` のような記法を利用していますが、単純なプロパティへのアクセスでタイピング量が多くなってしまうことを不満と感じる人が非常に多いです。Volt ではできるだけ簡潔にしたいと考えています。Ruby では以下のようなことが可能です。 25 | 26 | ```ruby 27 | item = Volt::Model.new 28 | item[:name] # => nil 29 | ``` 30 | 31 | これはコントローラーのコードでは問題なく動作しますが、Volt で ModelController を使用する場合、コントローラーのモデルをモデルのインスタンスにセットしたい場合があるでしょう。その場合、バインディングで以下の設定をする必要があります (Ruby の仕様のためです): 32 | 33 | ```html 34 | 35 | ``` 36 | 37 | これは動作自体には問題ないですが、可読性が悪く、混乱の原因になる可能性があると考えています。 38 | 39 | _property という記法は Ruby では一般的ではありませんが、一度慣れてしまえば、多くのコードのタイピングや読解から解放されます。もしこれがあまり良い方法ではないとお考えであれば、[フィールド](/docs/models.md) を利用することも可能だということを覚えておいてください。 40 | -------------------------------------------------------------------------------- /ja/introduction/README.md: -------------------------------------------------------------------------------- 1 | # 目的 2 | 3 | 以下を達成することが Volt の目的です。 4 | 5 | 1. 開発者のしあわせ 6 | 2. クライアントとサーバー間でのコードの共有における重複の排除 7 | 3. クライアントとサーバー間の自動的なデータ同期 8 | 4. Built apps as nested components. コンポーネントは (Gem として) 共有化可能で、サービスとしても実行可能です。 9 | 5. 並行性。Voltは、シンプルに並行性を実現するツールを提供する。 10 | 6. インテリジェントなアセット管理 11 | 7. セキュアであること(わざわざ言うべきことではないですが) 12 | 8. 高速で軽量、かつスケーラブルであること 13 | 9. 理解しやすいコードベース 14 | 15 | # ロードマップ 16 | 17 | Voltの核となる機能の多くはすでに実装済みです。 しかし、1.0のリリースまでに対応すべきことがまだいくつか残っていて、そのほとんどはモデルに関するものです。 18 | 19 | 1. データプロバイダーAPI - 抽象化したAPIによって、様々なデータベース/データストアのためのアダプターの開発を容易にする。 20 | 2. Oauth連携 - どんなomniauthプロバイダーでも簡単に利用できるように、omniauthと連携する。 21 | 3. Voltからデータベースのインデックスを追加するためのマイグレーション 22 | 4. サーバーサイドのHTMLプリレンダリング - サーバー側でまずページのレンダリングを行い、それから、クライアント側でRubyコードが読み込まれたら、コンパイルされたものと結合するようにする。 23 | -------------------------------------------------------------------------------- /ja/roadmap/README.md: -------------------------------------------------------------------------------- 1 | # ロードマップ 2 | 3 | オープンソースプロジェクトであるため、時期を予測することが難しいですが、これからの6ヶ月間で計画している機能のロードマップは以下の通りです。 4 | 5 | | 機能 | 目標の日付 | 詳細 | 6 | |------------------------------------|------------- |----------------------------------------| 7 | | SQL サポートとモデル層の再実装 | 10/15 | (eager loading を含) | 8 | | "Auto-rest" サポート | 9/20 | (@jfaher によると大体は完成済み | 9 | | クエリ制限 API | 9/30 | | 10 | | Time ヘルパー | 11/1 | 大体は完成済み。要 Opal 0.9 | 11 | | has_many through と ポリモーフィッククエリ | 11/30 | | 12 | | volt-user-templates への omniauth 連携 | 12/1 | | 13 | 14 | さらに、まだ具体的なタイムラインはありませんが、より大きな機能について計画中です。 15 | 16 | - RubyMontion のサポート - RubyMotion との連携によって、Volt アプリケーションの一部として、Volt (とデータの同期) を iOS/Android のネイティブアプリケーションで利用できるようにしたいと考えています。これは、HTML ビューのフォルダに「web」フォルダを用意し、コントローラーとネイティブのウィジェットをつなぐためのコードを「ios」と「android」フォルダに rubymotion のコードを配置することを意味しています。 17 | 18 | - サーバーサイドレンダリング - サーバーがページをプリレンダリングし、JS が読み込まれる前にページを表示できることが目的です。JS がロードされたとき、バインディングにフックされます。サーバーサイドレンダリングについては大体完成していますが、サーバー側でレンダリングされたバインディングに紐付ける作業が残っています。また、考慮すべきエッジケース (インライン JS を使用するコンポーネントや、DOM 操作など) が多く残っています。現在の計画としては、サーバーサイドに向かないコンポーネントに印をつけられるようにして、コンポーネントのレンダリングが遅延しないようにすることを考えています。 19 | 20 | -------------------------------------------------------------------------------- /ja/tutorial/README.md: -------------------------------------------------------------------------------- 1 | # チュートリアル 2 | 3 | ここでは、Volt で基本的な Web アプリケーションを作成する手順を示します。 このチュートリアルは、Ruby と Web 開発の基本的な知識を持っていることを前提とします。 4 | 5 | ## セットアップ 6 | 7 | 最初に、Volt をインストールして空のアプリケーションを作成しましょう。Ruby (>2.1.0) と rubygems がインストールされていることを確認してください。 8 | 9 | 次に、Volt の gem をインストールします: 10 | 11 | gem install volt 12 | 13 | Volt の gem を使って新しいプロジェクトを作成します: 14 | 15 | volt new sample_project 16 | 17 | これで sample_project フォルダーに基本的なプロジェクトがセットアップされます。```cd``` コマンドでそのフォルダーに移動し、サーバーを起動します: 18 | 19 | bundle exec volt server 20 | 21 | Voltのコンソールには以下でアクセスすることができます: 22 | 23 | bundle exec volt console 24 | 25 | -------------------------------------------------------------------------------- /ja/why_volt/README.md: -------------------------------------------------------------------------------- 1 | # Why Volt 2 | 3 | 私は1996年から Web サイトの構築をしています。初めての Web アプリケーションは1998年に開発しました。それから、Web 開発に対して、新しい様々なツールや技術がレイヤーとして積み重なるのを目にしてきました。それぞれのレイヤーが更なるパワーと柔軟性を与えてきましたが、同時に複雑にもなってしましました。最もシンプルなアプリケーションでも、現代の Web 開発者であれば、html、css、javascript、バックエンドのプログラム言語、http、ヘッダー、キャッシュ、バックエンドのフレームワークフロントエンドのフレームワーク、REST、アセットコンパイル、などの多くに精通している必要があります。 4 | 5 | これらのツールのリストはまだまだ続きます。Web アプリケーションの構築を高速化するためには、その複雑性をアウトソースする必要があると考えています。これは Web コミュニティはまだ実現できていないことですが、別の領域ではすでに実際に行われています。例えば、ほとんどのプログラミング言語において、我々は自身でメモリ管理を行う必要はありませんし、独自のファイルシステムを (普通は) 作ることはしませんし、UI を直接構築することもしません。その代わりに、ガベージコレクションや UI ツールキットを使うことで、それらの複雑性は覆い隠されました。 6 | 7 | ガベージコレクションの仕組みを理解することは役に立ちます。それを知ることでより良いプログラマーとなることができるでしょう。しかし、(バグの可能性のある) malloc や free の多用でコードをややこしくすることは複雑さしか与えないと思います。 8 | 9 | Volt は、これと同様の方法で Web の複雑性を減らすことを試みています。どのようにその複雑さをシンプルにするか見てみましょう。 10 | 11 | ### 言語 12 | 13 | 少し前までは、すべての Web アプリケーションは JavaScript ではない別のバックエンドの言語で記述され、JavaScript はフロントエンドの言語として利用されていました。それから、JavaScript をバックエンドの言語として利用する人たちが現れました。Node のコミュニティは、クライアントとサーバーで同一の言語を使用することが、物事をシンプルにする、との正当な主張をしています。Volt チームはこれに完全に同意します。しかし、我々が描いている未来は、サーバーの言語として JavaScript を直接使うのではなく、JavaScript へのコンパイルを行うものです。 14 | 15 | 同一の言語がクライアントとサーバーで動作することは、コンテキストの変更による認知的負荷 (cognitive load) を現象させます。しかし、一番良いのは**「同一のコード」**がどちらでも動作することです。これは、Node のプログラマーがまだ実現していないものです。 16 | 17 | ### フロントエンドとバックエンドのフレームワーク 18 | 19 | 今日の Web アプリケーションは、一般的にバックエンドのフレームワークとフロントエンドのフレームワークの両方から構築されます。これは、同じようなことも2つの異なる方法でやるということです。Volt は、クライアントとサーバーのどちらでも動作する1つのフレームワークです。 20 | 21 | ### HTTP と REST 22 | 23 | ほとんどのアプリケーションはクライアントとサーバーで別のツールを使って構築されています。したがって、REST API を用いて同期されます。Volt では、クライアントとサーバー間で自動的に同期するモデルのクラスを使ってデータにアクセスすることができます。また、開発者がそのためのコードを書く必要がありません。 24 | 25 | ### フルスタックのコンポーネント 26 | 27 | ほとんどの Web スタックのアキレス腱と言えるのは、クライアントとサーバー間の標準が存在しないことです。Volt はこれを標準化します。再度言いますが、同一のコードがクライアントとサーバーで動作するのです。 -------------------------------------------------------------------------------- /styles/website.css: -------------------------------------------------------------------------------- 1 | /* CSS for website */ 2 | --------------------------------------------------------------------------------