question_chain 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +110 -8
- data/lib/question_chain/answerable.rb +16 -23
- data/lib/question_chain/models/chain_template.rb +5 -1
- data/lib/question_chain/models/ui_object.rb +6 -4
- data/lib/question_chain/state_machine.rb +1 -1
- data/lib/question_chain/version.rb +1 -1
- data/question_chain.gemspec +3 -3
- data/test_app/Gemfile +4 -4
- data/test_app/environments/test.rb +1 -1
- data/test_app/spec/factories.rb +6 -0
- data/test_app/spec/models/flight_spec.rb +10 -10
- data/test_app/spec/models/ui_group_spec.rb +1 -1
- data/test_app/spec/spec_helper.rb +13 -0
- metadata +9 -11
- data/test_app/spec/acceptance/new_spec +0 -30
data/README.rdoc
CHANGED
@@ -2,19 +2,123 @@
|
|
2
2
|
|
3
3
|
== What Am I?
|
4
4
|
|
5
|
-
|
5
|
+
There will be guides on how to use this http://guides.carboncalculated.com;
|
6
6
|
|
7
|
-
|
7
|
+
This Rails3 Engine allows you to create a forms for Carbon Calculations in like 2 sometimes 3 minutes depending on typing speed.
|
8
8
|
|
9
|
-
|
10
|
-
to be used with the CarbonCalculated API http://carboncalculated.com
|
9
|
+
== Dependencies
|
11
10
|
|
12
|
-
|
11
|
+
MongoMapper 0.9.0
|
13
12
|
|
14
|
-
|
13
|
+
Mongoid 2.0.0 (mongoid branch)
|
14
|
+
|
15
|
+
Note you will have to go through a few hoops to get this working currently however once you have UI for carbon calculations
|
16
|
+
can be generated very very quickly!
|
17
|
+
|
18
|
+
If you really want to dive in then please look at this example application using question chain;
|
19
|
+
|
20
|
+
https://github.com/carboncalculated/example-question-chain-application
|
15
21
|
|
16
22
|
== Getting started
|
17
23
|
|
24
|
+
Firstly You will need to be using creating a Rails3 Application;
|
25
|
+
|
26
|
+
add question_chain to your Gemfile
|
27
|
+
|
28
|
+
gem "question_chain"
|
29
|
+
|
30
|
+
you will also need the QuestionChainJS https://github.com/carboncalculated/QuestionChainJS
|
31
|
+
|
32
|
+
This is currently Mootools dependent;
|
33
|
+
|
34
|
+
== Setup
|
35
|
+
|
36
|
+
You will need to create a method (calculated_session) on your Rails Application Module; as question_chain
|
37
|
+
will look for a calculated session here when it talks to the carbon calculated API
|
38
|
+
|
39
|
+
module YourApplication
|
40
|
+
def self.calculated_session
|
41
|
+
@session ||= Calculated::Session.create(:api_key => ENV[:api_key])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
=== Background Information
|
46
|
+
|
47
|
+
With quesition_chain you are given a Rails3 Engine; this engine provides you with the following;
|
48
|
+
|
49
|
+
* Controller Module: (QuestionChain::Answers) For creating editing models that emit carbon (ie Journey; Material; Waste; Car)
|
50
|
+
|
51
|
+
* Model Module: (QuestionChain::Answerable) Helper Methods for any model that emits carbon.
|
52
|
+
|
53
|
+
* ChainTemplate: Defines context of where in your application your emitting models are located and what if any parent resources
|
54
|
+
it has; example
|
55
|
+
|
56
|
+
* Question: You build a "Question" its this quesition id (4babb5fef78b124341000002) that is then rendered for calculations in the UI
|
57
|
+
|
58
|
+
Please look at the example application that uses this Gem; before you go any further
|
59
|
+
|
60
|
+
=== Questions
|
61
|
+
|
62
|
+
This is where you can build up your UI for the question you wish to ask to calculated emissions;
|
63
|
+
|
64
|
+
* "What was your origin airport and destination airport?"
|
65
|
+
* "How many miles did you travel in your car?"
|
66
|
+
* "What material and how many tones of it do you use?"
|
67
|
+
|
68
|
+
Each question will relate to the CarbonCalcualated API! therefore a question will need either a
|
69
|
+
computation_id or a calculator_id
|
70
|
+
|
71
|
+
At the minute there is no UI for creating these question however there are example rake tasks that can be
|
72
|
+
seen in the example application
|
73
|
+
|
74
|
+
=== ChainTemplate
|
75
|
+
|
76
|
+
This where you can define "calculation contexts"; what does that mean? this is where you can say what resource
|
77
|
+
emits and its association with another resource; Example below is basically saying for user class it has
|
78
|
+
many flights these flights are to seen as a QuestionChain Question; Its the flight that emits Carbon!
|
79
|
+
|
80
|
+
ChainTemplate.create!(
|
81
|
+
:for_resource => "user",
|
82
|
+
:context => {
|
83
|
+
"flights" => ["4babb5fef78b124341000002"]
|
84
|
+
})
|
85
|
+
|
86
|
+
=== Controllers
|
87
|
+
|
88
|
+
=== Routing
|
89
|
+
|
90
|
+
There is currently not a helper for the routing however this is an example structure to get an application working
|
91
|
+
where the context is a calculation model
|
92
|
+
|
93
|
+
# == Have yet to create a Routing helper from question Chain
|
94
|
+
# Hence manua here and this is about is obvious well its just not
|
95
|
+
match '/answers/fire_object_search' => 'answers#fire_object_search'
|
96
|
+
match '/answers/fire_populate_drop_down' => 'answers#fire_populate_drop_down'
|
97
|
+
|
98
|
+
chain_template_routes = lambda do
|
99
|
+
scope "/:context(/:question_id)" do
|
100
|
+
resources :answers, :only => [:new, :create, :index] do
|
101
|
+
collection do
|
102
|
+
post :fire_populate_drop_down
|
103
|
+
post :fire_object_search
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
scope "/:context" do
|
109
|
+
resources :answers, :only => [:edit, :update, :show] do
|
110
|
+
collection do
|
111
|
+
post :fire_populate_drop_down
|
112
|
+
post :fire_object_search
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
resource :users do
|
119
|
+
chain_template_routes.call
|
120
|
+
end
|
121
|
+
|
18
122
|
== UiObjects
|
19
123
|
|
20
124
|
=== Drop Downs
|
@@ -30,5 +134,3 @@ At the minute this has dependencies on MongoMapper currently thinking about movi
|
|
30
134
|
=== Markup
|
31
135
|
|
32
136
|
=== CSS
|
33
|
-
|
34
|
-
=== Bundling
|
@@ -2,6 +2,7 @@ module QuestionChain
|
|
2
2
|
module Answerable
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
include MongoMapper::Serialize
|
5
|
+
|
5
6
|
|
6
7
|
included do
|
7
8
|
key :question_id, ObjectId
|
@@ -22,7 +23,7 @@ module QuestionChain
|
|
22
23
|
before_save :cache_attributes
|
23
24
|
|
24
25
|
# == Search
|
25
|
-
|
26
|
+
include Hunt
|
26
27
|
searches :reference, :created_by, :stored_variable_input, :stored_identifier, :_extra_keywords
|
27
28
|
ensure_index :'searches.default'
|
28
29
|
|
@@ -35,8 +36,9 @@ module QuestionChain
|
|
35
36
|
validates_presence_of :question_id
|
36
37
|
validates_presence_of :answer_params
|
37
38
|
validates_presence_of :result
|
38
|
-
|
39
|
-
|
39
|
+
validates_presence_of :user
|
40
|
+
validate :valid_answer_params
|
41
|
+
validate :valid_result
|
40
42
|
|
41
43
|
# == Associations
|
42
44
|
belongs_to :user
|
@@ -45,25 +47,7 @@ module QuestionChain
|
|
45
47
|
attr_protected :user_id
|
46
48
|
|
47
49
|
end
|
48
|
-
|
49
|
-
module ClassMethods
|
50
|
-
require "csv" #ruby19
|
51
|
-
def self.to_csv(options = {})
|
52
|
-
@csv_string ||= FasterCSV.generate do |csv|
|
53
|
-
# header row
|
54
|
-
csv << self.attributes_for_api
|
55
|
-
|
56
|
-
# data rows
|
57
|
-
self.all(options).each do |resource|
|
58
|
-
attributes = self.attributes_for_api.map do |key|
|
59
|
-
resource.send(key)
|
60
|
-
end
|
61
|
-
csv << attributes
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
50
|
+
|
67
51
|
module InstanceMethods
|
68
52
|
def add_extra_keywords
|
69
53
|
unless (self.class._extra_keyword_methods || []).empty?
|
@@ -134,9 +118,18 @@ module QuestionChain
|
|
134
118
|
end
|
135
119
|
|
136
120
|
def cache_attributes
|
137
|
-
write_attribute(:created_by, user.full_name)
|
121
|
+
write_attribute(:created_by, user.full_name) if user && user.respond_to?(:full_name)
|
138
122
|
write_attribute(:stored_variable_input, variable_input)
|
139
123
|
end
|
124
|
+
|
125
|
+
def valid_answer_params
|
126
|
+
errors.add(:answer_params, "") if answer_params.empty?
|
127
|
+
end
|
128
|
+
|
129
|
+
def valid_result
|
130
|
+
errors.add(:result, "") if result.empty?
|
131
|
+
end
|
140
132
|
end
|
133
|
+
|
141
134
|
end
|
142
135
|
end
|
@@ -29,7 +29,7 @@ class ChainTemplate
|
|
29
29
|
# == Validations
|
30
30
|
validates_presence_of :for_resource
|
31
31
|
validates_presence_of :context
|
32
|
-
|
32
|
+
validate :valid_context
|
33
33
|
|
34
34
|
def self.attributes_for_api
|
35
35
|
%w(id name for_resource account_id parent_resource)
|
@@ -40,4 +40,8 @@ class ChainTemplate
|
|
40
40
|
self.active_at = Time.now
|
41
41
|
self.save!
|
42
42
|
end
|
43
|
+
|
44
|
+
def valid_context
|
45
|
+
errors.add(:context, "") if context.empty?
|
46
|
+
end
|
43
47
|
end
|
@@ -33,9 +33,7 @@ class UiObject
|
|
33
33
|
validates_presence_of :ui_group_id
|
34
34
|
validates_presence_of :label
|
35
35
|
validates_presence_of :ui_attributes
|
36
|
-
|
37
|
-
!ui_attributes.empty?
|
38
|
-
}
|
36
|
+
validate :valid_ui_attributes
|
39
37
|
validates_associated :rules
|
40
38
|
|
41
39
|
# == Associations
|
@@ -44,7 +42,7 @@ class UiObject
|
|
44
42
|
|
45
43
|
# == Hooks
|
46
44
|
before_save :add_rule_observers!
|
47
|
-
|
45
|
+
before_validation :set_default_attributes, :on => :create
|
48
46
|
|
49
47
|
def self.attributes_for_api
|
50
48
|
%w(id name _type label description default_value ui_attributes ui_group_id rules extra_info css_classes)
|
@@ -88,5 +86,9 @@ class UiObject
|
|
88
86
|
self.add_observer(rule, :fire!)
|
89
87
|
end
|
90
88
|
end
|
89
|
+
|
90
|
+
def valid_ui_attributes
|
91
|
+
errors.add(:ui_attributes, "") if ui_attributes.empty?
|
92
|
+
end
|
91
93
|
|
92
94
|
end
|
data/question_chain.gemspec
CHANGED
@@ -9,13 +9,13 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Richard Hooker"]
|
10
10
|
s.email = ["richard.hooker@carboncalculated.com"]
|
11
11
|
s.homepage = ""
|
12
|
-
s.summary = %q{Rails3 Gem to Generate Carbon Calculated
|
13
|
-
s.description = %q{Rails3 Gem to Generate Carbon Calculated
|
12
|
+
s.summary = %q{Rails3 Gem to Generate Carbon Calculated Applications}
|
13
|
+
s.description = %q{Rails3 Gem to Generate Carbon Calculated Applications}
|
14
14
|
|
15
15
|
s.rubyforge_project = "question_chain"
|
16
16
|
|
17
17
|
s.add_dependency 'mustache', '>= 0.98.0'
|
18
|
-
s.add_dependency 'mongo_mapper', '
|
18
|
+
s.add_dependency 'mongo_mapper', '~> 0.9.0'
|
19
19
|
s.add_dependency 'mustache', '>= 0.98.0'
|
20
20
|
s.add_dependency 'hashie', ">= 0.2.1"
|
21
21
|
s.add_dependency 'crack', ">= 0.1.8"
|
data/test_app/Gemfile
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
source 'http://rubygems.org'
|
2
2
|
|
3
3
|
## Bundle the gems you use:
|
4
|
-
gem "rails", "3.0.
|
4
|
+
gem "rails", "3.0.7"
|
5
5
|
|
6
|
-
gem "bson_ext", "1.
|
6
|
+
gem "bson_ext", "1.3.0"
|
7
7
|
gem "inherited_resources"
|
8
|
-
gem "mongo_mapper", "0.
|
9
|
-
gem "hunt"
|
8
|
+
gem "mongo_mapper", "~> 0.9.0"
|
9
|
+
gem "hunt", :git => "git://github.com/hookercookerman/hunt.git"
|
10
10
|
gem "transitions"
|
11
11
|
gem "question_chain", :path =>File.expand_path("../../", __FILE__), :require => "question_chain"
|
12
12
|
gem "yard"
|
data/test_app/spec/factories.rb
CHANGED
@@ -15,11 +15,17 @@ Factory.sequence :related_attribute do |n|
|
|
15
15
|
"related_attribute_#{n}"
|
16
16
|
end
|
17
17
|
|
18
|
+
Factory.define :user do |f|
|
19
|
+
f.first_name {"Egg"}
|
20
|
+
f.last_name {"Beans"}
|
21
|
+
end
|
22
|
+
|
18
23
|
Factory.define :flight do |f|
|
19
24
|
f.question_id {BSON::ObjectId.new}
|
20
25
|
f.result{ {"co2"=> "45.5", "object_references" => {"123" => {"identifier" => "beans"}}}}
|
21
26
|
f.answer_params {{"flight" => "123"}}
|
22
27
|
f.reference {Factory.next(:name)}
|
28
|
+
f.association :user
|
23
29
|
end
|
24
30
|
|
25
31
|
Factory.define :chain_template do |f|
|
@@ -8,14 +8,14 @@ describe "Flight (Test Model)" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should have answerable keys" do
|
11
|
-
@flight.keys.should include(
|
12
|
-
@flight.keys.should include(
|
13
|
-
@flight.keys.should include(
|
14
|
-
@flight.keys.should include(
|
15
|
-
@flight.keys.should include(
|
16
|
-
@flight.keys.should include(
|
17
|
-
@flight.keys.should include(
|
18
|
-
@flight.keys.should include(
|
11
|
+
@flight.keys.should include("question_id")
|
12
|
+
@flight.keys.should include("result")
|
13
|
+
@flight.keys.should include("answer_params")
|
14
|
+
@flight.keys.should include("answer_json")
|
15
|
+
@flight.keys.should include("user_id")
|
16
|
+
@flight.keys.should include("reference")
|
17
|
+
@flight.keys.should include("stored_identifier")
|
18
|
+
@flight.keys.should include("_extra_keywords")
|
19
19
|
end
|
20
20
|
|
21
21
|
it "Should have access to _extra_keyword class method" do
|
@@ -63,8 +63,8 @@ describe "Flight (Test Model)" do
|
|
63
63
|
flights.first.should == @flight
|
64
64
|
end
|
65
65
|
|
66
|
-
it "should not be found on a silly search like
|
67
|
-
flights = Flight.search "
|
66
|
+
it "should not be found on a silly search like crumpets" do
|
67
|
+
flights = Flight.search "crumpets"
|
68
68
|
flights.should be_empty
|
69
69
|
end
|
70
70
|
end
|
@@ -32,7 +32,7 @@ describe "UiGroup" do
|
|
32
32
|
@ui_group = Factory.build(:ui_group)
|
33
33
|
@text_field = @ui_group.text_fields.create!(Factory.attributes_for(:text_field))
|
34
34
|
@relatable_category_drop_down = @ui_group.relatable_category_drop_downs.create!(Factory.attributes_for(:relatable_category_drop_down))
|
35
|
-
@object_referenece_drop_down = @ui_group.
|
35
|
+
@object_referenece_drop_down = @ui_group.create_object_reference_drop_down(Factory.attributes_for(:object_reference_drop_down))
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should have 3 ui_objects" do
|
@@ -4,6 +4,19 @@ require 'rspec/rails'
|
|
4
4
|
|
5
5
|
# Requires supporting files with custom matchers and macros, etc,
|
6
6
|
# in ./support/ and its subdirectories.
|
7
|
+
class User
|
8
|
+
include MongoMapper::Document
|
9
|
+
|
10
|
+
# == Keys
|
11
|
+
key :first_name, String
|
12
|
+
key :last_name, String
|
13
|
+
|
14
|
+
def full_name
|
15
|
+
"#{first_name} #{last_name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
7
20
|
require File.expand_path("../factories", __FILE__)
|
8
21
|
|
9
22
|
require "database_cleaner"
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Richard Hooker
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-04-19 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -38,13 +38,13 @@ dependencies:
|
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
|
-
- -
|
41
|
+
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
segments:
|
44
44
|
- 0
|
45
|
-
-
|
46
|
-
-
|
47
|
-
version: 0.
|
45
|
+
- 9
|
46
|
+
- 0
|
47
|
+
version: 0.9.0
|
48
48
|
type: :runtime
|
49
49
|
version_requirements: *id002
|
50
50
|
- !ruby/object:Gem::Dependency
|
@@ -152,7 +152,7 @@ dependencies:
|
|
152
152
|
version: 0.3.0
|
153
153
|
type: :runtime
|
154
154
|
version_requirements: *id009
|
155
|
-
description: Rails3 Gem to Generate Carbon Calculated
|
155
|
+
description: Rails3 Gem to Generate Carbon Calculated Applications
|
156
156
|
email:
|
157
157
|
- richard.hooker@carboncalculated.com
|
158
158
|
executables: []
|
@@ -244,7 +244,6 @@ files:
|
|
244
244
|
- test_app/lib/tasks/yard.rake
|
245
245
|
- test_app/public/.gitkeep
|
246
246
|
- test_app/script/rails
|
247
|
-
- test_app/spec/acceptance/new_spec
|
248
247
|
- test_app/spec/factories.rb
|
249
248
|
- test_app/spec/models/chain_template_spec.rb
|
250
249
|
- test_app/spec/models/flight_spec.rb
|
@@ -286,7 +285,7 @@ rubyforge_project: question_chain
|
|
286
285
|
rubygems_version: 1.3.7
|
287
286
|
signing_key:
|
288
287
|
specification_version: 3
|
289
|
-
summary: Rails3 Gem to Generate Carbon Calculated
|
288
|
+
summary: Rails3 Gem to Generate Carbon Calculated Applications
|
290
289
|
test_files:
|
291
290
|
- test_app/Gemfile
|
292
291
|
- test_app/Rakefile
|
@@ -312,7 +311,6 @@ test_files:
|
|
312
311
|
- test_app/lib/tasks/yard.rake
|
313
312
|
- test_app/public/.gitkeep
|
314
313
|
- test_app/script/rails
|
315
|
-
- test_app/spec/acceptance/new_spec
|
316
314
|
- test_app/spec/factories.rb
|
317
315
|
- test_app/spec/models/chain_template_spec.rb
|
318
316
|
- test_app/spec/models/flight_spec.rb
|
@@ -1,30 +0,0 @@
|
|
1
|
-
# Todo For Acceptance Specs
|
2
|
-
|
3
|
-
# Feature: New Answer (for a Flight)
|
4
|
-
# In order add a new answer for a resource that can have a co2 computation
|
5
|
-
# As an application user
|
6
|
-
# I want to be able create a new answer
|
7
|
-
#
|
8
|
-
# Scenario: New Answer for a flight resource (Question wants a distance and a flight)
|
9
|
-
# Given a flight context exists with a valid question
|
10
|
-
# When go to the new flight answers page
|
11
|
-
#
|
12
|
-
# Then show me the page
|
13
|
-
# And I should see "Flight Calculator" within "#question"
|
14
|
-
# And I should see "Please enter flight details" within "#question"
|
15
|
-
# And I should see "Distance" within "#ui_objects"
|
16
|
-
# And I should see "Flight" within "#ui_objects"
|
17
|
-
# And I should see "flight1" within ".ui-objects-object_reference-drop-down-template"
|
18
|
-
# And I should see "flight2" within ".ui-objects-object_reference-drop-down-template"
|
19
|
-
#
|
20
|
-
# Feature: Edit Answer (for a Flight)
|
21
|
-
# In order to change the the details of the resource for a carbon calculation so calculations are correct
|
22
|
-
# As an application user
|
23
|
-
# I want to be able create a edit a carbon calculated resource (Flight)
|
24
|
-
#
|
25
|
-
# Scenario: View the edit page for the flight resource
|
26
|
-
# Given a flight context exists with a valid question
|
27
|
-
# And a flight exists with the id: "3458234509854309534", distance: "12", :flight => "23432234234"
|
28
|
-
# When go to the edit flight answer page
|
29
|
-
#
|
30
|
-
|