paid_up 0.11.7 → 0.12.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +17 -13
  3. data/.rubocop_todo.yml +7 -0
  4. data/.travis.yml +4 -3
  5. data/Gemfile +29 -24
  6. data/README.md +22 -1
  7. data/Rakefile +6 -5
  8. data/VERSION +1 -1
  9. data/app/controllers/paid_up/paid_up_controller.rb +16 -9
  10. data/app/controllers/paid_up/plans_controller.rb +2 -0
  11. data/app/controllers/paid_up/subscriptions_controller.rb +58 -49
  12. data/app/helpers/paid_up/features_helper.rb +35 -34
  13. data/app/helpers/paid_up/paid_up_helper.rb +10 -8
  14. data/app/helpers/paid_up/plans_helper.rb +75 -55
  15. data/app/helpers/paid_up/subscriptions_helper.rb +17 -13
  16. data/app/models/paid_up/ability.rb +53 -46
  17. data/app/models/paid_up/plan.rb +36 -34
  18. data/app/models/paid_up/plan_feature_setting.rb +2 -0
  19. data/app/models/paid_up/unlimited.rb +2 -0
  20. data/app/views/paid_up/features/_abilities_table.html.haml +1 -45
  21. data/app/views/paid_up/features/_boolean_state.html.haml +6 -0
  22. data/app/views/paid_up/features/_setting_state.html.haml +13 -0
  23. data/app/views/paid_up/subscriptions/index.html.haml +2 -2
  24. data/config/initializers/stripe.rb +2 -0
  25. data/config/locales/en.yml +4 -1
  26. data/config/routes.rb +3 -1
  27. data/lib/generators/paid_up/install/install_generator.rb +4 -1
  28. data/lib/generators/paid_up/install/templates/ability.rb +2 -0
  29. data/lib/generators/paid_up/install/templates/initializer.rb +2 -0
  30. data/lib/generators/paid_up/utils.rb +2 -0
  31. data/lib/paid_up/configuration.rb +4 -2
  32. data/lib/paid_up/engine.rb +2 -0
  33. data/lib/paid_up/extensions/integer.rb +2 -0
  34. data/lib/paid_up/extensions/stripe.rb +2 -0
  35. data/lib/paid_up/feature.rb +10 -7
  36. data/lib/paid_up/feature_setting_type.rb +45 -0
  37. data/lib/paid_up/feature_setting_types/rolify.rb +10 -0
  38. data/lib/paid_up/feature_setting_types/table.rb +7 -0
  39. data/lib/paid_up/localization.rb +2 -0
  40. data/lib/paid_up/mixins/paid_for.rb +59 -47
  41. data/lib/paid_up/mixins/subscriber.rb +45 -101
  42. data/lib/paid_up/railtie.rb +2 -0
  43. data/lib/paid_up/ruby_version_check.rb +15 -0
  44. data/lib/paid_up/subscription.rb +80 -0
  45. data/lib/paid_up/validators/rolify_rows.rb +11 -6
  46. data/lib/paid_up/validators/table_rows.rb +9 -6
  47. data/lib/paid_up/version.rb +2 -0
  48. data/lib/paid_up.rb +8 -0
  49. data/paid_up.gemspec +108 -115
  50. data/spec/controllers/paid_up/plans_spec.rb +2 -0
  51. data/spec/controllers/paid_up/subscriptions_spec.rb +18 -11
  52. data/spec/dummy/Rakefile +2 -0
  53. data/spec/dummy/app/assets/stylesheets/application.css.scss +6 -0
  54. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  55. data/spec/dummy/app/models/ability.rb +2 -0
  56. data/spec/dummy/app/models/doodad.rb +2 -0
  57. data/spec/dummy/app/models/group.rb +2 -0
  58. data/spec/dummy/app/models/post.rb +2 -0
  59. data/spec/dummy/app/models/role.rb +2 -0
  60. data/spec/dummy/app/models/user.rb +2 -0
  61. data/spec/dummy/app/views/layouts/application.html.haml +13 -11
  62. data/spec/dummy/bin/bundle +2 -0
  63. data/spec/dummy/bin/rails +2 -0
  64. data/spec/dummy/bin/rake +2 -0
  65. data/spec/dummy/bin/setup +10 -8
  66. data/spec/dummy/config/application.rb +2 -3
  67. data/spec/dummy/config/boot.rb +2 -0
  68. data/spec/dummy/config/environment.rb +2 -0
  69. data/spec/dummy/config/environments/development.rb +2 -0
  70. data/spec/dummy/config/environments/test.rb +2 -4
  71. data/spec/dummy/config/initializers/assets.rb +2 -0
  72. data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -0
  73. data/spec/dummy/config/initializers/cookies_serializer.rb +2 -0
  74. data/spec/dummy/config/initializers/devise.rb +2 -0
  75. data/spec/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  76. data/spec/dummy/config/initializers/inflections.rb +1 -0
  77. data/spec/dummy/config/initializers/mime_types.rb +1 -0
  78. data/spec/dummy/config/initializers/paid_up.rb +10 -16
  79. data/spec/dummy/config/initializers/rolify.rb +2 -0
  80. data/spec/dummy/config/initializers/session_store.rb +2 -0
  81. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  82. data/spec/dummy/config/routes.rb +2 -0
  83. data/spec/dummy/config.ru +2 -0
  84. data/spec/dummy/db/schema.rb +14 -23
  85. data/spec/dummy/db/seeds.rb +8 -6
  86. data/spec/dummy/db/test.sqlite3 +0 -0
  87. data/spec/dummy/lib/tasks/system.rake +2 -0
  88. data/spec/factories/doodad.rb +2 -0
  89. data/spec/factories/group.rb +2 -0
  90. data/spec/factories/plan.rb +2 -0
  91. data/spec/factories/plan_feature_setting.rb +2 -0
  92. data/spec/factories/post.rb +2 -0
  93. data/spec/factories/user.rb +3 -1
  94. data/spec/models/group_spec.rb +9 -7
  95. data/spec/models/paid_up/feature_spec.rb +2 -0
  96. data/spec/models/paid_up/plan_feature_setting_spec.rb +2 -0
  97. data/spec/models/paid_up/plan_spec.rb +2 -0
  98. data/spec/models/scope_spec.rb +9 -7
  99. data/spec/models/user_spec.rb +60 -58
  100. data/spec/paid_up_spec.rb +2 -0
  101. data/spec/rails_helper.rb +16 -2
  102. data/spec/routing/paid_up/plans_spec.rb +2 -0
  103. data/spec/routing/paid_up/subscription_spec.rb +2 -0
  104. data/spec/spec_helper.rb +2 -0
  105. data/spec/support/controller_macros.rb +2 -0
  106. data/spec/support/factory_girl.rb +2 -0
  107. data/spec/support/loaded_site/features.rb +2 -0
  108. data/spec/support/loaded_site/groups.rb +2 -0
  109. data/spec/support/loaded_site/loaded_site.rb +2 -0
  110. data/spec/support/loaded_site/plans.rb +2 -0
  111. data/spec/support/loaded_site/posts.rb +2 -0
  112. data/spec/support/loaded_site/users.rb +4 -2
  113. data/spec/support/stripe.rb +2 -0
  114. data/spec/views/paid_up/plans_spec.rb +9 -7
  115. data/spec/views/paid_up/subscriptions_spec.rb +20 -19
  116. metadata +124 -90
  117. data/app/views/devise/confirmations/new.html.haml +0 -13
  118. data/app/views/devise/passwords/edit.html.haml +0 -19
  119. data/app/views/devise/passwords/new.html.haml +0 -14
  120. data/app/views/devise/registrations/_new_form.html.haml +0 -23
  121. data/app/views/devise/registrations/edit.html.haml +0 -39
  122. data/app/views/devise/registrations/new.html.haml +0 -11
  123. data/app/views/devise/sessions/_new_form.html.haml +0 -21
  124. data/app/views/devise/sessions/new.html.haml +0 -11
  125. data/app/views/devise/shared/_links.html.haml +0 -14
  126. data/app/views/devise/unlocks/new.html.haml +0 -14
  127. data/app/views/layouts/mailer.html.haml +0 -3
  128. data/app/views/layouts/mailer.text.haml +0 -1
  129. data/app/views/paid_up/subscription_mailer/payment_failed_email.html.haml +0 -0
  130. data/app/views/paid_up/subscription_mailer/payment_failed_email.text.haml +0 -0
  131. data/coverage/.last_run.json +0 -5
  132. data/coverage/.resultset.json +0 -1927
  133. data/spec/dummy/app/views/pages/index.html.haml +0 -1
  134. data/spec/dummy/config/environments/production.rb +0 -83
  135. data/spec/dummy/config/initializers/high_voltage.rb +0 -3
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # PaidUp module
2
4
  module PaidUp
3
- @@feature_object = {}
5
+ @feature_object = {}
4
6
 
5
7
  def self.add_feature(params)
6
8
  feature = PaidUp::Feature.new(params)
7
- @@feature_object[feature.slug.to_sym] = feature
9
+ @feature_object[feature.slug.to_sym] = feature
8
10
  end
9
11
 
10
12
  def self.features
11
- @@feature_object
13
+ @feature_object
12
14
  end
13
15
 
14
16
  # Feature Class: Not an ActiveRecord object.
@@ -45,7 +47,7 @@ module PaidUp
45
47
  end
46
48
 
47
49
  def feature_model_name
48
- acceptable_setting_types = %w( table_rows rolify_rows )
50
+ acceptable_setting_types = %w(table_rows rolify_rows)
49
51
  unless acceptable_setting_types.include? setting_type
50
52
  raise :no_implicit_conversion_of_type_features.l(type: setting_type)
51
53
  end
@@ -60,6 +62,10 @@ module PaidUp
60
62
  raw[slug.to_sym]
61
63
  end
62
64
 
65
+ def self.find_by_slug!(slug)
66
+ find_by_slug(slug) || raise(:feature_not_found.l)
67
+ end
68
+
63
69
  def self.all
64
70
  raw.values
65
71
  end
@@ -80,10 +86,7 @@ module PaidUp
80
86
  find_all(conditions).first
81
87
  end
82
88
 
83
- # Define on self, since it's a class method
84
89
  def self.method_missing(method_sym, *arguments, &block)
85
- # the first argument is a Symbol, so you need to_s it if you want to
86
- # pattern match
87
90
  if method_sym.to_s =~ /^find_by_(.*)$/
88
91
  find(Regexp.last_match[1].to_sym => arguments.first)
89
92
  elsif method_sym.to_s =~ /^find_all_by_(.*)$/
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PaidUp module
4
+ module PaidUp
5
+ # Feature Setting Type Class: Not an ActiveRecord object.
6
+ class FeatureSettingType
7
+ include ActiveModel::Model
8
+ include ActiveModel::AttributeMethods
9
+
10
+ attr_accessor :name, :user
11
+ delegate :plan, to: :user
12
+
13
+ def rows_unlimited?
14
+ rows_allowed == PaidUp::Unlimited.to_i
15
+ end
16
+
17
+ def rows_remaining
18
+ rows_allowed - rows_count
19
+ end
20
+
21
+ def rows_allowed
22
+ plan.feature_setting name
23
+ end
24
+
25
+ def rows
26
+ scope.where(user: user)
27
+ end
28
+
29
+ def ids
30
+ rows.ids
31
+ end
32
+
33
+ def rows_count
34
+ rows.size
35
+ end
36
+
37
+ def model
38
+ name.classify.constantize
39
+ end
40
+
41
+ def scope
42
+ model.paid_for_scope
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaidUp
4
+ # Class for 'rolify_rows' feature setting type
5
+ class RolifyFeatureSettingType < FeatureSettingType
6
+ def rows
7
+ scope.with_role(:owner, user)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaidUp
4
+ # Class for 'table_rows' feature setting type
5
+ class TableFeatureSettingType < FeatureSettingType
6
+ end
7
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # String Extension
2
4
  module StringExtension
3
5
  def localize(*args)
@@ -1,5 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaidUp
2
4
  module Mixins
5
+ ASSOCIATION_METHODS = {
6
+ rolify_rows: :associations_for_rolify_rows,
7
+ table_rows: :associations_for_table_rows,
8
+ boolean: :true
9
+ }.freeze
10
+
3
11
  # PaidFor Mixin
4
12
  module PaidFor
5
13
  extend ActiveSupport::Concern
@@ -7,41 +15,53 @@ module PaidUp
7
15
  def paid_for(options = {})
8
16
  cattr_accessor :paid_for_scope_symbol # Creates class-level instance var
9
17
 
10
- send :extend, ClassMethods
11
- send :include, InstanceMethods
18
+ extend ClassMethods
19
+ include InstanceMethods
12
20
 
13
21
  self.paid_for_scope_symbol = options.fetch(:scope, :all)
14
- feature.nil? && raise(
15
- :feature_not_found_feature.l(feature: table_name)
16
- )
17
- case feature.setting_type
18
- when 'boolean'
19
- # Nothing needs doing
20
- when 'rolify_rows'
21
- resourcify
22
- attr_accessor :owner
23
- when 'table_rows'
24
- belongs_to :user
25
- User.has_many table_name.to_sym
26
- else
27
- raise(
28
- :value_is_not_a_valid_setting_type.l(
29
- value: feature.setting_type
30
- )
31
- )
32
- end
22
+
23
+ validate_feature
24
+ associations
33
25
  end
34
26
 
27
+ # Extended by paid_for mixin
35
28
  module ClassMethods
36
29
  def feature
37
30
  PaidUp::Feature.find_by_slug(table_name)
38
31
  end
39
32
 
40
33
  def paid_for_scope
41
- send(self.paid_for_scope_symbol)
34
+ send(paid_for_scope_symbol)
35
+ end
36
+
37
+ private
38
+
39
+ def validate_feature
40
+ return true unless feature.nil?
41
+ raise(:feature_not_found_feature.l(feature: table_name))
42
+ end
43
+
44
+ def associations
45
+ setting_type = feature.setting_type
46
+ method = ASSOCIATION_METHODS[setting_type.to_sym] ||
47
+ raise(
48
+ :value_is_not_a_valid_setting_type.l(value: setting_type)
49
+ )
50
+ send(method)
51
+ end
52
+
53
+ def associations_for_rolify_rows
54
+ resourcify
55
+ attr_accessor :owner
56
+ end
57
+
58
+ def associations_for_table_rows
59
+ belongs_to :user
60
+ User.has_many table_name.to_sym
42
61
  end
43
62
  end
44
63
 
64
+ # Included by paid_for mixin
45
65
  module InstanceMethods
46
66
  def owners
47
67
  case self.class.feature.setting_type
@@ -71,40 +91,32 @@ module PaidUp
71
91
  end
72
92
 
73
93
  def owners_records
74
- ids = []
75
- owners.each do |subscriber|
76
- case self.class.feature.setting_type
77
- when 'table_rows'
78
- ids += subscriber.send(self.class.table_name)
79
- .paid_for_scope
80
- .ids
81
- when 'rolify_rows'
82
- ids += self.class
83
- .with_role(:owner, subscriber)
84
- .paid_for_scope
85
- .ids
86
- else
87
- raise(
88
- :no_features_associated_with_table.l(
89
- table: self.class.table_name
90
- )
91
- )
92
- end
94
+ self.class.where(id: owners_records_ids)
95
+ end
96
+
97
+ def owners_records_ids
98
+ setting = self.class.feature.setting_type
99
+ .gsub('_rows', '_setting')
100
+ table_name = self.class.table_name
101
+ unless %w(table_setting rolify_setting).include? setting
102
+ raise :no_features_associated_with_table.l(table: table_name)
93
103
  end
94
- self.class.where(id: ids)
104
+ owners.map do |subscriber|
105
+ subscriber.send(setting, table_name).ids
106
+ end.flatten
95
107
  end
96
108
 
97
109
  def owners_records_count
98
- owners_records.count
110
+ owners_records.size
99
111
  end
100
112
 
101
- def enabled
113
+ def enabled?
102
114
  if owners_enabled_count >= owners_records_count
103
115
  true
104
116
  else
105
- enabled_records = owners_records.order('created_at ASC')
106
- .limit(owners_enabled_count)
107
- enabled_records.include? self
117
+ owners_records.order(id: :asc)
118
+ .limit(owners_enabled_count)
119
+ .include? self
108
120
  end
109
121
  end
110
122
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaidUp
2
4
  module Mixins
3
5
  # Subscriber Mixin
@@ -10,12 +12,15 @@ module PaidUp
10
12
  has_many feature.slug.to_sym
11
13
  end
12
14
 
15
+ delegate :plan, to: :paid_up_subscription
13
16
  after_initialize :set_default_attributes, :load_stripe_data
17
+ after_save :load_stripe_data
14
18
  before_save :remove_anonymous_association
15
19
  before_destroy { |record| record.stripe_data.delete }
16
- send :include, InstanceMethods
20
+ include InstanceMethods
17
21
  end
18
22
 
23
+ # Included by subscriber mixin
19
24
  module InstanceMethods
20
25
  def reload(*args, &blk)
21
26
  super(*args, &blk)
@@ -31,144 +36,71 @@ module PaidUp
31
36
  stripe_data.present? && stripe_data.sources.all(object: 'card')
32
37
  end
33
38
 
34
- def subscribe_to_plan(plan_to_set, stripe_token = nil, trial_end = nil)
39
+ def subscribe_to_plan(
40
+ new_plan, stripe_token = nil, coupon = nil, trial_end = nil
41
+ )
35
42
  # If there is an existing subscription
36
- if stripe_id.present? && !subscription.nil?
37
- if stripe_token.present? # The customer has entered a new card
38
- subscription.source = stripe_token
39
- subscription.save
40
- reload
41
- end
42
- if coupon_code.present?
43
- stripe_data.coupon = coupon_code
44
- stripe_data.save
45
- end
46
- if trial_end.present?
47
- stripe_data.subscription.trial_end = trial_end
48
- stripe_data.subscription.save
49
- end
50
- subscription.plan = plan_to_set.stripe_id
51
- result = subscription.save ||
52
- (raise(:could_not_update_subscription.l) && false)
43
+ if stripe_id.present? && paid_up_subscription.present?
44
+ paid_up_subscription.update(new_plan, stripe_token, coupon, trial_end)
53
45
  else # Totally new subscription
54
- args = {
55
- source: stripe_token,
56
- plan: plan_to_set.stripe_id,
57
- email: email,
58
- trial_end: trial_end
59
- }
60
- coupon_code.present? && args[:coupon] = coupon_code
61
- customer = Stripe::Customer.create(args) ||
62
- (raise(:could_not_create_subscription.l) && false)
63
-
64
- # If there is an update to be made, we go ahead
65
- if stripe_id != customer.id
66
- result = update_attributes(stripe_id: customer.id) ||
67
- (raise(:could_not_associate_subscription.l) && false)
68
- else
69
- result = true
70
- end
46
+ paid_up_subscription.create(new_plan, stripe_token, coupon, trial_end)
71
47
  end
72
- result && Rails.cache.delete("#{stripe_id}/stripe_data") && reload
48
+ Rails.cache.delete("#{stripe_id}/stripe_data")
49
+ reload
73
50
  end
74
51
 
75
52
  def subscribe_to_free_plan
76
53
  subscribe_to_plan PaidUp::Plan.free
77
54
  end
78
55
 
79
- def plan
80
- if subscription.present?
81
- PaidUp::Plan.find_by_stripe_id(subscription.plan.id)
82
- else
83
- PaidUp::Plan.free
84
- end
85
- end
86
-
87
- def table_rows_unlimited?(table_name)
88
- table_rows_allowed(table_name) == PaidUp::Unlimited.to_i
89
- end
90
-
91
- def table_rows_remaining(table_name)
92
- table_rows_allowed(table_name) - table_rows(table_name)
93
- end
94
-
95
- def table_rows_allowed(table_name)
96
- plan.feature_setting table_name
97
- end
98
-
99
- def table_rows(table_name)
100
- model = table_name.classify.constantize
101
- model.where(user: self).paid_for_scope.size
102
- end
103
-
104
- def rolify_rows_unlimited?(table_name)
105
- rolify_rows_allowed(table_name) == PaidUp::Unlimited.to_i
106
- end
107
-
108
- def rolify_rows_remaining(table_name)
109
- rolify_rows_allowed(table_name) - rolify_rows(table_name)
56
+ def table_setting(table_name)
57
+ PaidUp::TableFeatureSettingType.new(name: table_name, user: self)
110
58
  end
111
59
 
112
- def rolify_rows_allowed(table_name)
113
- plan.feature_setting table_name
114
- end
115
-
116
- def rolify_rows(table_name)
117
- model = table_name.classify.constantize
118
- model.with_role(:owner, self).paid_for_scope.size
60
+ def rolify_setting(table_name)
61
+ PaidUp::RolifyFeatureSettingType.new(name: table_name, user: self)
119
62
  end
120
63
 
121
64
  def plan_stripe_id
122
- subscription.nil? && return
123
- subscription.plan.id
65
+ paid_up_subscription&.stripe_data&.plan&.id
124
66
  end
125
67
 
126
- def subscription
68
+ def paid_up_subscription
127
69
  stripe_data.nil? && subscribe_to_free_plan
128
- stripe_data.subscriptions.data.first
70
+ @subscription
129
71
  end
130
72
 
131
- def is_subscribed_to?(plan_to_check)
73
+ def subscribed_to?(plan_to_check)
132
74
  plan.present? && plan.id == plan_to_check.id
133
75
  end
134
76
 
135
77
  def can_upgrade_to?(plan_to_check)
136
78
  plan.nil? || (
137
- !is_subscribed_to?(plan_to_check) &&
79
+ !subscribed_to?(plan_to_check) &&
138
80
  (plan_to_check.sort_order.to_i > plan.sort_order.to_i)
139
81
  )
140
82
  end
141
83
 
142
84
  def can_downgrade_to?(plan_to_check)
143
- !plan.nil? && (
144
- !is_subscribed_to?(plan_to_check) &&
85
+ plan.present? && (
86
+ !subscribed_to?(plan_to_check) &&
145
87
  (plan_to_check.sort_order.to_i < plan.sort_order.to_i)
146
88
  )
147
89
  end
148
90
 
149
91
  def using_free_plan?
150
- plan.nil? ||
151
- stripe_data.delinquent ||
152
- (plan.stripe_id == PaidUp.configuration.free_plan_stripe_id)
92
+ plan.nil? || stripe_data.delinquent ||
93
+ plan.stripe_id == PaidUp.configuration.free_plan_stripe_id
153
94
  end
154
95
 
155
96
  private
156
97
 
157
98
  def set_default_attributes
158
- if new_record?
159
- self.stripe_id = PaidUp.configuration.anonymous_customer_stripe_id
160
- end
99
+ return unless new_record?
100
+ self.stripe_id = PaidUp.configuration.anonymous_customer_stripe_id
161
101
  end
162
102
 
163
103
  def load_stripe_data
164
- working_stripe_id = if new_record?
165
- PaidUp.configuration
166
- .anonymous_customer_stripe_id
167
- else
168
- !stripe_id.present? && subscribe_to_free_plan
169
- stripe_id
170
- end
171
-
172
104
  @customer_stripe_data = Rails.cache.fetch(
173
105
  "#{working_stripe_id}/stripe_data",
174
106
  expires_in: 12.hours
@@ -176,14 +108,26 @@ module PaidUp
176
108
  Stripe::Customer.retrieve working_stripe_id
177
109
  end
178
110
 
179
- @customer_stripe_data.nil? && raise(:could_not_load_subscription.l)
111
+ @subscription = PaidUp::Subscription.new(user: self)
112
+
113
+ raise(:could_not_load_subscription.l) if @customer_stripe_data.nil?
114
+ stripe_data
180
115
  end
181
116
 
182
- def remove_anonymous_association
183
- if stripe_id == PaidUp.configuration.anonymous_customer_stripe_id
184
- self.stripe_id = nil
117
+ def working_stripe_id
118
+ if new_record?
119
+ PaidUp.configuration.anonymous_customer_stripe_id
120
+ else
121
+ subscribe_to_free_plan unless stripe_id.present?
122
+ stripe_id
185
123
  end
186
124
  end
125
+
126
+ def remove_anonymous_association
127
+ return unless stripe_id ==
128
+ PaidUp.configuration.anonymous_customer_stripe_id
129
+ self.stripe_id = nil
130
+ end
187
131
  end
188
132
  end
189
133
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaidUp
2
4
  class Railtie < Rails::Railtie
3
5
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ if RUBY_VERSION < '2.3.0' && RUBY_ENGINE == 'ruby'
4
+ desc = if defined?(RUBY_DESCRIPTION)
5
+ RUBY_DESCRIPTION
6
+ else
7
+ "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
8
+ end
9
+ abort <<-end_message
10
+ This version of PaidUp requires Ruby 2.3.0 or newer.
11
+ You're running
12
+ #{desc}
13
+ Please upgrade to Ruby 2.3.0 or newer to continue.
14
+ end_message
15
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PaidUp module
4
+ module PaidUp
5
+ # Subscription Class: Not an ActiveRecord object.
6
+ class Subscription
7
+ include ActiveModel::Model
8
+ include ActiveModel::AttributeMethods
9
+
10
+ attr_accessor :stripe_data, :user
11
+ delegate :status, :trial_start, :trial_end, :current_period_start,
12
+ :current_period_end, :cancel_at_period_end, to: :stripe_data
13
+ delegate :email, :stripe_id, to: :user
14
+
15
+ def initialize(args)
16
+ super args
17
+ self.stripe_data = user.stripe_data.subscriptions.first
18
+ end
19
+
20
+ def plan
21
+ if stripe_data&.plan&.id.present?
22
+ PaidUp::Plan.find_by_stripe_id(stripe_data.plan.id)
23
+ else
24
+ PaidUp::Plan.free
25
+ end
26
+ end
27
+
28
+ def update(plan, stripe_token = nil, coupon = nil, trial_end = nil)
29
+ update_stripe_token(stripe_token)
30
+ update_coupon(coupon)
31
+ update_trial_end(trial_end)
32
+ update_plan(plan)
33
+ stripe_data.save || raise(:could_not_update_plan.l)
34
+ end
35
+
36
+ def create(plan, stripe_token = nil, coupon = nil, trial_end = nil)
37
+ customer = Stripe::Customer.create(source: stripe_token, email: email,
38
+ plan: plan.stripe_id, coupon: coupon,
39
+ trial_end: trial_end) ||
40
+ raise(:could_not_create_subscription.l)
41
+
42
+ # If there is an update to be made, we go ahead
43
+ return true if stripe_id == customer.id
44
+ user.update_attributes(stripe_id: customer.id) ||
45
+ raise(:could_not_associate_subscription.l)
46
+ end
47
+
48
+ private
49
+
50
+ def update_stripe_token(stripe_token)
51
+ return unless stripe_token.present?
52
+ # The customer has entered a new card
53
+ # We need to update the info on the Stripe API.
54
+ stripe_data.source = stripe_token
55
+ end
56
+
57
+ def update_coupon(coupon)
58
+ return unless coupon.present?
59
+ # The customer has entered a new coupon code
60
+ # We need to update the stripe customer.
61
+ stripe_data.coupon = coupon
62
+ end
63
+
64
+ def update_trial_end(trial_end)
65
+ return unless trial_end.present?
66
+ # The customer has cancelled or otherwise altered their trial_end
67
+ # We need to update the info on the Stripe API.
68
+ # stripe_data.stripe_data.trial_end = trial_end
69
+ # stripe_data.stripe_data.save!
70
+ stripe_data.trial_end = trial_end
71
+ end
72
+
73
+ def update_plan(new_plan)
74
+ return unless new_plan.present?
75
+ # The customer has changed plans
76
+ # We need to update the info on the Stripe API.
77
+ stripe_data.plan = new_plan.stripe_id
78
+ end
79
+ end
80
+ end
@@ -1,17 +1,22 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaidUp
2
4
  module Validators
3
5
  # RolifyRows Validator
4
6
  class RolifyRows < ActiveModel::Validator
5
7
  def validate(record)
8
+ found_in = options[:found_in]
6
9
  if record.send(options[:field]) == options[:comparison] &&
7
- !ActiveRecord::Base.connection.table_exists?(
8
- record.send(options[:found_in])
9
- )
10
- record.errors[
11
- options[:found_in]
12
- ] << :when_using_rolify_rows_table_must_exist.l
10
+ !found_in_valid?(record, found_in)
11
+ record.errors[found_in] << :when_using_rolify_rows_table_must_exist.l
13
12
  end
14
13
  end
14
+
15
+ def found_in_valid?(record, found_in)
16
+ ActiveRecord::Base.connection.data_source_exists?(
17
+ record.send(found_in)
18
+ )
19
+ end
15
20
  end
16
21
  end
17
22
  end
@@ -1,17 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PaidUp
2
4
  module Validators
3
5
  # Table Rows validator
4
6
  class TableRows < ActiveModel::Validator
5
7
  def validate(record)
8
+ found_in = options[:found_in]
6
9
  if record.send(options[:field]) == options[:comparison] &&
7
- !ActiveRecord::Base.connection.table_exists?(
8
- record.send(options[:found_in])
9
- )
10
- record.errors[
11
- options[:found_in]
12
- ] << :when_using_table_rows_table_must_exist.l
10
+ !found_in_valid?(record, found_in)
11
+ record.errors[found_in] << :when_using_table_rows_table_must_exist.l
13
12
  end
14
13
  end
14
+
15
+ def found_in_valid?(record, found_in)
16
+ ActiveRecord::Base.connection.data_source_exists? record.send(found_in)
17
+ end
15
18
  end
16
19
  end
17
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # PaidUp module
2
4
  module PaidUp
3
5
  VERSION = File.read(File.expand_path('../../../VERSION', __FILE__))
data/lib/paid_up.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # PaidUp Module
2
4
  module PaidUp
3
5
  require 'active_record/railtie'
@@ -18,10 +20,13 @@ module PaidUp
18
20
 
19
21
  require 'paid_up/configuration'
20
22
  require 'paid_up/feature'
23
+ require 'paid_up/feature_setting_type'
24
+ require 'paid_up/subscription'
21
25
  require 'paid_up/railtie'
22
26
  require 'paid_up/engine'
23
27
  require 'paid_up/localization'
24
28
  require 'paid_up/version'
29
+ require 'paid_up/ruby_version_check'
25
30
 
26
31
  require 'paid_up/extensions/stripe'
27
32
  require 'paid_up/extensions/integer'
@@ -29,6 +34,9 @@ module PaidUp
29
34
  require 'paid_up/mixins/subscriber'
30
35
  require 'paid_up/mixins/paid_for'
31
36
 
37
+ require 'paid_up/feature_setting_types/table'
38
+ require 'paid_up/feature_setting_types/rolify'
39
+
32
40
  require 'haml-rails'
33
41
  require 'bootstrap_leather'
34
42