Commit 96d8c58d43c8e18acdfa4a1a7bedbcac537aef31:
README updates
Branch: refs/heads/master
Author: Sam Ruby <[email protected]>
Committer: Sam Ruby <[email protected]>
Pusher: rubys <[email protected]>
------------------------------------------------------------
Gemfile | -
README | ------
README.md | ++++++++ -
views/main.html.rb | + -
------------------------------------------------------------
252 changes: 232 additions, 20 deletions.
------------------------------------------------------------
diff --git a/Gemfile b/Gemfile
index 3e6c43e..ac16276 100644
--- a/Gemfile
+++ b/Gemfile
@@ -6,7 +6,6 @@ gem 'ruby2js'
gem 'sinatra'
gem 'nokogumbo'
gem 'execjs'
-gem 'github-markdown'
gem 'whimsy-asf'
group :test do
diff --git a/README b/README
deleted file mode 100644
index 1d4582f..0000000
--- a/README
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a React.js application making use of Wunderbar in the production of
-HTML and Ruby2JS in the production of JavaScript.
-
- http://facebook.github.io/react/
- https://github.com/rubys/wunderbar#readme
- https://github.com/rubys/ruby2js#readme
diff --git a/README.md b/README.md
index 0ae0c3b..d16c472 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,14 @@
+Preface
+---
+
+ * I ask that you [give it five
minutes](https://signalvnoise.com/posts/3124-give-it-five-minutes)
+ * Be prepared to [rethink best
practices](https://www.youtube.com/watch?v=x7cQ3mrcKaY)
+
Preparation
---
-This has been tested to work on Mac OSX and Linux. It may not work yet on
-Windows.
+This has been tested to work on Mac OSX and Linux. It likely will not work
+yet on Windows.
For a partial installation, all you need is Ruby and Node.js.
@@ -17,22 +23,29 @@ For planning purposes, prereqs for a _full_ installation
will require:
* The following software installed:
* Subversion
* Ruby 1.9.3 or greater
- * Node.js
+ * io.js plus npm install react, jsdom, and jquery
* PhantomJS 2.0
* Mac OS/X Yosemite users may need to get the binary from comments
on [12900](https://github.com/ariya/phantomjs/issues/12900).
-Kicking the tires:
+Note:
+
+ * The installation of PhantomJS on Linux current requires a 30+ minute
+ compile. The binary provided for OS/X Yosemite is not part of the
+ standard distribution. Feel free to skip this step on your first
+ ("give it five minutes") pass through this. If you see promise,
+ come back and complete this step.
+
+
+Kicking the tires
---
-```
-sudo gem install bundler
-git clone ...
-cd ...
-bundle install
-rake
-RACK_ENV=test puma
-```
+ sudo gem install bundler
+ git clone ...
+ cd agenda
+ bundle install
+ rake spec
+ rake server:test
Visit http://localhost:9292/ in your favorite browser.
@@ -41,7 +54,213 @@ Notes:
* If you don't have PhantomJS installed, or have a version of PhantomJS
prior to version 2.0 installed, one test will fail.
+ * If you don't have io.js installed, two additional tests will fail.
+
* The data you see is a sanitized version of actual agendas that have
been included in the repository for test purposes.
+Viewing Source (Live Results)
+---
+
+At this point, you have something up and running. Let's take a look around.
+
+ * The first thing I want you to do is use the view source function in your
+ browser. What you will see is:
+
+ * A head section that pulls in some stylesheets. Most notably, the
+ stylesheet from [bootstrap](http://getbootstrap.com/).
+
+ * a `<div>` element with an id of `main` followed by the HTML used
+ to present the first page fetched from the server. If you want to
+ see a different page, go to that page and hit refresh then view
+ source again. This content is nicely indented and other than
+ an abundance of `data-reactid` attributes that React uses to keep
+ track of things, it is fairly straightforward.
+
+ * a few `<script>` elements that pull in react, jquery, bootstrap, and
+ the agenda app itself. I suggest that you leave that for the moment,
+ we'll come back to it.
+
+ * an inline script that calls `React.render` with a datastructure
+ containing all the data the app needs on the client to do navigation.
+ Most importantly, this page contains a parsed agenda. Mentally file
+ that away for later consideration.
+
+ * Next I want you to find and launch your JavaScript console. In it, enter
+ the following expression: `Main.item`. If you are currently on the agenda
+ page, the results will be underwhelming. If so, go to another page, and
+ try again. You will see the data associated with the specific page you
+ are looking at. Instance variables will be preceded by an underscore.
+ Methods and computed properties will not be.
+
+ * If you are so inclined, you can actually make changes to the
+ datastructures. Those changes won't be visible until you re-render.
+ Something to try: `Main.item._report = 'All is Good!'; Main.refresh()`
+
+ * One last thing before we leave this section, go to an agenda page, and
+ replace the final `/` in the URL with `.json`. The contents you see is
+ what is fetched by the client when it needs to get an update of the data.
+ This data is heavily cached, so it takes negligible resources to check.
+
+Viewing Source (this time, Actual Code)
+---
+
+ * While you are unlikely to need to look at it, the agenda parsing logic
+ is in
[agenda.rb](https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/lib/whimsy/asf/agenda.rb)
+ plus the
[agenda](https://svn.apache.org/repos/infra/infrastructure/trunk/projects/whimsy/lib/whimsy/asf/agenda)
+ subdirectory.
+
+ * the `views/pages/index.js.rb` file contains the code for the agenda page.
+ It defines a class with a render method. Names that start with an
+ underscore become HTML elements. Nesting is generally represented by
+ `do`...`end` blocks, and occasionally (rarely) by curly braces. Attributes
+ are represented by `name: value` pairs. Note the complete lack of
+ `<%=` ... `%>` syntax required by things like JSP or erb. Iteration is
+ done by naming what you want to iterate over, and following the do with
+ a name in vertical bars that contains the instance.
+
+ Element names that start with a capital letter are essentially macros.
+ We'll come back to that.
+
+ * the `views/pages/search.js.rb` file contains the code for the search page.
+ There are more methods defined here. You will find definitions for
+ these methods in the React
+ [Lifecycle
Methods](http://facebook.github.io/react/docs/component-specs.html#lifecycle-methods).
+ You will see logic mixed with presentation. React is deadly serious when
+ it adopted the slogan "rethink best practices". What makes this work
+ is the component lifecycle that React provides. Components have mutable
+ state (which are the variables which are preceded by an `@` sign), and are
+ passed immutable properties (variables preceded by two `@` signs). Some
+ methods are prohibited from mutating state (most notable: the render
+ method). And one method (`componentWillReceiveProps`) even has access
+ to the before and after values for properties. Don't get hung up on the
+ logic here, but do go to the navigation bar on the top right of the
+ browser page, and select `Search` and play with search live.
+
+ * At this point, I suggest that you make a change. More specifically, I
+ suggest you break something. Insert the keyword `do` into a random spot
+ in either this or another file, and save your changes. This will cause
+ the server to restart. Hit refresh in the browser, and you will see
+ a stack traceback indicating where the problem is. Undo this change,
+ and then lets continue exploring.
+
+ * The `views/forms/add-comment.js.rb` file is probably a better example of
+ a component. The render function is more straightforward. Not mentioned
+ before, but element names followed by a dot followed by a name is a
+ shorthand for specifying HTML class attributes. And an element name
+ followed by a dot followed by an exclamation point is shorthand for
+ specifying HTML id attributes. Both of these innovations were first
+ pioneered by [markaby](http://markaby.github.io/).
+
+ Of special interest in this file is the `onChange` and `onClick`
+ attributes. This is how you associate an event with a method. The
+ `save` method will call post which will send data to the server.
+
+ * `views/actions/comment.json.rb` is the code which is run on the server
+ when you save a comment. It gets a list of pending items for this user,
+ modifies it based on the parameters passed, puts this data back and then
+ returns the modified list to the client (this is the last line, in Ruby
+ the keyword `return` is optional, and generally not used unless returning
+ from the middle of a method). Most server actions will be simple. Some
+ will do things like commit changes to svn.
+
+ * I mentioned previously that element names that start with a capital
+ letter are effectively macros. You've seen `Index`, `Search`, and
+ `AddComment` classes, each of which start with a capital letter. These
+ actually are examples of what React calls components that act like
+ macros. `views/main.html.rb' contains the 'top'. `views/app.js.rb`
+ lists all of the files that make up the client side of the application.
+
+ * This brings us back to to the app.js script mentioned much earlier.
+ If you visit http://localhost:9292/app.js you will see the full script.
+ Every bit of this JavaScript was generated from the js.rb files mentioned
+ above. Undoubtedly you have seen small amounts of JavaScript before
+ but I suspect that much of this looks foreign. Nicely indented,
+ vaguely familiar, but very foreign. Most people these days generate
+ JavaScript. Popular with React is something called JSX, but that's
+ both controversial and [doesn't support if
+ statements](http://facebook.github.io/react/tips/if-else-in-JSX.html).
+
+Testing
+---
+
+If you've made it this far, you've undoubtedly spent more than the five
+minutes I've asked of you. Hopefully, that's because I've piqued your
+interest. Having a test suite is important as it will allow you to
+confidently make changes without breaking things. If you haven't yet,
+I encourage you to install Poltergeist and io.js. Now onto the tests:
+
+ * `spec/parse_spec.rb` is a vanilla unit test that verifies that the
+ output of a parse matches what you would expect. This approach is
+ good testing out server side logic.
+
+ * `spec/index_spec.rb`, and `report_spec.rb`, and `spec/other_views_spec.rb`
+ uses [capybara](https://github.com/jnicklas/capybara) to verify that
+ the html produced matches what you would expect. This makes use of the
+ server side rendering of pages. Generally this involves identifying
+ things to look for in the HTML with CSS paths and either text or
+ attribute values. Clearly this approach is focused on verifying HTML
+ output.
+
+ * `spec/form_spec.rb` shows how client side logic (expressed in Ruby,
+ but compiled to JavaScript) can be tested. It does so by setting
+ up a http server (the code for which is in `spec/react_server.rb`)
+ which runs arbitrary scripts and returns the results as HTML. This
+ approach excels at testing a React component.
+
+ * Finally, `spec/navigate_spec.rb` actually tests functions with a real
+ (albeit headless) browser.
+
+Despite the diversity, the above tests have a lot of commonality and build
+on standard Ruby test functions. Together they should be able to cover
+pretty much any type of testing requirements.
+
+Conclusion
+---
+
+Congratulations for making it this far. To recap:
+
+ * You have gotten the whimsy agenda application running locally on your
+ own laptop or desktop. You've seen how to inspect and interact with
+ the running code, and explored a number of representative functions.
+
+ * You've made a change and saw it deployed immediately (even though the
+ change was to break things).
+
+ * You've run the tests, so you can confidently make changes and know that
+ they didn't break anything.
+
+ * Most of all, you've seen that things seems unreasonably fast without
+ you needing to expend much effort to make it so.
+
+This code clearly isn't complete. What I'm looking for is people who are
+wlling to experiment and contribute. Are you in?
+
+Gotchas
+---
+
+Nothing is perfect. Here are a few things to watch out for:
+
+ * In Ruby there isn't a difference between accessing attributes and methods
+ which have no arguments. In JavaScript there is. To make this work,
+ parenthesis are required when calling or defining methods that have
+ no arguments.
+
+ * In React, assignments to component state (@variables) don't take effect
+ immediately. You will find that individual methods tend to be short in
+ React components, but if you find yourself assigning to a state variable
+ and then reading it later in the same function you won't be seeing the
+ updated value.
+
+If you encounter any other gotchas, let me know and I'll update this README.
+
+Further reading:
+---
+
+ * [bootstrap](http://getbootstrap.com/)
+ * [capybara](https://github.com/jnicklas/capybara#readme)
+ * [react](http://facebook.github.io/react/).
+ * [ruby2js](https://github.com/rubys/ruby2js/#readme).
+ * [sinatra](http://www.sinatrarb.com/)
+ * [wunderbar](https://github.com/rubys/wunderbar/#readme).
diff --git a/views/main.html.rb b/views/main.html.rb
index a07c399..a70d0b8 100644
--- a/views/main.html.rb
+++ b/views/main.html.rb
@@ -7,7 +7,7 @@
_title 'ASF Board Agenda'
_link rel: 'stylesheet', href: '../stylesheets/app.css'
- _div.main!
+ _div_.main!
_script src: '../app.js'
_.render '#main' do