Skip to content

Commit

Permalink
Grumble on Rails, almost
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielg committed Dec 20, 2008
1 parent eba4d24 commit 28a51fa
Show file tree
Hide file tree
Showing 42 changed files with 605 additions and 221 deletions.
34 changes: 27 additions & 7 deletions app/controllers/application_controller.rb
Expand Up @@ -2,14 +2,34 @@
# Likewise, all the methods added will be available for all controllers.

class ApplicationController < ActionController::Base

helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details

# See ActionController::RequestForgeryProtection for details
# Uncomment the :secret if you're not using the cookie session store
protect_from_forgery # :secret => '73e34eb8d66e3353099a52e08d7d9040'

# See ActionController::Base for details
# Uncomment this to filter the contents of submitted sensitive data parameters
# from your application log (in this case, all fields with names like "password").
# Scrub sensitive parameters from your log
# filter_parameter_logging :password

private

def load_target
if target_id = params[:target_id]
@target = Target.find_or_initialize_by_uri(params[:target_id])
@target.save if @target.new_record?
raise ActiveRecord::RecordInvalid.new(@target) unless @target.valid?
else
raise ActiveRecord::RecordNotFound
end
end

def render_json(obj, opts = {})
json = obj.to_json
json = "var grumbleData = (#{json});\n\nGrumble.#{opts[:callback]}(grumbleData)\n" if opts[:callback] && callback_requested?
response.content_type = 'application/json'
render :text => json, :status => opts[:status] || :ok
end

def callback_requested?
params[:callback] == 'true'
end

end
2 changes: 2 additions & 0 deletions app/controllers/grumblers_controller.rb
@@ -0,0 +1,2 @@
class GrumblersController < ApplicationController
end
30 changes: 30 additions & 0 deletions app/controllers/grumbles_controller.rb
@@ -0,0 +1,30 @@
class GrumblesController < ApplicationController
before_filter :load_target

def index
grumbles = @target.grumbles.map { |grumble| grumble_attributes(grumble) }
render_json({:grumbles => grumbles}, :callback => 'getGrumbles')
end

def create
grumble = @target.grumbles.build(params[:grumble].slice(:subject, :body, :anon_grumbler_name))
if grumble.save
#status(201)
render_json({:grumble => grumble_attributes(grumble)}, :callback => 'grumbleCreated', :status => :created)
else
throw(:halt, [406, [:invalid_record, grumble]])
end
end

private

def grumble_attributes(grumble)
grumble_data = {:id => grumble.uuid, :grumble_url => grumble_url(:id => grumble, :target_id => grumble.target),
:grumbler_name => grumble.grumbler_name, :subject => grumble.subject, :body => grumble.body,
:created_at => grumble.created_at}
grumble_data[:grumbler_url] = grumbler_url(grumble.grumbler) if grumble.grumbler
grumble_data
end


end
19 changes: 19 additions & 0 deletions app/controllers/targets_controller.rb
@@ -0,0 +1,19 @@
class TargetsController < ApplicationController
before_filter :load_target
rescue_from ActiveRecord::RecordNotFound, :with => :target_not_found
rescue_from ActiveRecord::RecordInvalid, :with => :target_invalid

def show
render_json({:target => {:grumble_count => @target.grumbles.count.to_i,
:new_grumble_url => new_grumble_url(:target_id => @target),
:grumble_index_url => grumbles_url(:target_id => @target)}},
:callback => 'getTarget')
end

private

def target_not_found
render :nothing => true, :status => :not_found
end

end
2 changes: 2 additions & 0 deletions app/helpers/grumblers_helper.rb
@@ -0,0 +1,2 @@
module GrumblersHelper
end
2 changes: 2 additions & 0 deletions app/helpers/grumbles_helper.rb
@@ -0,0 +1,2 @@
module GrumblesHelper
end
2 changes: 2 additions & 0 deletions app/helpers/targets_helper.rb
@@ -0,0 +1,2 @@
module TargetsHelper
end
4 changes: 4 additions & 0 deletions app/models/grumble.rb
Expand Up @@ -16,6 +16,10 @@ def registered_grumbler?
!grumbler.nil?
end

def to_param
uuid
end

private

def set_uuid
Expand Down
3 changes: 3 additions & 0 deletions app/models/target.rb
Expand Up @@ -6,6 +6,9 @@ class Target < ActiveRecord::Base
validate :validate_uri
has_many :grumbles, :order => 'created_at DESC'

def to_param
uri
end
private

def validate_uri
Expand Down
5 changes: 2 additions & 3 deletions config/environment.rb
Expand Up @@ -32,7 +32,6 @@
config.gem 'mocha'
config.gem 'haml'
config.gem 'uuidtools'

# Only load the plugins named here, in the order given. By default, all plugins
# in vendor/plugins are loaded in alphabetical order.
# :all can be used as a placeholder for all plugins not explicitly named
Expand All @@ -48,7 +47,7 @@
# Make Time.zone default to the specified zone, and make Active Record store time values
# in the database in UTC, and return them converted to the specified local zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Comment line to use default local time.
config.time_zone = 'UTC'
config.time_zone = ENV['TZ'] = 'UTC'

# The internationalization framework can be changed to have another default locale (standard is :en) or more load paths.
# All files from config/locales/*.rb,yml are added automatically.
Expand Down Expand Up @@ -77,4 +76,4 @@
# Activate observers that should always be running
# Please note that observers generated using script/generate observer need to have an _observer suffix
# config.active_record.observers = :cacher, :garbage_collector, :forum_observer
end
end
1 change: 1 addition & 0 deletions config/initializers/load_libraries.rb
@@ -0,0 +1 @@
require 'ruby-debug' if Rails.env.test? || Rails.env.development?
1 change: 1 addition & 0 deletions config/initializers/routing_overrides.rb
@@ -0,0 +1 @@
#ActionController::Routing::SEPARATORS.delete('.')
17 changes: 17 additions & 0 deletions config/routes.rb
@@ -1,4 +1,21 @@
ActionController::Routing::Routes.draw do |map|

# targets GET /targets(.:format) {:controller=>"targets", :action=>"index"}
# POST /targets(.:format) {:controller=>"targets", :action=>"create"}
# new_target GET /targets/new(.:format) {:controller=>"targets", :action=>"new"}
# edit_target GET /targets/:id/edit(.:format) {:controller=>"targets", :action=>"edit"}
# target GET /targets/:id(.:format) {:controller=>"targets", :action=>"show"}
# PUT /targets/:id(.:format) {:controller=>"targets", :action=>"update"}
# DELETE /targets/:id(.:format) {:controller=>"targets", :action=>"destroy"}
map.new_target '/targets', :controller => 'targets', :action => 'new'
map.target '/targets/:target_id', :controller => 'targets', :action => 'show'

map.new_grumble '/targets/:target_id/grumbles/new', :controller => 'grumbles', :action => 'new'
map.grumbles '/targets/:target_id/grumbles', :controller => 'grumbles', :action => 'index'
map.grumble '/targets/:target_id/grumbles/:id', :controller => 'grumbles', :action => 'show'

map.grumbler '/grumblers/:id', :controller => 'grumblers', :action => 'show'

# The priority is based upon order of creation: first created -> highest priority.

# Sample of regular route:
Expand Down
8 changes: 8 additions & 0 deletions test/functional/grumblers_controller_test.rb
@@ -0,0 +1,8 @@
require 'test_helper'

class GrumblersControllerTest < ActionController::TestCase
# Replace this with your real tests.
test "the truth" do
assert true
end
end
160 changes: 160 additions & 0 deletions test/functional/grumbles_controller_test.rb
@@ -0,0 +1,160 @@
require 'test_helper'

class GrumblesControllerTest < ActionController::TestCase

should "call a callback function if callback=true parameter is given" do
get :index, :target_id => "http://www.example.com/posts/12/", :callback => "true"
assert_match %r[Grumble.getGrumbles\(.*\)], @response.body
end

context "GET request with valid target" do
setup do
@target = Factory(:target)
json_response { get :index, :target_id => @target.uri }
end

should "return a JSON list of grumbles" do
assert_equal @target.grumbles.size, @json_response['grumbles'].size
end

context "returned grumble" do
context "by a non registered grumbler" do
setup do
grumble = @target.grumbles.detect { |g| !g.registered_grumbler? }
@json_grumble = @json_response['grumbles'].detect { |g| g['id'] == grumble.uuid }
end

should "have a grumble_url" do
deny @json_grumble['grumble_url'].blank?
end

should "have a grumbler_name" do
deny @json_grumble['grumbler_name'].blank?
end

should "not have a grumbler_url" do
assert @json_grumble['grumbler_url'].blank?
end

should "have a subject" do
deny @json_grumble['subject'].blank?
end

should "have a body" do
deny @json_grumble['body'].blank?
end

should "have a created_at" do
deny @json_grumble['created_at'].blank?
end

end # by a non registered grumbler

context "by a registered grumbler" do
setup do
grumble = @target.grumbles.detect(&:registered_grumbler?)
@json_grumble = @json_response['grumbles'].detect { |g| g['id'] == grumble.uuid }
end

should "have a grumble_url" do
deny @json_grumble['grumble_url'].blank?
end

should "have a grumbler_name" do
deny @json_grumble['grumbler_name'].blank?
end

should "have a grumbler_url" do
deny @json_grumble['grumbler_url'].blank?
end

should "have a subject" do
deny @json_grumble['subject'].blank?
end

should "have a body" do
deny @json_grumble['body'].blank?
end

should "have a created_at" do
deny @json_grumble['created_at'].blank?
end

end # by a registered grumbler

end # returned grumbles

end # GET

context "POST request with valid target" do

context "with valid grumble attributes and a brand new target" do
setup do
@target = Factory.build(:target)
grumble_attrs = Factory.attributes_for(:grumble)
json_response { post :create, :target_id => @target.uri, :grumble => grumble_attrs }
@json_grumble = @json_response['grumble']
end

should_change "Target.count", :by => 1
should_change "Grumble.count", :by => 1

should "create a target with the URI specified" do
assert Target.find_by_uri(@target.uri)
end

end # with valid grumble attributes and a brand new target

setup do
@target = Factory(:target)
end

context "by a non registered user" do

should "call a callback function if callback=true parameter is given" do
grumble_attrs = Factory.attributes_for(:grumble)
post :create, :target_id => @target.uri, :grumble => grumble_attrs, :callback => 'true'
assert_match %r[Grumble.grumbleCreated\(.*\)], @response.body
end

context "with valid grumble attributes" do
setup do
grumble_attrs = Factory.attributes_for(:grumble)
json_response { post :create, :target_id => @target.uri, :grumble => grumble_attrs }
@json_grumble = @json_response['grumble']
end

should "respond with 201 created" do
assert_response :created
end

should "have a grumble_url" do
deny @json_grumble['grumble_url'].blank?
end

should "have a grumbler_name" do
deny @json_grumble['grumbler_name'].blank?
end

should "not have a grumbler_url" do
assert @json_grumble['grumbler_url'].blank?
end

should "have a subject" do
deny @json_grumble['subject'].blank?
end

should "have a body" do
deny @json_grumble['body'].blank?
end

should "have a created_at" do
deny @json_grumble['created_at'].blank?
end
end # with valid grumble attributes

end # by a non registered user

end # POST request with valid target

end

0 comments on commit 28a51fa

Please sign in to comment.