Skip to content

Commit

Permalink
React app displaying messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
dblock committed Nov 28, 2015
1 parent a93877a commit 9632e9f
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 54 deletions.
8 changes: 8 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ gem 'sdoc', '~> 0.4.0', group: :doc
# Slack Bot
gem 'slack-ruby-bot'

# HAML
gem 'haml-rails'

# React
gem 'react-rails'
gem 'sprockets-coffee-react'
gem 'js-routes'

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug'
Expand Down
42 changes: 42 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,24 @@ GEM
tzinfo (~> 1.1)
addressable (2.3.8)
arel (6.0.3)
babel-source (5.8.34)
babel-transpiler (0.7.0)
babel-source (>= 4.0, < 6)
execjs (~> 2.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
byebug (8.2.1)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0)
coffee-react (3.0.1)
execjs
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.10.0)
connection_pool (2.2.0)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
erubis (2.7.0)
Expand All @@ -72,7 +79,20 @@ GEM
launchy (~> 2.4)
globalid (0.3.6)
activesupport (>= 4.1.0)
haml (4.0.7)
tilt
haml-rails (0.9.0)
actionpack (>= 4.0.1)
activesupport (>= 4.0.1)
haml (>= 4.0.6, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
hashie (3.4.3)
html2haml (2.0.0)
erubis (~> 2.7.0)
haml (~> 4.0.0)
nokogiri (~> 1.6.0)
ruby_parser (~> 3.5)
i18n (0.7.0)
jbuilder (2.3.2)
activesupport (>= 3.0.0, < 5)
Expand All @@ -81,6 +101,9 @@ GEM
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
js-routes (1.1.2)
railties (>= 3.2)
sprockets-rails
json (1.8.3)
launchy (2.4.3)
addressable (~> 2.3)
Expand Down Expand Up @@ -125,6 +148,13 @@ GEM
thor (>= 0.18.1, < 2.0)
rake (10.4.2)
rdoc (4.2.0)
react-rails (1.5.0)
babel-transpiler (>= 0.7.0)
coffee-script-source (~> 1.8)
connection_pool
execjs
rails (>= 3.2)
tilt
rspec-core (3.4.1)
rspec-support (~> 3.4.0)
rspec-expectations (3.4.0)
Expand All @@ -142,6 +172,8 @@ GEM
rspec-mocks (~> 3.4.0)
rspec-support (~> 3.4.0)
rspec-support (3.4.1)
ruby_parser (3.7.2)
sexp_processor (~> 4.1)
sass (3.4.19)
sass-rails (5.0.4)
railties (>= 4.0.0, < 5.0)
Expand All @@ -152,6 +184,7 @@ GEM
sdoc (0.4.1)
json (~> 1.7, >= 1.7.7)
rdoc (~> 4.0)
sexp_processor (4.6.0)
slack-ruby-bot (0.4.5)
activesupport
giphy (~> 2.0.2)
Expand All @@ -167,6 +200,11 @@ GEM
spring (1.4.4)
sprockets (3.4.1)
rack (> 1, < 3)
sprockets-coffee-react (3.0.1)
coffee-react (>= 3.0.1)
coffee-script
sprockets
tilt
sprockets-rails (2.3.3)
actionpack (>= 3.0)
activesupport (>= 3.0)
Expand Down Expand Up @@ -197,14 +235,18 @@ PLATFORMS
DEPENDENCIES
byebug
coffee-rails (~> 4.1.0)
haml-rails
jbuilder (~> 2.0)
jquery-rails
js-routes
rails (= 4.2.4)
react-rails
rspec-rails
sass-rails (~> 5.0)
sdoc (~> 0.4.0)
slack-ruby-bot
spring
sprockets-coffee-react
sqlite3
turbolinks
uglifier (>= 1.3.0)
Expand Down
3 changes: 3 additions & 0 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require react
//= require react_ujs
//= require js-routes
//= require_tree .
12 changes: 12 additions & 0 deletions app/assets/javascripts/react/messages/message.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# @cjsx React.DOM

@Message = React.createClass
displayName: 'Message'
render: ->
# let's use this add-on to set the main div's class names
cx = React.addons.classSet

# here we use the calculated classes
<div className="message">
{@props.data.id}: {@props.data.message?.text}
</div>
69 changes: 69 additions & 0 deletions app/assets/javascripts/react/messages_section.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# @cjsx React.DOM

@MessagesSection = React.createClass
# Display name used for debugging
displayName: 'MessagesSection'

# Invoked before the component is mounted and provides the initial
# state for the render method.
getInitialState: ->
# We'll change it to true once we fetch data
didFetchData: false
# The messages JSON array used to display the messages in the view
messages: []

# Invoked right after the component renders
componentDidMount: ->
# Lets fetch all the messages...
@_fetchMessages()
setInterval(@_fetchMessages, 1000);

# AJAX call to our MessagesController
_fetchMessages: ()->
$.ajax
url: Routes.messages_path()
.done @_fetchDataDone
.fail @_fetchDataFail

# If the AJAX call is successful...
_fetchDataDone: (data, textStatus, jqXHR) ->
# We change the state of the component. This will cause the component and
# it's children to render again
@setState
didFetchData: true
messages: data

# If errors in AJAX call...
_fetchDataFail: (xhr, status, err) =>
console.error @props.url, status, err.toString()

# How the component is going to be rendered to the user depending on it's
# props and state...
render: ->
# The collection of Message components we are going to display
# using the messages stored in the component's state
messagesNode = @state.messages.map (message) ->
# Message component with a data property containing all the JSON
# attributes we are going to use to display it to the user
<Message key={message.id} data={message}/>

# HTML displayed if no messages found in it's state
noDataNode =
<div className="warning">
<h4>No messages found...</h4>
</div>

# Here starts the render result
<div>
<div className="messages-wrapper">
{
# If there are messages render the messages...
if @state.messages.length > 0
messagesNode
# If has fetched data and no messages found, render the
# warning message instead
else if @state.didFetchData
noDataNode
}
</div>
</div>
4 changes: 4 additions & 0 deletions app/controllers/home_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class HomeController < ApplicationController
def index
end
end
8 changes: 8 additions & 0 deletions app/controllers/messages_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class MessagesController < ApplicationController
def index
data = (1..10).map do |i|
{ id: i, message: Rails.cache.read(i) }
end
render json: data
end
end
5 changes: 5 additions & 0 deletions app/views/home/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
%section
%header
%h1 Tattletale

= react_component 'MessagesSection', {}, :div
7 changes: 7 additions & 0 deletions bot/say.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
class Say < SlackRubyBot::Commands::Base
@id = 0

def self.next_id
@id = @id % 10 + 1
end

command 'say' do |client, data, match|
Rails.cache.write next_id, { text: match['expression'] }
send_message client, data.channel, match['expression']
end
end
3 changes: 3 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ class Application < Rails::Application

# Do not swallow errors in after_commit/after_rollback callbacks.
config.active_record.raise_in_transactional_callbacks = true

# React config
config.react.addons = true
end
end
56 changes: 2 additions & 54 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,56 +1,4 @@
Rails.application.routes.draw do
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".

# You can have the root of your site routed with "root"
# root 'welcome#index'

# Example of regular route:
# get 'products/:id' => 'catalog#view'

# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase

# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products

# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end

# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end

# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end

# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable

# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
root 'home#index'
resources :messages, only: :index
end

0 comments on commit 9632e9f

Please sign in to comment.