@@ -1,4 +1,4 @@ |
||
| 1 |
-require 'json_with_indifferent_access' |
|
| 1 |
+require 'json_serialized_field' |
|
| 2 | 2 |
require 'assignable_types' |
| 3 | 3 |
require 'markdown_class_attributes' |
| 4 | 4 |
require 'utils' |
@@ -6,6 +6,7 @@ require 'utils' |
||
| 6 | 6 |
class Agent < ActiveRecord::Base |
| 7 | 7 |
include AssignableTypes |
| 8 | 8 |
include MarkdownClassAttributes |
| 9 |
+ include JSONSerializedField |
|
| 9 | 10 |
|
| 10 | 11 |
markdown_class_attributes :description, :event_description |
| 11 | 12 |
|
@@ -16,8 +17,7 @@ class Agent < ActiveRecord::Base |
||
| 16 | 17 |
|
| 17 | 18 |
attr_accessible :options, :memory, :name, :type, :schedule, :source_ids |
| 18 | 19 |
|
| 19 |
- serialize :options, JSONWithIndifferentAccess |
|
| 20 |
- serialize :memory, JSONWithIndifferentAccess |
|
| 20 |
+ json_serialize :options, :memory |
|
| 21 | 21 |
|
| 22 | 22 |
validates_presence_of :name, :user |
| 23 | 23 |
validate :sources_are_owned |
@@ -79,14 +79,6 @@ class Agent < ActiveRecord::Base |
||
| 79 | 79 |
# Implement me in your subclass to test for valid options. |
| 80 | 80 |
end |
| 81 | 81 |
|
| 82 |
- def options=(o) |
|
| 83 |
- self[:options] = ActiveSupport::HashWithIndifferentAccess.new(o) |
|
| 84 |
- end |
|
| 85 |
- |
|
| 86 |
- def memory=(o) |
|
| 87 |
- self[:memory] = ActiveSupport::HashWithIndifferentAccess.new(o) |
|
| 88 |
- end |
|
| 89 |
- |
|
| 90 | 82 |
def event_created_within?(days) |
| 91 | 83 |
last_event_at && last_event_at > days.to_i.days.ago |
| 92 | 84 |
end |
@@ -1,11 +1,13 @@ |
||
| 1 |
-require 'json_with_indifferent_access' |
|
| 1 |
+require 'json_serialized_field' |
|
| 2 | 2 |
|
| 3 | 3 |
class Event < ActiveRecord::Base |
| 4 |
+ include JSONSerializedField |
|
| 5 |
+ |
|
| 4 | 6 |
attr_accessible :lat, :lng, :payload, :user_id, :user, :expires_at |
| 5 | 7 |
|
| 6 | 8 |
acts_as_mappable |
| 7 | 9 |
|
| 8 |
- serialize :payload, JSONWithIndifferentAccess |
|
| 10 |
+ json_serialize :payload |
|
| 9 | 11 |
|
| 10 | 12 |
belongs_to :user |
| 11 | 13 |
belongs_to :agent, :counter_cache => true, :touch => :last_event_at |
@@ -14,10 +16,6 @@ class Event < ActiveRecord::Base |
||
| 14 | 16 |
where("events.created_at > ?", timespan)
|
| 15 | 17 |
} |
| 16 | 18 |
|
| 17 |
- def payload=(o) |
|
| 18 |
- self[:payload] = ActiveSupport::HashWithIndifferentAccess.new(o) |
|
| 19 |
- end |
|
| 20 |
- |
|
| 21 | 19 |
def reemit! |
| 22 | 20 |
agent.create_event :payload => payload, :lat => lat, :lng => lng |
| 23 | 21 |
end |
@@ -0,0 +1,42 @@ |
||
| 1 |
+require 'json_with_indifferent_access' |
|
| 2 |
+ |
|
| 3 |
+module JSONSerializedField |
|
| 4 |
+ extend ActiveSupport::Concern |
|
| 5 |
+ |
|
| 6 |
+ module ClassMethods |
|
| 7 |
+ def json_serialize(*fields) |
|
| 8 |
+ fields.each do |field| |
|
| 9 |
+ class_eval <<-CODE |
|
| 10 |
+ serialize :#{field}, JSONWithIndifferentAccess
|
|
| 11 |
+ |
|
| 12 |
+ validate :#{field}_has_no_errors
|
|
| 13 |
+ |
|
| 14 |
+ def #{field}=(input)
|
|
| 15 |
+ @#{field}_assignment_error = false
|
|
| 16 |
+ case input |
|
| 17 |
+ when String |
|
| 18 |
+ if input.strip.length == 0 |
|
| 19 |
+ self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new
|
|
| 20 |
+ else |
|
| 21 |
+ json = JSON.parse(input) rescue nil |
|
| 22 |
+ if json |
|
| 23 |
+ self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new(json)
|
|
| 24 |
+ else |
|
| 25 |
+ @#{field}_assignment_error = "was assigned invalid JSON"
|
|
| 26 |
+ end |
|
| 27 |
+ end |
|
| 28 |
+ when Hash |
|
| 29 |
+ self[:#{field}] = ActiveSupport::HashWithIndifferentAccess.new(input)
|
|
| 30 |
+ else |
|
| 31 |
+ @#{field}_assignment_error = "cannot be set to an instance of \#{input.class}"
|
|
| 32 |
+ end |
|
| 33 |
+ end |
|
| 34 |
+ |
|
| 35 |
+ def #{field}_has_no_errors
|
|
| 36 |
+ errors.add(:#{field}, @#{field}_assignment_error) if @#{field}_assignment_error
|
|
| 37 |
+ end |
|
| 38 |
+ CODE |
|
| 39 |
+ end |
|
| 40 |
+ end |
|
| 41 |
+ end |
|
| 42 |
+end |
@@ -1,6 +1,6 @@ |
||
| 1 | 1 |
class JSONWithIndifferentAccess |
| 2 | 2 |
def self.load(json) |
| 3 |
- ActiveSupport::HashWithIndifferentAccess.new(JSON.load(json || '{}'))
|
|
| 3 |
+ ActiveSupport::HashWithIndifferentAccess.new(JSON.parse(json || '{}'))
|
|
| 4 | 4 |
end |
| 5 | 5 |
|
| 6 | 6 |
def self.dump(hash) |
@@ -266,6 +266,48 @@ describe Agent do |
||
| 266 | 266 |
agent.memory[:bad].should == 2 |
| 267 | 267 |
end |
| 268 | 268 |
|
| 269 |
+ it "should work when assigned a hash or JSON string" do |
|
| 270 |
+ agent = Agents::SomethingSource.new(:name => "something") |
|
| 271 |
+ agent.memory = {}
|
|
| 272 |
+ agent.memory.should == {}
|
|
| 273 |
+ agent.memory["foo"].should be_nil |
|
| 274 |
+ |
|
| 275 |
+ agent.memory = "" |
|
| 276 |
+ agent.memory["foo"].should be_nil |
|
| 277 |
+ agent.memory.should == {}
|
|
| 278 |
+ |
|
| 279 |
+ agent.memory = '{"hi": "there"}'
|
|
| 280 |
+ agent.memory.should == { "hi" => "there" }
|
|
| 281 |
+ |
|
| 282 |
+ agent.memory = '{invalid}'
|
|
| 283 |
+ agent.memory.should == { "hi" => "there" }
|
|
| 284 |
+ agent.should have(1).errors_on(:memory) |
|
| 285 |
+ |
|
| 286 |
+ agent.memory = "{}"
|
|
| 287 |
+ agent.memory["foo"].should be_nil |
|
| 288 |
+ agent.memory.should == {}
|
|
| 289 |
+ agent.should have(0).errors_on(:memory) |
|
| 290 |
+ |
|
| 291 |
+ agent.options = "{}"
|
|
| 292 |
+ agent.options["foo"].should be_nil |
|
| 293 |
+ agent.options.should == {}
|
|
| 294 |
+ agent.should have(0).errors_on(:options) |
|
| 295 |
+ |
|
| 296 |
+ agent.options = '{"hi": 2}'
|
|
| 297 |
+ agent.options["hi"].should == 2 |
|
| 298 |
+ agent.should have(0).errors_on(:options) |
|
| 299 |
+ |
|
| 300 |
+ agent.options = '{"hi": wut}'
|
|
| 301 |
+ agent.options["hi"].should == 2 |
|
| 302 |
+ agent.should have(1).errors_on(:options) |
|
| 303 |
+ agent.errors_on(:options).should include("was assigned invalid JSON")
|
|
| 304 |
+ |
|
| 305 |
+ agent.options = 5 |
|
| 306 |
+ agent.options["hi"].should == 2 |
|
| 307 |
+ agent.should have(1).errors_on(:options) |
|
| 308 |
+ agent.errors_on(:options).should include("cannot be set to an instance of Fixnum")
|
|
| 309 |
+ end |
|
| 310 |
+ |
|
| 269 | 311 |
it "should not allow agents owned by other people" do |
| 270 | 312 |
agent = Agents::SomethingSource.new(:name => "something") |
| 271 | 313 |
agent.user = users(:bob) |