intercom-rails 0.2.8 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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