intercom-rails 0.2.8 → 0.2.9
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.
- data/README.mdown +1 -1
- data/lib/intercom-rails/auto_include_filter.rb +42 -35
- data/lib/intercom-rails/config.rb +56 -52
- data/lib/intercom-rails/proxy.rb +66 -4
- data/lib/intercom-rails/proxy/company.rb +8 -9
- data/lib/intercom-rails/proxy/user.rb +8 -10
- data/lib/intercom-rails/railtie.rb +2 -1
- data/lib/intercom-rails/version.rb +1 -1
- data/lib/rails/generators/intercom/config/intercom.rb.erb +13 -0
- data/test/action_controller_test_setup.rb +2 -1
- data/test/intercom-rails/auto_include_filter_test.rb +11 -0
- data/test/intercom-rails/config_test.rb +9 -0
- metadata +8 -2
data/README.mdown
CHANGED
@@ -28,7 +28,7 @@ To make installing Intercom as easy as possible, where possible a `<script>` tag
|
|
28
28
|
To disable automatic insertion for a particular controller or action you can:
|
29
29
|
|
30
30
|
```ruby
|
31
|
-
skip_after_filter
|
31
|
+
skip_after_filter :intercom_rails_auto_include
|
32
32
|
```
|
33
33
|
|
34
34
|
### Troubleshooting
|
@@ -1,52 +1,59 @@
|
|
1
1
|
module IntercomRails
|
2
2
|
|
3
|
-
|
3
|
+
module AutoInclude
|
4
|
+
def intercom_rails_auto_include
|
5
|
+
Filter.filter(self)
|
6
|
+
end
|
4
7
|
|
5
|
-
|
8
|
+
class Filter
|
6
9
|
|
7
|
-
|
8
|
-
auto_include_filter = new(controller)
|
9
|
-
return unless auto_include_filter.include_javascript?
|
10
|
+
CLOSING_BODY_TAG = %r{</body>}
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def self.filter(controller)
|
13
|
+
auto_include_filter = new(controller)
|
14
|
+
return unless auto_include_filter.include_javascript?
|
13
15
|
|
14
|
-
|
16
|
+
auto_include_filter.include_javascript!
|
17
|
+
end
|
15
18
|
|
16
|
-
|
17
|
-
@controller = kontroller
|
18
|
-
end
|
19
|
+
attr_reader :controller
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
def initialize(kontroller)
|
22
|
+
@controller = kontroller
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
response_has_closing_body_tag? &&
|
28
|
-
intercom_script_tag.valid?
|
29
|
-
end
|
25
|
+
def include_javascript!
|
26
|
+
response.body = response.body.gsub(CLOSING_BODY_TAG, intercom_script_tag.output + '\\0')
|
27
|
+
end
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
def include_javascript?
|
30
|
+
!intercom_script_tag_called_manually? &&
|
31
|
+
html_content_type? &&
|
32
|
+
response_has_closing_body_tag? &&
|
33
|
+
intercom_script_tag.valid?
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
response
|
38
|
-
|
36
|
+
private
|
37
|
+
def response
|
38
|
+
controller.response
|
39
|
+
end
|
39
40
|
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
def html_content_type?
|
42
|
+
response.content_type == 'text/html'
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
def response_has_closing_body_tag?
|
46
|
+
!!(response.body[CLOSING_BODY_TAG])
|
47
|
+
end
|
48
|
+
|
49
|
+
def intercom_script_tag_called_manually?
|
50
|
+
controller.instance_variable_get(SCRIPT_TAG_HELPER_CALLED_INSTANCE_VARIABLE)
|
51
|
+
end
|
52
|
+
|
53
|
+
def intercom_script_tag
|
54
|
+
@script_tag ||= ScriptTag.new(:find_current_user_details => true, :find_current_company_details => true, :controller => controller)
|
55
|
+
end
|
47
56
|
|
48
|
-
def intercom_script_tag
|
49
|
-
@script_tag ||= ScriptTag.new(:find_current_user_details => true, :find_current_company_details => true, :controller => controller)
|
50
57
|
end
|
51
58
|
|
52
59
|
end
|
@@ -1,39 +1,64 @@
|
|
1
|
-
|
1
|
+
require 'active_support/inflector'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
3
|
+
module IntercomRails
|
4
|
+
|
5
|
+
class ConfigSingleton
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def self.config_accessor(*args, &block)
|
8
|
+
config_reader(*args)
|
9
|
+
config_writer(*args, &block)
|
11
10
|
end
|
12
|
-
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
def self.config_reader(name)
|
13
|
+
self.send(:define_singleton_method, name) do
|
14
|
+
instance_variable_get("@#{name}")
|
15
|
+
end
|
18
16
|
end
|
19
|
-
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def self.config_writer(name, &block)
|
19
|
+
self.send(:define_singleton_method, "#{name}=") do |value|
|
20
|
+
block.call(value) if block && (block.arity <= 1)
|
21
|
+
|
22
|
+
if block && (block.arity > 1)
|
23
|
+
field_name = underscored_class_name ? "#{underscored_class_name}.#{name}" : name
|
24
|
+
block.call(value, field_name)
|
25
|
+
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
+
instance_variable_set("@#{name}", value)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.config_group(name, &block)
|
32
|
+
camelized_name = name.to_s.classify
|
33
|
+
group = self.const_set(camelized_name, Class.new(self))
|
34
|
+
|
35
|
+
self.send(:define_singleton_method, name) do
|
36
|
+
group
|
37
|
+
end
|
38
|
+
|
39
|
+
group.send(:instance_variable_set, :@underscored_class_name, name)
|
40
|
+
group.instance_eval(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def self.underscored_class_name
|
45
|
+
@underscored_class_name
|
27
46
|
end
|
28
47
|
|
29
|
-
group.instance_eval(&block)
|
30
48
|
end
|
31
49
|
|
32
|
-
|
50
|
+
class Config < ConfigSingleton
|
33
51
|
|
34
|
-
|
52
|
+
CUSTOM_DATA_VALIDATOR = Proc.new do |custom_data, field_name|
|
53
|
+
raise ArgumentError, "#{field_name} custom_data should be a hash" unless custom_data.kind_of?(Hash)
|
54
|
+
unless custom_data.values.all? { |value| value.kind_of?(Proc) || value.kind_of?(Symbol) }
|
55
|
+
raise ArgumentError, "all custom_data attributes should be either a Proc or a symbol"
|
56
|
+
end
|
57
|
+
end
|
35
58
|
|
36
|
-
|
59
|
+
IS_PROC_VALIDATOR = Proc.new do |value, field_name|
|
60
|
+
raise ArgumentError, "#{field_name} is not a proc" unless value.kind_of?(Proc)
|
61
|
+
end
|
37
62
|
|
38
63
|
def self.reset!
|
39
64
|
to_reset = self.constants.map {|c| const_get c}
|
@@ -52,42 +77,21 @@ module IntercomRails
|
|
52
77
|
config_accessor :library_url
|
53
78
|
|
54
79
|
config_group :user do
|
55
|
-
config_accessor :current
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
config_accessor :model do |value|
|
60
|
-
raise ArgumentError, "user.model should be a Proc" unless value.kind_of?(Proc)
|
61
|
-
end
|
62
|
-
|
63
|
-
config_accessor :company_association do |value|
|
64
|
-
raise ArgumentError, "company_association should be a Proc" unless value.kind_of?(Proc)
|
65
|
-
end
|
66
|
-
|
67
|
-
config_accessor :custom_data do |value|
|
68
|
-
raise ArgumentError, "user.custom_data should be a hash" unless value.kind_of?(Hash)
|
69
|
-
unless value.reject { |_,v| v.kind_of?(Proc) || v.kind_of?(Symbol) }.count.zero?
|
70
|
-
raise ArgumentError, "all custom_data attributes should be either a Proc or a symbol"
|
71
|
-
end
|
72
|
-
end
|
80
|
+
config_accessor :current, &IS_PROC_VALIDATOR
|
81
|
+
config_accessor :model, &IS_PROC_VALIDATOR
|
82
|
+
config_accessor :company_association, &IS_PROC_VALIDATOR
|
83
|
+
config_accessor :custom_data, &CUSTOM_DATA_VALIDATOR
|
73
84
|
end
|
74
85
|
|
75
86
|
config_group :company do
|
76
|
-
config_accessor :current
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
config_accessor :custom_data do |value|
|
81
|
-
raise ArgumentError, "company.custom_data should be a hash" unless value.kind_of?(Hash)
|
82
|
-
unless value.reject { |_,v| v.kind_of?(Proc) || v.kind_of?(Symbol) }.count.zero?
|
83
|
-
raise ArgumentError, "all custom_data attributes should be either a Proc or a symbol"
|
84
|
-
end
|
85
|
-
end
|
87
|
+
config_accessor :current, &IS_PROC_VALIDATOR
|
88
|
+
config_accessor :plan, &IS_PROC_VALIDATOR
|
89
|
+
config_accessor :monthly_spend, &IS_PROC_VALIDATOR
|
90
|
+
config_accessor :custom_data, &CUSTOM_DATA_VALIDATOR
|
86
91
|
end
|
87
92
|
|
88
93
|
config_group :inbox do
|
89
94
|
config_accessor :counter
|
90
|
-
|
91
95
|
config_accessor :style do |value|
|
92
96
|
raise ArgumentError, "inbox.style must be one of :default or :custom" unless [:default, :custom].include?(value)
|
93
97
|
end
|
data/lib/intercom-rails/proxy.rb
CHANGED
@@ -25,16 +25,26 @@ module IntercomRails
|
|
25
25
|
standard_data.merge custom_data
|
26
26
|
end
|
27
27
|
|
28
|
+
def standard_data
|
29
|
+
proxied_values = self.class.standard_data_proxy_attributes.reduce({}) do |hsh, attribute_name|
|
30
|
+
hsh[attribute_name] = send(attribute_name) if send(attribute_name).present?
|
31
|
+
hsh
|
32
|
+
end
|
33
|
+
|
34
|
+
configured_values = self.class.standard_data_config_attributes.reduce({}) do |hsh, attribute_name|
|
35
|
+
next(hsh) unless config_variable_set?(attribute_name)
|
36
|
+
hsh.merge(attribute_name => send(attribute_name))
|
37
|
+
end
|
38
|
+
|
39
|
+
proxied_values.merge(configured_values)
|
40
|
+
end
|
41
|
+
|
28
42
|
def custom_data
|
29
43
|
custom_data_from_config.merge custom_data_from_request
|
30
44
|
end
|
31
45
|
|
32
46
|
protected
|
33
47
|
|
34
|
-
def attribute_present?(attribute)
|
35
|
-
proxied_object.respond_to?(attribute) && proxied_object.send(attribute).present?
|
36
|
-
end
|
37
|
-
|
38
48
|
def self.type
|
39
49
|
self.class_string.downcase.to_sym
|
40
50
|
end
|
@@ -51,6 +61,58 @@ module IntercomRails
|
|
51
61
|
self.class.config(type_override)
|
52
62
|
end
|
53
63
|
|
64
|
+
def config_variable_set?(variable_name)
|
65
|
+
config.send(variable_name).present?
|
66
|
+
end
|
67
|
+
|
68
|
+
def identity_present?
|
69
|
+
self.class.identity_attributes.any? { |attribute_name| proxied_object.respond_to?(attribute_name) && proxied_object.send(attribute_name).present? }
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.proxy_delegator(attribute_name, options = {})
|
73
|
+
instance_variable_name = :"@_proxy_#{attribute_name}_delegated_value"
|
74
|
+
standard_data_proxy_attributes << attribute_name
|
75
|
+
identity_attributes << attribute_name if options[:identity]
|
76
|
+
|
77
|
+
send(:define_method, attribute_name) do
|
78
|
+
return nil unless proxied_object.respond_to?(attribute_name)
|
79
|
+
|
80
|
+
current_value = instance_variable_get(instance_variable_name)
|
81
|
+
return current_value if current_value
|
82
|
+
|
83
|
+
value = proxied_object.send(attribute_name)
|
84
|
+
instance_variable_set(instance_variable_name, value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.config_delegator(attribute_name)
|
89
|
+
instance_variable_name = :"@_config_#{attribute_name}_delegated_value"
|
90
|
+
standard_data_config_attributes << attribute_name
|
91
|
+
|
92
|
+
send(:define_method, attribute_name) do
|
93
|
+
return nil unless config.send(attribute_name).present?
|
94
|
+
|
95
|
+
current_value = instance_variable_get(instance_variable_name)
|
96
|
+
return current_value if current_value
|
97
|
+
|
98
|
+
getter = config.send(attribute_name)
|
99
|
+
value = getter.call(proxied_object)
|
100
|
+
instance_variable_set(instance_variable_name, value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.identity_attributes
|
105
|
+
@_identity_attributes ||= []
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.standard_data_proxy_attributes
|
109
|
+
@_standard_data_proxy_attributes ||= []
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.standard_data_config_attributes
|
113
|
+
@_standard_data_config_attributes ||= []
|
114
|
+
end
|
115
|
+
|
54
116
|
private
|
55
117
|
|
56
118
|
def custom_data_from_request
|
@@ -4,6 +4,13 @@ module IntercomRails
|
|
4
4
|
|
5
5
|
class Company < Proxy
|
6
6
|
|
7
|
+
proxy_delegator :id, :identity => true
|
8
|
+
proxy_delegator :name
|
9
|
+
proxy_delegator :created_at
|
10
|
+
|
11
|
+
config_delegator :plan
|
12
|
+
config_delegator :monthly_spend
|
13
|
+
|
7
14
|
def self.companies_for_user(user)
|
8
15
|
return unless config(:user).company_association.present?
|
9
16
|
companies = config(:user).company_association.call(user.user)
|
@@ -25,15 +32,7 @@ module IntercomRails
|
|
25
32
|
end
|
26
33
|
|
27
34
|
def valid?
|
28
|
-
company.present? &&
|
29
|
-
end
|
30
|
-
|
31
|
-
def standard_data
|
32
|
-
hsh = {}
|
33
|
-
hsh[:id] = company.id
|
34
|
-
hsh[:name] = company.name if attribute_present?(:name)
|
35
|
-
hsh[:created_at] = company.created_at.to_i if attribute_present?(:created_at)
|
36
|
-
hsh
|
35
|
+
company.present? && identity_present?
|
37
36
|
end
|
38
37
|
|
39
38
|
end
|
@@ -4,6 +4,11 @@ module IntercomRails
|
|
4
4
|
|
5
5
|
class User < Proxy
|
6
6
|
|
7
|
+
proxy_delegator :id, :identity => true
|
8
|
+
proxy_delegator :email, :identity => true
|
9
|
+
proxy_delegator :name
|
10
|
+
proxy_delegator :created_at
|
11
|
+
|
7
12
|
PREDEFINED_POTENTIAL_USER_OBJECTS = [
|
8
13
|
Proc.new { current_user },
|
9
14
|
Proc.new { @user }
|
@@ -31,21 +36,14 @@ module IntercomRails
|
|
31
36
|
end
|
32
37
|
|
33
38
|
def standard_data
|
34
|
-
|
35
|
-
|
36
|
-
hsh[:user_id] = user.id if attribute_present?(:id)
|
37
|
-
[:email, :name, :created_at].each do |attribute|
|
38
|
-
hsh[attribute] = user.send(attribute) if attribute_present?(attribute)
|
39
|
+
super.tap do |hsh|
|
40
|
+
hsh[:user_id] = hsh.delete(:id) if hsh.has_key?(:id)
|
39
41
|
end
|
40
|
-
|
41
|
-
hsh
|
42
42
|
end
|
43
43
|
|
44
44
|
def valid?
|
45
45
|
return false if user.blank? || user.respond_to?(:new_record?) && user.new_record?
|
46
|
-
|
47
|
-
return true if user.respond_to?(:email) && user.email.present?
|
48
|
-
false
|
46
|
+
identity_present?
|
49
47
|
end
|
50
48
|
|
51
49
|
end
|
@@ -3,7 +3,8 @@ module IntercomRails
|
|
3
3
|
initializer "intercom-rails" do |app|
|
4
4
|
ActionView::Base.send :include, ScriptTagHelper
|
5
5
|
ActionController::Base.send :include, CustomDataHelper
|
6
|
-
ActionController::Base.send :
|
6
|
+
ActionController::Base.send :include, AutoInclude
|
7
|
+
ActionController::Base.after_filter, :intercom_rails_auto_include
|
7
8
|
end
|
8
9
|
|
9
10
|
rake_tasks do
|
@@ -67,6 +67,19 @@ IntercomRails.config do |config|
|
|
67
67
|
# :number_of_messages => Proc.new { |app| app.messages.count },
|
68
68
|
# :is_interesting => :is_interesting?
|
69
69
|
# }
|
70
|
+
|
71
|
+
# == Company Plan name
|
72
|
+
# This is the name of the plan a company is currently paying (or not paying) for.
|
73
|
+
# e.g. Messaging, Free, Pro, etc.
|
74
|
+
#
|
75
|
+
# config.company.plan = Proc.new { |current_company| current_company.plan.name }
|
76
|
+
|
77
|
+
# == Company Monthly Spend
|
78
|
+
# This is the amount the company spends each month on your app. If your company
|
79
|
+
# has a plan, it will set the 'total value' of that plan appropriately.
|
80
|
+
#
|
81
|
+
# config.company.monthly_spend = Proc.new { |current_company| current_company.plan.price }
|
82
|
+
# config.company.monthly_spend = Proc.new { |current_company| (current_company.plan.price - current_company.subscription.discount) }
|
70
83
|
<%- end -%>
|
71
84
|
|
72
85
|
# == Inbox Style
|
@@ -11,7 +11,8 @@ end
|
|
11
11
|
class ActionController::Base
|
12
12
|
|
13
13
|
include IntercomRails::CustomDataHelper
|
14
|
-
|
14
|
+
include IntercomRails::AutoInclude
|
15
|
+
after_filter :intercom_rails_auto_include
|
15
16
|
|
16
17
|
include TestRoutes.url_helpers
|
17
18
|
include TestRoutes.mounted_helpers
|
@@ -2,6 +2,8 @@ require 'action_controller_test_setup'
|
|
2
2
|
|
3
3
|
class TestController < ActionController::Base
|
4
4
|
|
5
|
+
skip_after_filter :intercom_rails_auto_include, :only => :with_user_instance_variable_after_filter_skipped
|
6
|
+
|
5
7
|
def without_user
|
6
8
|
render :text => params[:body], :content_type => 'text/html'
|
7
9
|
end
|
@@ -11,6 +13,10 @@ class TestController < ActionController::Base
|
|
11
13
|
render :text => params[:body], :content_type => 'text/html'
|
12
14
|
end
|
13
15
|
|
16
|
+
def with_user_instance_variable_after_filter_skipped
|
17
|
+
with_user_instance_variable
|
18
|
+
end
|
19
|
+
|
14
20
|
def with_user_and_app_instance_variables
|
15
21
|
@user = dummy_user
|
16
22
|
@app = dummy_company
|
@@ -153,4 +159,9 @@ class AutoIncludeFilterTest < ActionController::TestCase
|
|
153
159
|
assert_includes @response.body, "6"
|
154
160
|
end
|
155
161
|
|
162
|
+
def test_skip_after_filter
|
163
|
+
get :with_user_instance_variable_after_filter_skipped, :body => "<body>Hello world</body>"
|
164
|
+
assert_equal @response.body, "<body>Hello world</body>"
|
165
|
+
end
|
166
|
+
|
156
167
|
end
|
@@ -50,6 +50,15 @@ class ConfigTest < MiniTest::Unit::TestCase
|
|
50
50
|
assert_equal custom_data_config, IntercomRails.config.user.custom_data
|
51
51
|
end
|
52
52
|
|
53
|
+
def test_setting_company_custom_data
|
54
|
+
custom_data_config = {
|
55
|
+
'the_local' => Proc.new { 'club 93' }
|
56
|
+
}
|
57
|
+
|
58
|
+
IntercomRails.config.company.custom_data = custom_data_config
|
59
|
+
assert_equal custom_data_config, IntercomRails.config.company.custom_data
|
60
|
+
end
|
61
|
+
|
53
62
|
def test_setting_inbox_style
|
54
63
|
IntercomRails.config.inbox.style = :custom
|
55
64
|
assert_equal :custom, IntercomRails.config.inbox.style
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: intercom-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2013-01-02 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activesupport
|
@@ -179,12 +179,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
179
|
- - ! '>='
|
180
180
|
- !ruby/object:Gem::Version
|
181
181
|
version: '0'
|
182
|
+
segments:
|
183
|
+
- 0
|
184
|
+
hash: 3627757893855353112
|
182
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
186
|
none: false
|
184
187
|
requirements:
|
185
188
|
- - ! '>='
|
186
189
|
- !ruby/object:Gem::Version
|
187
190
|
version: '0'
|
191
|
+
segments:
|
192
|
+
- 0
|
193
|
+
hash: 3627757893855353112
|
188
194
|
requirements: []
|
189
195
|
rubyforge_project: intercom-rails
|
190
196
|
rubygems_version: 1.8.23
|