Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Introduce Response#value, an abstraction over Surveyor's value storage. #310

Closed
wants to merge 1 commit into from

3 participants

@yipdw

This commit also makes some other simplifications:

  1. The value key in the JSON representation of a response should always
    be present, as a response always has a value. Previously, this was
    not the case.

  2. Answer#response_class is a string, not a symbol. ActsAsResponse#as
    expects symbols, but is usually invoked with a response class as its
    first argument. This commit resolves the string/symbol inconsistency
    for these methods and eliminates some unnecessary interning.
    (There's a #to_s in the case condition for backwards
    compatibility; at some point, that ought to be removed.)

  3. "return case" in ActsAsResponse#as is redundant.


NB: there's no Response#value= here because the corresponding writer, IMO, only makes sense in NCS Core or other applications setting values from JSON representations of Responses. If, however, that functionality is desired in Surveyor, I can add it to this pull request.

David Yip Introduce Response#value, an abstraction over Surveyor's value storage.
This commit also makes some other simplifications:

1. The value key in the JSON representation of a response should always
   be present, as a response always has a value.  Previously, this was
   not the case.

2. Answer#response_class is a string, not a symbol.  ActsAsResponse#as
   expects symbols, but is usually invoked with a response class as its
   first argument.  This commit resolves the string/symbol inconsistency
   for these methods and eliminates some unnecessary interning.
   (There's a #to_s in the case condition for backwards
   compatibility; at some point, that ought to be removed.)

3. "return case" in ActsAsResponse#as is redundant.
d7eaafb
@yoon
Owner
  1. A response doesn't always have a value - only if Answer#response_class is string, text, integer, float, date, datetime, or time.

  2. In the DSL Question#pick and Answer#response_class are allowed to be symbols for ease of writing. We should make the behavior of the two consistent - either overridding the pick= as is done in the Question class, or another solution in the parser.

@yipdw
  1. A Response still has a value; it's just nil. (And it's fine if it's nil for answers -- the proposed Response#value returns nil in that case.)
  2. I agree that the #to_s should not exist. However, I still strongly recommend string usage:

  • response_class is stored as a string;
  • to the best of my knowledge, no major Ruby implementation now or in the near future will subject unused symbols to garbage collection; and
  • the number of possibilities for Answer#response_class are unbounded.

IMO, if the sole justification for symbols is to save a character, then the parser should take care of converting those symbols to strings.

@jdzak
Owner

Having this would make it much easier to get a response's value. Putting it in surveyor's codebase makes sense because it's probably something most people have written in their application to get a response value. The code looks fine.

+1 to pull

@yoon yoon closed this
@yoon
Owner

we jave built consensus in #311 around having Response#value replace the other _value attributes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 25, 2012
  1. Introduce Response#value, an abstraction over Surveyor's value storage.

    David Yip authored
    This commit also makes some other simplifications:
    
    1. The value key in the JSON representation of a response should always
       be present, as a response always has a value.  Previously, this was
       not the case.
    
    2. Answer#response_class is a string, not a symbol.  ActsAsResponse#as
       expects symbols, but is usually invoked with a response class as its
       first argument.  This commit resolves the string/symbol inconsistency
       for these methods and eliminates some unnecessary interning.
       (There's a #to_s in the case condition for backwards
       compatibility; at some point, that ought to be removed.)
    
    3. "return case" in ActsAsResponse#as is redundant.
This page is out of date. Refresh to see the latest.
View
4 app/views/surveyor/show.json.rabl
@@ -10,5 +10,5 @@ child :responses do
attribute :updated_at => :modified_at
node(:answer_id){|r| r.answer.api_id }
node(:question_id){|r| r.question.api_id }
- node(:value, :if => lambda{|r| r.answer.response_class != "answer"}){|r| r.as(r.answer.response_class) }
-end
+ node(:value){|r| r.value }
+end
View
5 features/export_to_json.feature
@@ -83,7 +83,8 @@ Feature: Survey export
"answer_id":"*",
"question_id":"*",
"created_at":"*",
- "modified_at":"*"
+ "modified_at":"*",
+ "value":null
},{
"uuid":"*",
"answer_id":"*",
@@ -93,4 +94,4 @@ Feature: Survey export
"value":"orange"
}]
}
- """
+ """
View
22 lib/surveyor/acts_as_response.rb
@@ -1,17 +1,23 @@
module Surveyor
module ActsAsResponse
- # Returns the response as a particular response_class type
- def as(type_symbol)
- return case type_symbol.to_sym
- when :string, :text, :integer, :float, :datetime
- self.send("#{type_symbol}_value".to_sym)
- when :date
+ # Returns the response as a particular type
+ def as(response_class)
+ case response_class.to_s
+ when "string", "text", "integer", "float", "datetime"
+ self.send("#{response_class}_value")
+ when "date"
self.datetime_value.nil? ? nil : self.datetime_value.to_date
- when :time
+ when "time"
self.datetime_value.nil? ? nil : self.datetime_value.to_time
else # :answer_id
self.answer_id
end
end
+
+ def value
+ a = answer
+
+ as(a.response_class) unless a.response_class == 'answer'
+ end
end
-end
+end
View
46 spec/models/response_spec.rb
@@ -89,6 +89,52 @@
resp.as(:stuff).should == nil
end
end
+
+ describe '#value' do
+ let(:answer) { @response.answer }
+
+ shared_examples_for 'a value coercer' do |field, value, as|
+ it "coerces its value to #{as}" do
+ @response.send("#{field}=", value)
+
+ @response.value.should == @response.as(as)
+ end
+ end
+
+ describe 'with response class of string' do
+ before { answer.response_class = 'string' }
+
+ it_should_behave_like 'a value coercer', 'string_value', 'blah', :string
+ end
+
+ describe 'with integers' do
+ before { answer.response_class = 'integer' }
+
+ it_should_behave_like 'a value coercer', 'integer_value', 1001, :integer
+ end
+
+ describe 'with floats' do
+ before { answer.response_class = 'float' }
+
+ it_should_behave_like 'a value coercer', 'float_value', 3.14, :float
+ end
+
+ describe 'with answers' do
+ before { answer.response_class = 'answer' }
+
+ it 'returns nil' do
+ @response.value.should be_nil
+ end
+ end
+
+ describe 'with an unspecified response class' do
+ before { answer.response_class = nil }
+
+ it 'returns the answer ID' do
+ @response.value.should == @response.answer_id
+ end
+ end
+ end
end
describe Response, "applicable_attributes" do
Something went wrong with that request. Please try again.