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.
@@ -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 IntercomRails::AutoIncludeFilter
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
- class AutoIncludeFilter
3
+ module AutoInclude
4
+ def intercom_rails_auto_include
5
+ Filter.filter(self)
6
+ end
4
7
 
5
- CLOSING_BODY_TAG = %r{</body>}
8
+ class Filter
6
9
 
7
- def self.filter(controller)
8
- auto_include_filter = new(controller)
9
- return unless auto_include_filter.include_javascript?
10
+ CLOSING_BODY_TAG = %r{</body>}
10
11
 
11
- auto_include_filter.include_javascript!
12
- end
12
+ def self.filter(controller)
13
+ auto_include_filter = new(controller)
14
+ return unless auto_include_filter.include_javascript?
13
15
 
14
- attr_reader :controller
16
+ auto_include_filter.include_javascript!
17
+ end
15
18
 
16
- def initialize(kontroller)
17
- @controller = kontroller
18
- end
19
+ attr_reader :controller
19
20
 
20
- def include_javascript!
21
- response.body = response.body.gsub(CLOSING_BODY_TAG, intercom_script_tag.output + '\\0')
22
- end
21
+ def initialize(kontroller)
22
+ @controller = kontroller
23
+ end
23
24
 
24
- def include_javascript?
25
- !intercom_script_tag_called_manually? &&
26
- html_content_type? &&
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
- private
32
- def response
33
- controller.response
34
- end
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
- def html_content_type?
37
- response.content_type == 'text/html'
38
- end
36
+ private
37
+ def response
38
+ controller.response
39
+ end
39
40
 
40
- def response_has_closing_body_tag?
41
- !!(response.body[CLOSING_BODY_TAG])
42
- end
41
+ def html_content_type?
42
+ response.content_type == 'text/html'
43
+ end
43
44
 
44
- def intercom_script_tag_called_manually?
45
- controller.instance_variable_get(SCRIPT_TAG_HELPER_CALLED_INSTANCE_VARIABLE)
46
- end
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
- class Module
1
+ require 'active_support/inflector'
2
2
 
3
- def config_accessor(*args, &block)
4
- config_reader(*args)
5
- config_writer(*args, &block)
6
- end
3
+ module IntercomRails
4
+
5
+ class ConfigSingleton
7
6
 
8
- def config_reader(name)
9
- self.send(:define_singleton_method, name) do
10
- instance_variable_get("@#{name}")
7
+ def self.config_accessor(*args, &block)
8
+ config_reader(*args)
9
+ config_writer(*args, &block)
11
10
  end
12
- end
13
11
 
14
- def config_writer(name, &block)
15
- self.send(:define_singleton_method, "#{name}=") do |value|
16
- block.call(value) if block
17
- instance_variable_set("@#{name}", value)
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
- def config_group(name, &block)
22
- camelized_name = name.to_s.split('_').map { |s| s[0].upcase + s[1..-1] }.join('')
23
- group = self.const_set(camelized_name, Module.new)
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
- self.send(:define_singleton_method, name) do
26
- group
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
- end
50
+ class Config < ConfigSingleton
33
51
 
34
- module IntercomRails
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
- module Config
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 do |value|
56
- raise ArgumentError, "user.current should be a Proc" unless value.kind_of?(Proc)
57
- end
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 do |value|
77
- raise ArgumentError, "company.current should be a Proc" unless value.kind_of?(Proc)
78
- end
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
@@ -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? && company.respond_to?(:id) && company.id.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
- hsh = {}
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
- return true if user.respond_to?(:id) && user.id.present?
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 :after_filter, AutoIncludeFilter
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
@@ -1,3 +1,3 @@
1
1
  module IntercomRails
2
- VERSION = "0.2.8"
2
+ VERSION = "0.2.9"
3
3
  end
@@ -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
- after_filter IntercomRails::AutoIncludeFilter
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.8
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: 2012-12-18 00:00:00.000000000 Z
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