opal 0.8.0 → 0.8.1.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ # Using external libraries in your Opal app
2
+
3
+ As described in the getting started docs, opal uses a load path which works
4
+ with sprockets to create a set of locations which opal can require files
5
+ from. If you want to add a directory to this load path, you can add it to
6
+ either the global environment, or a sprockets instance.
7
+
8
+ ### Global Environment
9
+
10
+ In the `Opal` module, a property `paths` is used to hold the load paths which
11
+ `Opal` uses to require files from. You can add a directory to this:
12
+
13
+ ```ruby
14
+ Opal.append_path '../my_lib'
15
+ ```
16
+
17
+ Now, any ruby files in this directory can be discovered.
18
+
19
+ ### Sprockets instances
20
+
21
+ `Opal::Environment` is a subclass of the sprockets environment class which
22
+ can have instance specific paths added to it. This class will inherit all
23
+ global paths, but you can also add your instance paths as:
24
+
25
+ ```ruby
26
+ env = Opal::Environment.new
27
+ env.append_path '../my_lib'
28
+ ```
29
+
30
+ ## with Opal::Builder
31
+
32
+ _WIP_
33
+
34
+ ## With opal-sprockets
35
+
36
+ _WIP_
@@ -0,0 +1,64 @@
1
+ # Promise
2
+
3
+ `Promise` is a class available in the Opal stdlib for helping structure asynchronous code.
4
+
5
+ It can be required inside any Opal applicaton:
6
+
7
+ ```ruby
8
+ require 'promise'
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ This example shows how to use a `HTTP` request from `opal-jquery` from a callback style, into a promise style handler.
14
+
15
+ ```ruby
16
+ def get_json(url)
17
+ promise = Promise.new
18
+
19
+ HTTP.get(url) do |response|
20
+ if response.ok?
21
+ promise.resolve response.json
22
+ else
23
+ promise.reject response
24
+ end
25
+ end
26
+
27
+ promise
28
+ end
29
+
30
+ get_json('/users/1.json').then do |json|
31
+ puts "Got data: #{json}"
32
+ end.fail do |res|
33
+ alert "It didn't work :( #{res}"
34
+ end
35
+ ```
36
+
37
+ A promise can only be resolved or rejected once.
38
+
39
+ ### Chaining Promises
40
+
41
+ Promises become useful when chained together. The prevous example could be extended to get another object from the result of the first request.
42
+
43
+ ```ruby
44
+ get_json('/users/1.json').then do |json|
45
+ get_json("/posts/#{json[:post_id]}.json")
46
+ end.then do |post|
47
+ puts "got post: #{post}"
48
+ end
49
+ ```
50
+
51
+ ### Composing Promises
52
+
53
+ `Promise.when` can be used to wait for more than 1 promise to resolve (or reject). Lets assume we wanted to get 2 different users:
54
+
55
+ ```ruby
56
+ first = get_json '/users/1.json'
57
+ second = get_json '/users/2.json'
58
+
59
+ Promise.when(first, second).then do |user1, user2|
60
+ puts "got users: #{user1}, #{user2}"
61
+ end.fail do
62
+ alert "Something bad happened"
63
+ end
64
+ ```
@@ -0,0 +1,116 @@
1
+ # Opal in a Rails application
2
+
3
+ Add Opal to your Gemfile:
4
+
5
+ ``` ruby
6
+ gem 'opal-rails'
7
+ ```
8
+
9
+ Or to start off with Opal when you build your new Rails app:
10
+
11
+ ```bash
12
+ rails new <app-name> --javascript=opal
13
+ ```
14
+
15
+ ## Basic usage through the asset pipeline
16
+
17
+ ```js
18
+ // app/assets/application.js.rb
19
+
20
+ //= require opal
21
+ //= require opal_ujs
22
+ //= require turbolinks
23
+ //= require_tree .
24
+ ```
25
+
26
+ Opal requires are forwarded to the Asset Pipeline at compile time (similarly to what happens for RubyMotion). You can use either the `.rb` or `.opal` extension:
27
+
28
+ ```ruby
29
+ # app/assets/javascripts/greeter.js.rb
30
+
31
+ puts "G'day world!" # check the console!
32
+
33
+ # Dom manipulation
34
+ require 'opal-jquery'
35
+
36
+ Document.ready? do
37
+ Element.find('body > header').html = '<h1>Hi there!</h1>'
38
+ end
39
+ ```
40
+
41
+
42
+
43
+
44
+ ### As a template
45
+
46
+ You can use it for your views too, it even inherits instance and local variables from actions:
47
+
48
+ ```ruby
49
+ # app/controllers/posts_controller.rb
50
+
51
+ def create
52
+ @post = Post.create!(params[:post])
53
+ render type: :js, locals: {comments_html: render_to_string(@post.comments)}
54
+ end
55
+ ```
56
+
57
+ Each assign is filtered through JSON so it's reduced to basic types:
58
+
59
+ ```ruby
60
+ # app/views/posts/create.js.opal
61
+
62
+ post = Element.find('.post')
63
+ post.find('.title').html = @post[:title]
64
+ post.find('.body').html = @post[:body]
65
+ post.find('.comments').html = comments_html
66
+ ```
67
+
68
+
69
+ ### As a Haml filter (optional)
70
+
71
+ Of course you need to require `haml-rails` separately since its presence is not assumed
72
+
73
+ ```haml
74
+ -# app/views/posts/show.html.haml
75
+
76
+ %article.post
77
+ %h1.title= post.title
78
+ .body= post.body
79
+
80
+ %a#show-comments Display Comments!
81
+
82
+ .comments(style="display:none;")
83
+ - post.comments.each do |comment|
84
+ .comment= comment.body
85
+
86
+ :opal
87
+ Document.ready? do
88
+ Element.find('#show-comments').on :click do |click|
89
+ click.prevent_default
90
+ click.current_target.hide
91
+ Element.find('.comments').effect(:fade_in)
92
+ end
93
+ end
94
+ ```
95
+
96
+
97
+ ### Spec!
98
+
99
+ Add specs into `app/assets/javascripts/spec`:
100
+
101
+ and then a spec folder with you specs!
102
+
103
+ ```ruby
104
+ # app/assets/javascripts/spec/example_spec.js.rb
105
+
106
+ describe 'a spec' do
107
+ it 'has successful examples' do
108
+ 'I run'.should =~ /run/
109
+ end
110
+ end
111
+ ```
112
+
113
+ Then visit `/opal_spec` from your app and **reload at will**.
114
+
115
+ ![1 examples, 0 failures](http://f.cl.ly/items/001n0V0g0u0v14160W2G/Schermata%2007-2456110%20alle%201.06.29%20am.png)
116
+
@@ -0,0 +1,98 @@
1
+ # RSpec
2
+
3
+ `opal-rspec` allows opal to use rspec for running specs in javascript
4
+ environments. It comes with built-in support for running rspec with custom
5
+ `phantomjs` and standard web browser formatters. Also, async spec examples
6
+ are supported to reflect browser usage of ruby applications.
7
+
8
+ ```ruby
9
+ describe User do
10
+ it "can be created with a name" do
11
+ expect(User.new).to_not be_persisted
12
+ end
13
+ end
14
+ ```
15
+
16
+ ### Installation
17
+
18
+ Add the `opal-rspec` gem to your Gemfile:
19
+
20
+ ```ruby
21
+ # Gemfile
22
+ gem 'opal'
23
+ gem 'opal-rspec'
24
+ ```
25
+
26
+ ## Running specs
27
+
28
+ ### phantomjs
29
+
30
+ To run specs, a rake task can be added which will load all spec files
31
+ from `spec/`:
32
+
33
+ ```ruby
34
+ # Rakefile
35
+ require 'opal/rspec/rake_task'
36
+ Opal::RSpec::RakeTask.new(:default)
37
+ ```
38
+
39
+ Then, to run your specs inside phantomjs, just run the rake task:
40
+
41
+ ```sh
42
+ $ bundle exec rake
43
+ ```
44
+
45
+ ### In a Browser
46
+
47
+ `opal-rspec` can use sprockets to build and serve specs over a simple rack server. Add the following to a `config.ru` file:
48
+
49
+ ```ruby
50
+ # config.ru
51
+ require 'bundler'
52
+ Bundler.require
53
+
54
+ run Opal::Server.new { |s|
55
+ s.main = 'opal/rspec/sprockets_runner'
56
+ s.append_path 'spec'
57
+ s.debug = false
58
+ }
59
+ ```
60
+
61
+ Then run the rack server bundle exec rackup and visit `http://localhost:9292` in any web browser.
62
+
63
+ ## Async examples
64
+
65
+ `opal-rspec` adds support for async specs to rspec. These specs are defined using
66
+ `#async` instead of `#it`:
67
+
68
+ ```ruby
69
+ describe MyClass do
70
+ # normal example
71
+ it 'does something' do
72
+ expect(:foo).to eq(:foo)
73
+ end
74
+
75
+ # async example
76
+ async 'does something else, too' do
77
+ # ...
78
+ end
79
+ end
80
+ ```
81
+
82
+ This just marks the example as running async. To actually handle the async result,
83
+ you also need to use a `run_async` call inside some future handler:
84
+
85
+ ```ruby
86
+ async 'HTTP requests should work' do
87
+ HTTP.get('/users/1.json') do |res|
88
+ run_async {
89
+ expect(res).to be_ok
90
+ }
91
+ end
92
+ end
93
+ ```
94
+
95
+ The block passed to `run_async` informs the runner that this spec is finished
96
+ so it can move on. Any failures/expectations run inside this block will be run
97
+ in the context of the example.
98
+
@@ -0,0 +1,79 @@
1
+ # Using Opal with Sinatra
2
+
3
+ Add Opal to your Gemfile (or install using `gem`):
4
+
5
+ ```ruby
6
+ # Gemfile
7
+ gem 'sinatra'
8
+ gem 'opal', '~> 0.6.2'
9
+ ```
10
+
11
+ Opal uses `sprockets` as its default build system, so the asset-pipeline
12
+ from rails can be mimicked here to map all ruby assets in the `/assets`
13
+ path to be compiled using opal.
14
+
15
+ ## Basic Application
16
+
17
+ ```ruby
18
+ # config.ru
19
+ require 'opal'
20
+ require 'sinatra'
21
+
22
+ opal = Opal::Server.new {|s|
23
+ s.append_path 'app'
24
+ s.main = 'application'
25
+ }
26
+
27
+ map opal.source_maps.prefix do
28
+ run opal.source_maps
29
+ end
30
+
31
+ map '/assets' do
32
+ run opal.sprockets
33
+ end
34
+
35
+ get '/' do
36
+ <<-HTML
37
+ <!doctype html>
38
+ <html>
39
+ <head>
40
+ <script src="/assets/application.js"></script>
41
+ </head>
42
+ </html>
43
+ HTML
44
+ end
45
+
46
+ run Sinatra::Application
47
+ ```
48
+
49
+ This creates a simple sprockets instance under the `/assets` path. Opal
50
+ uses a set of load paths to compile assets using sprockets. The
51
+ `Opal::Environment` instance is a simple subclass of `Sprockets::Environment`
52
+ with all the custom opal paths added automatically.
53
+
54
+ This `env` object includes all the opal corelib and stdlib paths. To add
55
+ any custom application directories, you must add them to the load path using
56
+ `env.append_path`. You can now add an `app/application.rb` file into this
57
+ added path with some basic content:
58
+
59
+ ```ruby
60
+ # app/application.rb
61
+ require 'opal'
62
+
63
+ puts "wow, running ruby!"
64
+ ```
65
+
66
+ It is necessary to require the opal corelib (seen in the `require` call) above.
67
+ This just makes the Opal runtime and corelib available. Then it is possible to
68
+ use all the corelib methods and classes, e.g. `Kernel#puts` as seen above.
69
+
70
+ ### Running Application
71
+
72
+ As this is just a simple sinatra application, you can run it:
73
+
74
+ ```sh
75
+ $ bundle exec rackup
76
+ ```
77
+
78
+ And point your browser towards `http://localhost:9292/` and view the browser
79
+ debug console. You should see this message printed.
@@ -0,0 +1,49 @@
1
+ # Source maps
2
+
3
+ Source maps are available (on current stable release, v0.6.x) even without explicit support from Sprockets in a sort of hackish way.
4
+
5
+ _As such even if they generally work fine there are some limitations and edge case issues._
6
+
7
+ NOTE: Currently on `master` branch sourcemaps are work-in-progress and probably will integrate with the upcoming Sprockets 4 that has integrated support for them.
8
+
9
+ #### Processor `source_map_enabled` flag
10
+ To enable sourcemaps in the Sprockets processor you need to turn on the relative flag:
11
+
12
+ ```ruby
13
+ Opal::Processor.source_map_enabled = true # default
14
+ ```
15
+
16
+
17
+ #### Sprockets debug mode
18
+
19
+ The sourcemaps only work with Sprockets in debug mode because they are generated just for single files.
20
+
21
+
22
+ ## Enable source maps
23
+
24
+ ### Rails
25
+
26
+ Rails has debug mode already enabled in development environment with the following line from `config/environments/development.rb`:
27
+
28
+ ```ruby
29
+ # Debug mode disables concatenation and preprocessing of assets.
30
+ # This option may cause significant delays in view rendering with a large
31
+ # number of complex assets.
32
+ config.assets.debug = true
33
+ ```
34
+
35
+ `opal-rails` also enables sourcemaps in development so with the standard setup you ready to go.
36
+
37
+
38
+ ### Sinatra
39
+
40
+ You can add `Opal::Server` as in the official example: [sinatra/config.ru](https://github.com/opal/opal/blob/0-6-stable/examples/sinatra/config.ru).
41
+
42
+ ### Opal::Server
43
+
44
+ `Opal::Server` implements sourcemaps and can be used alone or with `Rack::Cascade` in conjunction with other apps.
45
+
46
+ ### Opal::Environment
47
+
48
+ `Opal::Environment` is a bit lower level and doesn't support source maps by itself.
49
+