cogniteev-intercom 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +6 -0
- data/Gemfile +13 -0
- data/MIT-LICENSE +21 -0
- data/README.md +378 -0
- data/Rakefile +21 -0
- data/changes.txt +168 -0
- data/intercom.gemspec +28 -0
- data/lib/data/cacert.pem +3965 -0
- data/lib/ext/sliceable_hash.rb +16 -0
- data/lib/intercom.rb +176 -0
- data/lib/intercom/admin.rb +9 -0
- data/lib/intercom/api_operations/convert.rb +19 -0
- data/lib/intercom/api_operations/count.rb +16 -0
- data/lib/intercom/api_operations/delete.rb +15 -0
- data/lib/intercom/api_operations/find.rb +23 -0
- data/lib/intercom/api_operations/find_all.rb +33 -0
- data/lib/intercom/api_operations/list.rb +17 -0
- data/lib/intercom/api_operations/load.rb +16 -0
- data/lib/intercom/api_operations/save.rb +51 -0
- data/lib/intercom/collection_proxy.rb +71 -0
- data/lib/intercom/company.rb +29 -0
- data/lib/intercom/contact.rb +22 -0
- data/lib/intercom/conversation.rb +17 -0
- data/lib/intercom/count.rb +21 -0
- data/lib/intercom/errors.rb +61 -0
- data/lib/intercom/event.rb +11 -0
- data/lib/intercom/extended_api_operations/reply.rb +16 -0
- data/lib/intercom/extended_api_operations/tags.rb +14 -0
- data/lib/intercom/extended_api_operations/users.rb +17 -0
- data/lib/intercom/generic_handlers/base_handler.rb +22 -0
- data/lib/intercom/generic_handlers/count.rb +59 -0
- data/lib/intercom/generic_handlers/tag.rb +71 -0
- data/lib/intercom/generic_handlers/tag_find_all.rb +47 -0
- data/lib/intercom/lib/dynamic_accessors.rb +59 -0
- data/lib/intercom/lib/dynamic_accessors_on_method_missing.rb +53 -0
- data/lib/intercom/lib/flat_store.rb +31 -0
- data/lib/intercom/lib/typed_json_deserializer.rb +53 -0
- data/lib/intercom/message.rb +9 -0
- data/lib/intercom/note.rb +17 -0
- data/lib/intercom/notification.rb +20 -0
- data/lib/intercom/request.rb +166 -0
- data/lib/intercom/segment.rb +14 -0
- data/lib/intercom/subscription.rb +15 -0
- data/lib/intercom/tag.rb +23 -0
- data/lib/intercom/traits/api_resource.rb +132 -0
- data/lib/intercom/traits/dirty_tracking.rb +33 -0
- data/lib/intercom/traits/generic_handler_binding.rb +29 -0
- data/lib/intercom/traits/incrementable_attributes.rb +12 -0
- data/lib/intercom/user.rb +30 -0
- data/lib/intercom/utils.rb +62 -0
- data/lib/intercom/version.rb +3 -0
- data/spec/spec_helper.rb +308 -0
- data/spec/unit/intercom/admin_spec.rb +9 -0
- data/spec/unit/intercom/collection_proxy_spec.rb +34 -0
- data/spec/unit/intercom/company_spec.rb +23 -0
- data/spec/unit/intercom/contact_spec.rb +25 -0
- data/spec/unit/intercom/event_spec.rb +25 -0
- data/spec/unit/intercom/lib/flat_store_spec.rb +29 -0
- data/spec/unit/intercom/message_spec.rb +21 -0
- data/spec/unit/intercom/note_spec.rb +19 -0
- data/spec/unit/intercom/notification_spec.rb +68 -0
- data/spec/unit/intercom/request_spec.rb +16 -0
- data/spec/unit/intercom/subscription_spec.rb +18 -0
- data/spec/unit/intercom/tag_spec.rb +23 -0
- data/spec/unit/intercom/traits/api_resource_spec.rb +85 -0
- data/spec/unit/intercom/user_spec.rb +230 -0
- data/spec/unit/intercom_spec.rb +90 -0
- metadata +214 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'intercom/api_operations/count'
|
2
|
+
require 'intercom/api_operations/list'
|
3
|
+
require 'intercom/api_operations/find'
|
4
|
+
require 'intercom/api_operations/find_all'
|
5
|
+
require 'intercom/api_operations/save'
|
6
|
+
require 'intercom/api_operations/load'
|
7
|
+
require 'intercom/extended_api_operations/users'
|
8
|
+
require 'intercom/extended_api_operations/tags'
|
9
|
+
require 'intercom/traits/incrementable_attributes'
|
10
|
+
require 'intercom/traits/api_resource'
|
11
|
+
|
12
|
+
module Intercom
|
13
|
+
class Company
|
14
|
+
include ApiOperations::Count
|
15
|
+
include ApiOperations::List
|
16
|
+
include ApiOperations::Find
|
17
|
+
include ApiOperations::FindAll
|
18
|
+
include ApiOperations::Save
|
19
|
+
include ApiOperations::Load
|
20
|
+
include ExtendedApiOperations::Users
|
21
|
+
include ExtendedApiOperations::Tags
|
22
|
+
include Traits::IncrementableAttributes
|
23
|
+
include Traits::ApiResource
|
24
|
+
|
25
|
+
def identity_vars ; [:id, :company_id] ; end
|
26
|
+
def flat_store_attributes ; [:custom_attributes] ; end
|
27
|
+
def update_verb ; 'post' ; end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'intercom/api_operations/count'
|
2
|
+
require 'intercom/api_operations/load'
|
3
|
+
require 'intercom/api_operations/find'
|
4
|
+
require 'intercom/api_operations/find_all'
|
5
|
+
require 'intercom/api_operations/save'
|
6
|
+
require 'intercom/api_operations/convert'
|
7
|
+
require 'intercom/traits/api_resource'
|
8
|
+
|
9
|
+
module Intercom
|
10
|
+
class Contact
|
11
|
+
include ApiOperations::Load
|
12
|
+
include ApiOperations::Find
|
13
|
+
include ApiOperations::FindAll
|
14
|
+
include ApiOperations::Save
|
15
|
+
include ApiOperations::Convert
|
16
|
+
include Traits::ApiResource
|
17
|
+
|
18
|
+
def identity_vars ; [:email, :user_id] ; end
|
19
|
+
def flat_store_attributes ; [:custom_attributes] ; end
|
20
|
+
def update_verb; 'put' ; end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'intercom/extended_api_operations/reply'
|
2
|
+
require 'intercom/api_operations/find_all'
|
3
|
+
require 'intercom/api_operations/find'
|
4
|
+
require 'intercom/api_operations/load'
|
5
|
+
require 'intercom/api_operations/save'
|
6
|
+
require 'intercom/traits/api_resource'
|
7
|
+
|
8
|
+
module Intercom
|
9
|
+
class Conversation
|
10
|
+
include ExtendedApiOperations::Reply
|
11
|
+
include ApiOperations::FindAll
|
12
|
+
include ApiOperations::Find
|
13
|
+
include ApiOperations::Load
|
14
|
+
include ApiOperations::Save
|
15
|
+
include Traits::ApiResource
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'intercom/traits/api_resource'
|
2
|
+
require 'intercom/api_operations/find'
|
3
|
+
require 'intercom/traits/generic_handler_binding'
|
4
|
+
require 'intercom/generic_handlers/count'
|
5
|
+
|
6
|
+
module Intercom
|
7
|
+
class Count
|
8
|
+
include ApiOperations::Find
|
9
|
+
include Traits::ApiResource
|
10
|
+
include Traits::GenericHandlerBinding
|
11
|
+
include GenericHandlers::Count
|
12
|
+
|
13
|
+
def self.fetch_for_app
|
14
|
+
Intercom::Count.find({})
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.fetch_broken_down_count(entity_to_count, count_context)
|
18
|
+
Intercom::Count.find(:type => entity_to_count, :count => count_context)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Intercom
|
2
|
+
|
3
|
+
# Base class exception from which all public Intercom exceptions will be derived
|
4
|
+
class IntercomError < StandardError
|
5
|
+
attr_reader :http_code, :application_error_code
|
6
|
+
def initialize(message, http_code = nil, error_code = application_error_code)
|
7
|
+
@http_code = http_code
|
8
|
+
@application_error_code = error_code
|
9
|
+
super(message)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when the credentials you provide don't match a valid account on Intercom.
|
14
|
+
# Check that you have set <b>Intercom.app_id=</b> and <b>Intercom.app_api_key=</b> correctly.
|
15
|
+
class AuthenticationError < IntercomError; end
|
16
|
+
|
17
|
+
# Raised when something does wrong on within the Intercom API service.
|
18
|
+
class ServerError < IntercomError; end
|
19
|
+
|
20
|
+
# Raised when we have bad gateway errors.
|
21
|
+
class BadGatewayError < IntercomError; end
|
22
|
+
|
23
|
+
# Raised when we experience a socket read timeout
|
24
|
+
class ServiceUnavailableError < IntercomError; end
|
25
|
+
|
26
|
+
# Raised when we experience socket connect timeout
|
27
|
+
class ServiceConnectionError < IntercomError; end
|
28
|
+
|
29
|
+
# Raised when requesting resources on behalf of a user that doesn't exist in your application on Intercom.
|
30
|
+
class ResourceNotFound < IntercomError; end
|
31
|
+
|
32
|
+
# Raised when the request has a bad syntax
|
33
|
+
class BadRequestError < IntercomError; end
|
34
|
+
|
35
|
+
# Raised when you have exceed the API rate limit
|
36
|
+
class RateLimitExceeded < IntercomError; end
|
37
|
+
|
38
|
+
# Raised when the request throws an error not accounted for
|
39
|
+
class UnexpectedError < IntercomError; end
|
40
|
+
|
41
|
+
# Raised when multiple users match the query (typically duplicate email addresses)
|
42
|
+
class MultipleMatchingUsersError < IntercomError; end
|
43
|
+
|
44
|
+
# Raised when you try to call a non-setter method that does not exist on an object
|
45
|
+
class Intercom::AttributeNotSetError < IntercomError ; end
|
46
|
+
|
47
|
+
# Raised when unexpected nil returned from server
|
48
|
+
class Intercom::HttpError < IntercomError ; end
|
49
|
+
|
50
|
+
#
|
51
|
+
# Non-public errors (internal to the gem)
|
52
|
+
#
|
53
|
+
|
54
|
+
# Base class exception from which all public Intercom exceptions will be derived
|
55
|
+
class IntercomInternalError < StandardError; end
|
56
|
+
|
57
|
+
# Raised when we attempt to handle a method missing but are unsuccessful
|
58
|
+
class Intercom::NoMethodMissingHandler < IntercomInternalError; end
|
59
|
+
|
60
|
+
class Intercom::DeserializationError < IntercomInternalError; end
|
61
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'intercom/api_operations/save'
|
2
|
+
require 'intercom/api_operations/find_all'
|
3
|
+
require 'intercom/traits/api_resource'
|
4
|
+
|
5
|
+
module Intercom
|
6
|
+
class Event
|
7
|
+
include ApiOperations::FindAll
|
8
|
+
include ApiOperations::Save
|
9
|
+
include Traits::ApiResource
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'intercom/traits/api_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module ExtendedApiOperations
|
5
|
+
module Reply
|
6
|
+
|
7
|
+
def reply(reply_data)
|
8
|
+
collection_name = Utils.resource_class_to_collection_name(self.class)
|
9
|
+
# TODO: For server, we should not need to merge in :conversation_id here (already in the URL)
|
10
|
+
response = Intercom.post("/#{collection_name}/#{id}/reply", reply_data.merge(:conversation_id => id))
|
11
|
+
from_response(response)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'intercom/traits/api_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module ExtendedApiOperations
|
5
|
+
module Tags
|
6
|
+
|
7
|
+
def tags
|
8
|
+
collection_name = Utils.resource_class_to_collection_name(self.class)
|
9
|
+
self.id ? Intercom::Tag.send("find_all_for_#{collection_name}", :id => id) : []
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'intercom/traits/api_resource'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module ExtendedApiOperations
|
5
|
+
module Users
|
6
|
+
|
7
|
+
def users
|
8
|
+
collection_name = Utils.resource_class_to_collection_name(self.class)
|
9
|
+
finder_details = {}
|
10
|
+
finder_details[:url] = "/#{collection_name}/#{id}/users"
|
11
|
+
finder_details[:params] = {}
|
12
|
+
CollectionProxy.new("users", finder_details)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Intercom
|
2
|
+
module GenericHandlers
|
3
|
+
class BaseHandler
|
4
|
+
attr_reader :method_sym, :arguments, :entity
|
5
|
+
|
6
|
+
def initialize(method_sym, arguments, entity)
|
7
|
+
@method_sym = method_sym
|
8
|
+
@arguments = arguments
|
9
|
+
@entity = entity
|
10
|
+
end
|
11
|
+
|
12
|
+
def method_string
|
13
|
+
method_sym.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def raise_no_method_missing_handler
|
17
|
+
raise Intercom::NoMethodMissingHandler, "Could not handle '#{method_string}'"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'intercom/generic_handlers/base_handler'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module GenericHandlers
|
5
|
+
module Count
|
6
|
+
module ClassMethods
|
7
|
+
def generic_count(method_sym, *arguments, &block)
|
8
|
+
|
9
|
+
handler_class = Class.new(GenericHandlers::BaseHandler) do
|
10
|
+
def handle
|
11
|
+
match = method_string.match(GenericHandlers::Count.count_breakdown_matcher)
|
12
|
+
if match && match[1] && match[2] && match[3].nil?
|
13
|
+
do_broken_down_count(match[1], match[2])
|
14
|
+
elsif method_string.end_with? '_count'
|
15
|
+
return do_count
|
16
|
+
else
|
17
|
+
raise_no_method_missing_handler
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def do_count
|
24
|
+
entity.fetch_for_app.send(appwide_entity_to_count)['count']
|
25
|
+
rescue Intercom::AttributeNotSetError
|
26
|
+
# Indicates this this kind of counting is not supported
|
27
|
+
raise_no_method_missing_handler
|
28
|
+
end
|
29
|
+
|
30
|
+
def do_broken_down_count(entity_to_count, count_context)
|
31
|
+
result = entity.fetch_broken_down_count(entity_to_count, count_context)
|
32
|
+
result.send(entity_to_count)[count_context]
|
33
|
+
rescue Intercom::BadRequestError => ex
|
34
|
+
# Indicates this this kind of counting is not supported
|
35
|
+
ex.application_error_code == 'parameter_invalid' ? raise_no_method_missing_handler : raise
|
36
|
+
end
|
37
|
+
|
38
|
+
def appwide_entity_to_count; method_string.gsub(/_count$/, ''); end
|
39
|
+
end
|
40
|
+
|
41
|
+
handler_class.new(method_sym, arguments, self).handle
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.count_breakdown_matcher
|
47
|
+
/([[:alnum:]]+)_counts_for_each_([[:alnum:]]+)/
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.handles_method?(method_sym)
|
51
|
+
method_sym.to_s.end_with? '_count' or method_sym.to_s.match(count_breakdown_matcher)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.included(base)
|
55
|
+
base.extend(ClassMethods)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'intercom/generic_handlers/base_handler'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module GenericHandlers
|
5
|
+
module Tag
|
6
|
+
module ClassMethods
|
7
|
+
def generic_tag(method_sym, *arguments, &block)
|
8
|
+
|
9
|
+
handler_class = Class.new(GenericHandlers::BaseHandler) do
|
10
|
+
def handle
|
11
|
+
if method_string.start_with? 'tag_'
|
12
|
+
return do_tagging
|
13
|
+
elsif method_string.start_with? 'untag_'
|
14
|
+
return do_untagging
|
15
|
+
else
|
16
|
+
raise_no_method_missing_handler
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def do_tagging
|
23
|
+
entity.create(:name => arguments[0], tagging_context.to_sym => tag_object_list(arguments))
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_untagging
|
27
|
+
current_tag = find_tag(arguments[0])
|
28
|
+
return untag_via_save(current_tag) if current_tag
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_tag(name_arg)
|
32
|
+
Intercom::Tag.find(:name => name_arg)
|
33
|
+
rescue Intercom::ResourceNotFound
|
34
|
+
return nil # Ignore if tag has since been deleted
|
35
|
+
end
|
36
|
+
|
37
|
+
def untag_via_save(current_tag)
|
38
|
+
current_tag.name = arguments[0]
|
39
|
+
current_tag.send("#{untagging_context}=", untag_object_list(arguments))
|
40
|
+
current_tag.save
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_object_list(args)
|
44
|
+
args[1].map { |id| { :id => id } }
|
45
|
+
end
|
46
|
+
|
47
|
+
def untag_object_list(args)
|
48
|
+
to_tag = tag_object_list(args)
|
49
|
+
to_tag.map { |tag_object| tag_object[:untag] = true }
|
50
|
+
to_tag
|
51
|
+
end
|
52
|
+
|
53
|
+
def tagging_context; method_string.gsub(/^tag_/, ''); end
|
54
|
+
def untagging_context; method_string.gsub(/^untag_/, ''); end
|
55
|
+
end
|
56
|
+
|
57
|
+
handler_class.new(method_sym, arguments, self).handle
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.handles_method?(method_sym)
|
63
|
+
method_sym.to_s.start_with?('tag_') || method_sym.to_s.start_with?('untag_')
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.included(base)
|
67
|
+
base.extend(ClassMethods)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'intercom/generic_handlers/base_handler'
|
2
|
+
|
3
|
+
module Intercom
|
4
|
+
module GenericHandlers
|
5
|
+
module TagFindAll
|
6
|
+
module ClassMethods
|
7
|
+
def generic_tag_find_all(method_sym, *arguments, &block)
|
8
|
+
|
9
|
+
handler_class = Class.new(GenericHandlers::BaseHandler) do
|
10
|
+
def handle
|
11
|
+
if method_string.start_with? 'find_all_for_'
|
12
|
+
return do_tag_find_all
|
13
|
+
else
|
14
|
+
raise_no_method_missing_handler
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def do_tag_find_all
|
21
|
+
Intercom::Tag.find_all(cleaned_arguments.merge(:taggable_type => Utils.singularize(context)))
|
22
|
+
end
|
23
|
+
|
24
|
+
def cleaned_arguments
|
25
|
+
cleaned_args = arguments[0]
|
26
|
+
cleaned_args[:taggable_id] = cleaned_args.delete(:id) if cleaned_args.has_key?(:id)
|
27
|
+
cleaned_args
|
28
|
+
end
|
29
|
+
|
30
|
+
def context; method_string.gsub(/^find_all_for_/, ''); end
|
31
|
+
end
|
32
|
+
|
33
|
+
handler_class.new(method_sym, arguments, self).handle
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.handles_method?(method_sym)
|
39
|
+
method_sym.to_s.start_with? 'find_all_for_'
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.included(base)
|
43
|
+
base.extend(ClassMethods)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Intercom
|
2
|
+
module Lib
|
3
|
+
module DynamicAccessors
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def define_accessors(attribute, value, object)
|
8
|
+
klass = object.class
|
9
|
+
if attribute.to_s.end_with?('_at') && attribute.to_s != 'update_last_request_at'
|
10
|
+
define_date_based_accessors(attribute, value, klass)
|
11
|
+
elsif object.flat_store_attribute?(attribute)
|
12
|
+
define_flat_store_based_accessors(attribute, value, klass)
|
13
|
+
else
|
14
|
+
define_standard_accessors(attribute, value, klass)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def define_flat_store_based_accessors(attribute, value, klass)
|
21
|
+
klass.class_eval %Q"
|
22
|
+
def #{attribute}=(value)
|
23
|
+
mark_field_as_changed!(:#{attribute})
|
24
|
+
@#{attribute} = Intercom::Lib::FlatStore.new(value)
|
25
|
+
end
|
26
|
+
def #{attribute}
|
27
|
+
@#{attribute}
|
28
|
+
end
|
29
|
+
"
|
30
|
+
end
|
31
|
+
|
32
|
+
def define_date_based_accessors(attribute, value, klass)
|
33
|
+
klass.class_eval %Q"
|
34
|
+
def #{attribute}=(value)
|
35
|
+
mark_field_as_changed!(:#{attribute})
|
36
|
+
@#{attribute} = value.nil? ? nil : value.to_i
|
37
|
+
end
|
38
|
+
def #{attribute}
|
39
|
+
@#{attribute}.nil? ? nil : Time.at(@#{attribute})
|
40
|
+
end
|
41
|
+
"
|
42
|
+
end
|
43
|
+
|
44
|
+
def define_standard_accessors(attribute, value, klass)
|
45
|
+
klass.class_eval %Q"
|
46
|
+
def #{attribute}=(value)
|
47
|
+
mark_field_as_changed!(:#{attribute})
|
48
|
+
@#{attribute} = value
|
49
|
+
end
|
50
|
+
def #{attribute}
|
51
|
+
@#{attribute}
|
52
|
+
end
|
53
|
+
"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|