active_presenter 1.4.0 → 2.0.0a

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -28,7 +28,7 @@ Creating a presenter is as simple as subclassing ActivePresenter::Base. Use the
28
28
  presents :user, :account
29
29
  end
30
30
 
31
- In the above example, :user will (predictably) become User. If you want to override this behaviour, specify the desired types in a hash, as so:
31
+ In the above example, :user will (predictably) become User. If you want to override this behavior, specify the desired types in a hash, as so:
32
32
 
33
33
  class PresenterWithTwoAddresses < ActivePresenter::Base
34
34
  presents :primary_address => Address, :secondary_address => Address
@@ -68,6 +68,15 @@ You can retrieve the errors in two ways.
68
68
 
69
69
  Both of these methods are compatible with error_messages_for. It just depends whether you'd like to show all the errors in one block, or whether you'd prefer to break them up.
70
70
 
71
+ === Protected and Accessible Attributes
72
+
73
+ ActivePresenter supports +attr_protected+ and +attr_accessible+ just like an ActiveRecord object to avoid mass assignment. This can be leveraged to provide an additional layer of protection at the presenter level.
74
+
75
+ class AccountPresenter < ActivePresenter::Base
76
+ presents :user, :profile
77
+ attr_accessible :user_email, :profile_birthday
78
+ end
79
+
71
80
  === Saving
72
81
 
73
82
  You can save your presenter the same way you'd save an ActiveRecord object. Both #save, and #save! behave the same way they do on a normal AR model.
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
1
  require 'rake'
2
- require 'rake/rdoctask'
2
+ require 'rdoc/task'
3
3
  require File.dirname(__FILE__)+'/lib/active_presenter'
4
4
  Dir.glob(File.dirname(__FILE__)+'/lib/tasks/**/*.rake').each { |l| load l }
5
5
 
6
6
  task :default => :test
7
7
 
8
8
  task :test do
9
- Dir['test/**/*_test.rb'].each { |l| require l }
9
+ Dir['test/**/*_test.rb'].each { |l| require File.join(File.dirname(__FILE__),l)}
10
10
  end
@@ -2,13 +2,19 @@ module ActivePresenter
2
2
  # Base class for presenters. See README for usage.
3
3
  #
4
4
  class Base
5
- include ActiveSupport::Callbacks
6
- define_callbacks :before_validation, :before_save, :after_save
7
-
5
+ extend ActiveModel::Callbacks
6
+ extend ActiveModel::Naming
7
+ extend ActiveModel::Translation
8
+ include ActiveModel::MassAssignmentSecurity
9
+ include ActiveModel::Conversion
10
+
11
+ attr_reader :errors
12
+
13
+ define_model_callbacks :validation, :save
14
+
8
15
  class_inheritable_accessor :presented
9
- class_inheritable_accessor :attr_protected, :attr_accessible
10
16
  self.presented = {}
11
-
17
+
12
18
  # Indicates which models are to be presented by this presenter.
13
19
  # i.e.
14
20
  #
@@ -27,29 +33,29 @@ module ActivePresenter
27
33
  types.each { |t| types_and_classes[t] = t.to_s.tableize.classify.constantize }
28
34
 
29
35
  attr_accessor *types_and_classes.keys
30
-
36
+
31
37
  types_and_classes.keys.each do |t|
32
38
  define_method("#{t}_errors") do
33
39
  send(t).errors
34
40
  end
35
-
41
+
36
42
  presented[t] = types_and_classes[t]
37
43
  end
38
44
  end
39
-
45
+
40
46
  def self.human_attribute_name(attribute_key_name, options = {})
41
47
  presentable_type = presented.keys.detect do |type|
42
48
  attribute_key_name.to_s.starts_with?("#{type}_") || attribute_key_name.to_s == type.to_s
43
49
  end
44
50
  attribute_key_name_without_class = attribute_key_name.to_s.gsub("#{presentable_type}_", "")
45
-
51
+
46
52
  if presented[presentable_type] and attribute_key_name_without_class != presentable_type.to_s
47
53
  presented[presentable_type].human_attribute_name(attribute_key_name_without_class, options)
48
54
  else
49
55
  I18n.translate(presentable_type, options.merge(:default => presentable_type.to_s.humanize, :scope => [:activerecord, :models]))
50
56
  end
51
57
  end
52
-
58
+
53
59
  # Since ActivePresenter does not descend from ActiveRecord, we need to
54
60
  # mimic some ActiveRecord behavior in order for the ActiveRecord::Errors
55
61
  # object we're using to work properly.
@@ -59,7 +65,7 @@ module ActivePresenter
59
65
  def self.self_and_descendants_from_active_record # :nodoc:
60
66
  [self]
61
67
  end
62
-
68
+
63
69
  def self.human_name(options = {}) # :nodoc:
64
70
  defaults = self_and_descendants_from_active_record.map do |klass|
65
71
  :"#{klass.name.underscore}"
@@ -67,31 +73,7 @@ module ActivePresenter
67
73
  defaults << self.name.humanize
68
74
  I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options))
69
75
  end
70
-
71
- # Note that +attr_protected+ is still applied to the received hash. Thus,
72
- # with this technique you can at most _extend_ the list of protected
73
- # attributes for a particular mass-assignment call.
74
- def self.attr_protected(*attributes)
75
- write_inheritable_attribute(:attr_protected, Set.new(attributes.map {|a| a.to_s}) + (protected_attributes || []))
76
- end
77
-
78
- # Returns an array of all the attributes that have been protected from mass-assignment.
79
- def self.protected_attributes # :nodoc:
80
- read_inheritable_attribute(:attr_protected)
81
- end
82
-
83
- # Note that +attr_accessible+ is still applied to the received hash. Thus,
84
- # with this technique you can at most _narrow_ the list of accessible
85
- # attributes for a particular mass-assignment call.
86
- def self.attr_accessible(*attributes)
87
- write_inheritable_attribute(:attr_accessible, Set.new(attributes.map(&:to_s)) + (accessible_attributes || []))
88
- end
89
-
90
- # Returns an array of all the attributes that have been made accessible to mass-assignment.
91
- def self.accessible_attributes # :nodoc:
92
- read_inheritable_attribute(:attr_accessible)
93
- end
94
-
76
+
95
77
  # Accepts arguments in two forms. For example, if you had a SignupPresenter that presented User, and Account, you could specify arguments in the following two forms:
96
78
  #
97
79
  # 1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft')
@@ -105,13 +87,12 @@ module ActivePresenter
105
87
  # If you don't specify an instance, one will be created by calling Model.new
106
88
  #
107
89
  def initialize(args = {})
108
- args ||= {}
109
-
90
+ @errors = ActiveModel::Errors.new(self)
91
+ return self unless args
110
92
  presented.each do |type, klass|
111
93
  value = args.delete(type)
112
94
  send("#{type}=", value.is_a?(klass) ? value : klass.new)
113
95
  end
114
-
115
96
  self.attributes = args
116
97
  end
117
98
 
@@ -121,11 +102,11 @@ module ActivePresenter
121
102
  #
122
103
  def attributes=(attrs)
123
104
  return if attrs.nil?
124
-
125
- attrs = attrs.stringify_keys
105
+
106
+ attrs = attrs.stringify_keys
126
107
  multi_parameter_attributes = {}
127
- attrs = remove_attributes_protected_from_mass_assignment(attrs)
128
-
108
+ attrs = sanitize_for_mass_assignment(attrs)
109
+
129
110
  attrs.each do |k,v|
130
111
  if (base_attribute = k.to_s.split("(").first) != k.to_s
131
112
  presentable = presentable_for(base_attribute)
@@ -135,87 +116,79 @@ module ActivePresenter
135
116
  send("#{k}=", v) unless attribute_protected?(k)
136
117
  end
137
118
  end
138
-
119
+
139
120
  multi_parameter_attributes.each do |presentable,multi_attrs|
140
121
  send(presentable).send(:attributes=, multi_attrs)
141
122
  end
142
123
  end
143
-
124
+
144
125
  # Makes sure that the presenter is accurate about responding to presentable's attributes, even though they are handled by method_missing.
145
126
  #
146
127
  def respond_to?(method, include_private = false)
147
128
  presented_attribute?(method) || super
148
129
  end
149
-
130
+
150
131
  # Handles the decision about whether to delegate getters and setters to presentable instances.
151
132
  #
152
133
  def method_missing(method_name, *args, &block)
153
134
  presented_attribute?(method_name) ? delegate_message(method_name, *args, &block) : super
154
135
  end
155
-
156
- # Returns an instance of ActiveRecord::Errors with all the errors from the presentables merged in using the type_attribute form (i.e. user_login).
157
- #
158
- def errors
159
- @errors ||= ActiveRecord::Errors.new(self)
160
- end
161
-
136
+
162
137
  # Returns boolean based on the validity of the presentables by calling valid? on each of them.
163
138
  #
164
139
  def valid?
140
+ validated = false
165
141
  errors.clear
166
- if run_callbacks_with_halt(:before_validation)
142
+ result = _run_validation_callbacks do
167
143
  presented.keys.each do |type|
168
144
  presented_inst = send(type)
169
-
170
145
  next unless save?(type, presented_inst)
171
146
  merge_errors(presented_inst, type) unless presented_inst.valid?
172
147
  end
173
-
174
- errors.empty?
148
+ validated = true
175
149
  end
150
+ errors.empty? && validated
176
151
  end
177
-
152
+
178
153
  # Do any of the attributes have unsaved changes?
179
154
  def changed?
180
155
  presented_instances.map(&:changed?).any?
181
156
  end
182
-
157
+
183
158
  # Save all of the presentables, wrapped in a transaction.
184
159
  #
185
160
  # Returns true or false based on success.
186
161
  #
187
162
  def save
188
163
  saved = false
189
-
190
164
  ActiveRecord::Base.transaction do
191
- if valid? && run_callbacks_with_halt(:before_save)
192
- saved = presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save}
193
- raise ActiveRecord::Rollback unless saved # TODO: Does this happen implicitly?
165
+ if valid?
166
+ _run_save_callbacks do
167
+ saved = presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save}
168
+ raise ActiveRecord::Rollback unless saved
169
+ end
194
170
  end
195
-
196
- run_callbacks_with_halt(:after_save) if saved
197
171
  end
198
-
199
172
  saved
200
173
  end
201
-
174
+
202
175
  # Save all of the presentables wrapped in a transaction.
203
176
  #
204
177
  # Returns true on success, will raise otherwise.
205
178
  #
206
179
  def save!
207
- raise ActiveRecord::RecordInvalid.new(self) unless valid?
208
- raise ActiveRecord::RecordNotSaved unless run_callbacks_with_halt(:before_save)
209
-
180
+ saved = false
210
181
  ActiveRecord::Base.transaction do
211
- presented.keys.select {|key| save?(key, send(key))}.each {|key| send(key).save!}
212
-
213
- run_callbacks_with_halt(:after_save)
182
+ raise ActiveRecord::RecordInvalid.new(self) unless valid?
183
+ _run_save_callbacks do
184
+ presented.keys.select {|key| save?(key, send(key))}.all? {|key| send(key).save!}
185
+ saved = true
186
+ end
187
+ raise ActiveRecord::RecordNotSaved.new(self) unless saved
214
188
  end
215
-
216
- true
189
+ saved
217
190
  end
218
-
191
+
219
192
  # Update attributes, and save the presentables
220
193
  #
221
194
  # Returns true or false based on success.
@@ -224,7 +197,7 @@ module ActivePresenter
224
197
  self.attributes = attrs
225
198
  save
226
199
  end
227
-
200
+
228
201
  # Should this presented instance be saved? By default, this returns true
229
202
  # Called from #save and #save!
230
203
  #
@@ -244,72 +217,61 @@ module ActivePresenter
244
217
  def id # :nodoc:
245
218
  nil
246
219
  end
247
-
220
+
248
221
  def new_record?
249
- true
222
+ presented_instances.map(&:new_record?).all?
223
+ end
224
+
225
+ def persisted?
226
+ presented_instances.map(&:persisted?).all?
250
227
  end
251
228
 
252
229
  protected
253
- def presented_instances
254
- presented.keys.map { |key| send(key) }
255
- end
256
-
257
- def delegate_message(method_name, *args, &block)
258
- presentable = presentable_for(method_name)
259
- send(presentable).send(flatten_attribute_name(method_name, presentable), *args, &block)
260
- end
261
-
262
- def presentable_for(method_name)
263
- presented.keys.sort_by { |k| k.to_s.size }.reverse.detect do |type|
264
- method_name.to_s.starts_with?(attribute_prefix(type))
265
- end
266
- end
267
-
268
- def presented_attribute?(method_name)
269
- p = presentable_for(method_name)
270
- !p.nil? && send(p).respond_to?(flatten_attribute_name(method_name,p))
271
- end
272
-
273
- def flatten_attribute_name(name, type)
274
- name.to_s.gsub(/^#{attribute_prefix(type)}/, '')
275
- end
276
-
277
- def attribute_prefix(type)
278
- "#{type}_"
279
- end
280
-
281
- def merge_errors(presented_inst, type)
282
- presented_inst.errors.each do |att,msg|
283
- if att == 'base'
284
- errors.add(type, msg)
285
- else
286
- errors.add(attribute_prefix(type)+att, msg)
287
- end
288
- end
289
- end
290
-
291
- def attribute_protected?(name)
292
- presentable = presentable_for(name)
293
- return false unless presentable
294
- flat_attribute = {flatten_attribute_name(name, presentable) => ''} #remove_att... normally takes a hash, so we use a ''
295
- presented[presentable].new.send(:remove_attributes_protected_from_mass_assignment, flat_attribute).empty?
296
- end
297
-
298
- def run_callbacks_with_halt(callback)
299
- run_callbacks(callback) { |result, object| result == false }
230
+
231
+ def presented_instances
232
+ presented.keys.map { |key| send(key) }
233
+ end
234
+
235
+ def delegate_message(method_name, *args, &block)
236
+ presentable = presentable_for(method_name)
237
+ send(presentable).send(flatten_attribute_name(method_name, presentable), *args, &block)
238
+ end
239
+
240
+ def presentable_for(method_name)
241
+ presented.keys.sort_by { |k| k.to_s.size }.reverse.detect do |type|
242
+ method_name.to_s.starts_with?(attribute_prefix(type))
300
243
  end
301
-
302
- def remove_attributes_protected_from_mass_assignment(attributes)
303
- if self.class.accessible_attributes.nil? && self.class.protected_attributes.nil?
304
- attributes
305
- elsif self.class.protected_attributes.nil?
306
- attributes.reject { |key, value| !self.class.accessible_attributes.include?(key.gsub(/\(.+/, ""))}
307
- elsif self.class.accessible_attributes.nil?
308
- attributes.reject { |key, value| self.class.protected_attributes.include?(key.gsub(/\(.+/,""))}
244
+ end
245
+
246
+ def presented_attribute?(method_name)
247
+ p = presentable_for(method_name)
248
+ !p.nil? && send(p).respond_to?(flatten_attribute_name(method_name,p))
249
+ end
250
+
251
+ def flatten_attribute_name(name, type)
252
+ name.to_s.gsub(/^#{attribute_prefix(type)}/, '')
253
+ end
254
+
255
+ def attribute_prefix(type)
256
+ "#{type}_"
257
+ end
258
+
259
+ def merge_errors(presented_inst, type)
260
+ presented_inst.errors.each do |att,msg|
261
+ if att == :base
262
+ errors.add(type, msg)
309
263
  else
310
- raise "Declare either attr_protected or attr_accessible for #{self.class}, but not both."
264
+ errors.add(attribute_prefix(type)+att.to_s, msg)
311
265
  end
312
266
  end
313
-
267
+ end
268
+
269
+ def attribute_protected?(name)
270
+ presentable = presentable_for(name)
271
+ return false unless presentable
272
+ flat_attribute = {flatten_attribute_name(name, presentable) => ''} #remove_att... normally takes a hash, so we use a ''
273
+ presented[presentable].new.send(:sanitize_for_mass_assignment, flat_attribute).empty?
274
+ end
275
+
314
276
  end
315
277
  end
@@ -1,9 +1,10 @@
1
1
  module ActivePresenter
2
2
  module VERSION
3
- MAJOR = 1
4
- MINOR = 4
3
+ MAJOR = 2
4
+ MINOR = 0
5
5
  TINY = 0
6
-
7
- STRING = [MAJOR, MINOR, TINY].join('.')
6
+ EXTRA = "a"
7
+
8
+ STRING = [MAJOR, MINOR, TINY].join('.') + EXTRA
8
9
  end
9
10
  end
data/lib/tasks/gem.rake CHANGED
@@ -1,4 +1,4 @@
1
- require 'rake/gempackagetask'
1
+ require 'rubygems/package_task'
2
2
 
3
3
  task :clean => :clobber_package
4
4
 
@@ -21,7 +21,7 @@ spec = Gem::Specification.new do |s|
21
21
  s.require_path = "lib"
22
22
  end
23
23
 
24
- Rake::GemPackageTask.new(spec) do |p|
24
+ Gem::PackageTask.new(spec) do |p|
25
25
  p.gem_spec = spec
26
26
  end
27
27
 
data/test/base_test.rb CHANGED
@@ -45,34 +45,34 @@ Expectations do
45
45
  expect SignupPresenter.new.not.to.be.valid?
46
46
  expect SignupPresenter.new(:user => User.new(hash_for_user)).to.be.valid?
47
47
 
48
- expect ActiveRecord::Errors do
48
+ expect ActiveModel::Errors do
49
49
  s = SignupPresenter.new
50
50
  s.valid?
51
51
  s.errors
52
52
  end
53
53
 
54
- expect ActiveRecord::Errors do
54
+ expect ActiveModel::Errors do
55
55
  s = SignupPresenter.new
56
56
  s.valid?
57
57
  s.user_errors
58
58
  end
59
59
 
60
- expect ActiveRecord::Errors do
60
+ expect ActiveModel::Errors do
61
61
  s = SignupPresenter.new
62
62
  s.valid?
63
63
  s.account_errors
64
64
  end
65
65
 
66
- expect String do
66
+ expect ["can't be blank"] do
67
67
  s = SignupPresenter.new
68
68
  s.valid?
69
- s.errors.on(:user_login)
69
+ s.errors[:user_login]
70
70
  end
71
71
 
72
- expect "can't be blank" do
72
+ expect ["can't be blank"] do
73
73
  s = SignupPresenter.new
74
74
  s.valid?
75
- s.errors.on(:user_login)
75
+ s.errors[:user_login]
76
76
  end
77
77
 
78
78
  expect ["User Password can't be blank"] do
@@ -81,13 +81,13 @@ Expectations do
81
81
  s.errors.full_messages
82
82
  end
83
83
 
84
- expect 'c4N n07 83 8L4nK' do
84
+ expect ['c4N n07 83 8L4nK'] do
85
85
  old_locale = I18n.locale
86
86
  I18n.locale = '1337'
87
87
 
88
88
  s = SignupPresenter.new(:user_login => nil)
89
89
  s.valid?
90
- message = s.errors.on(:user_login)
90
+ message = s.errors[:user_login]
91
91
 
92
92
  I18n.locale = old_locale
93
93
 
@@ -143,7 +143,7 @@ Expectations do
143
143
  end
144
144
 
145
145
  expect Account.any_instance.to.receive(:save!) do
146
- User.any_instance.stubs(:save!)
146
+ User.any_instance.stubs(:save!).returns(true)
147
147
  s = SignupPresenter.new(:user_login => "da", :user_password => "seekrit")
148
148
  s.save!
149
149
  end
@@ -173,7 +173,7 @@ Expectations do
173
173
  s.update_attributes :user_login => 'Something Different'
174
174
  s.user_login
175
175
  end
176
-
176
+
177
177
  # Multiparameter assignment
178
178
  expect Time.parse('March 27 1980 9:30:59 am') do
179
179
  s = SignupPresenter.new
@@ -192,23 +192,23 @@ Expectations do
192
192
  s = SignupPresenter.new
193
193
  s.attributes = nil
194
194
  end
195
-
195
+
196
196
  # this is a regression test to make sure that _title is working. we had a weird conflict with using String#delete
197
197
  expect 'something' do
198
198
  s = SignupPresenter.new :account_title => 'something'
199
199
  s.account_title
200
200
  end
201
201
 
202
- expect String do
202
+ expect ["can't be blank"] do
203
203
  s = SignupPresenter.new
204
204
  s.save
205
- s.errors.on(:user_login)
205
+ s.errors[:user_login]
206
206
  end
207
207
 
208
- expect String do
208
+ expect ["can't be blank"] do
209
209
  s = SignupPresenter.new
210
210
  s.save! rescue
211
- s.errors.on(:user_login)
211
+ s.errors[:user_login]
212
212
  end
213
213
 
214
214
  expect 'Login' do
@@ -219,7 +219,7 @@ Expectations do
219
219
  expect SignupPresenter do
220
220
  SignupPresenter.new(nil)
221
221
  end
222
-
222
+
223
223
  expect EndingWithSPresenter.new.address.not.to.be.nil?
224
224
 
225
225
  # this should act as ActiveRecord models do
@@ -237,25 +237,25 @@ Expectations do
237
237
  presenter.save!
238
238
  end.id
239
239
  end
240
-
240
+
241
241
  expect CantSavePresenter.new.not.to.be.save # it won't save because the filter chain will halt
242
-
242
+
243
243
  expect ActiveRecord::RecordNotSaved do
244
244
  CantSavePresenter.new.save!
245
245
  end
246
-
246
+
247
247
  expect 'Some Street' do
248
248
  p = AfterSavePresenter.new
249
249
  p.save
250
250
  p.address.street
251
251
  end
252
-
252
+
253
253
  expect 'Some Street' do
254
254
  p = AfterSavePresenter.new
255
255
  p.save!
256
256
  p.address.street
257
257
  end
258
-
258
+
259
259
  expect SamePrefixPresenter.new.to.be.respond_to?(:account_title)
260
260
  expect SamePrefixPresenter.new.to.be.respond_to?(:account_info_info)
261
261
 
@@ -305,7 +305,7 @@ Expectations do
305
305
  end.steps
306
306
  end
307
307
 
308
- expect ActiveRecord::Errors.any_instance.to.receive(:clear).twice do
308
+ expect ActiveModel::Errors.any_instance.to.receive(:clear) do
309
309
  CallbackCantValidatePresenter.new.valid?
310
310
  end
311
311
 
@@ -329,34 +329,33 @@ Expectations do
329
329
  expect Address do
330
330
  PresenterWithTwoAddresses.new.secondary_address
331
331
  end
332
-
332
+
333
333
  expect "123 awesome st" do
334
334
  p = PresenterWithTwoAddresses.new(:secondary_address_street => "123 awesome st")
335
335
  p.save
336
336
  p.secondary_address_street
337
337
  end
338
-
338
+
339
339
  # attr_protected
340
340
  expect "" do
341
341
  p = SignupPresenter.new(:account_secret => 'swordfish')
342
342
  p.account.secret
343
343
  end
344
-
344
+
345
345
  expect "comment" do
346
346
  p = HistoricalPresenter.new(:history_comment => 'comment', :user => User.new(hash_for_user))
347
347
  p.save
348
348
  p.history_comment
349
349
  end
350
-
350
+
351
351
  expect false do
352
352
  SignupPresenter.new.changed?
353
353
  end
354
-
354
+
355
355
  expect true do
356
356
  p = SignupPresenter.new(:user => User.new(hash_for_user))
357
357
  p.save
358
358
  p.user_login = 'something_else'
359
359
  p.changed?
360
360
  end
361
-
362
361
  end
data/test/lint_test.rb ADDED
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__)+'/test_helper'
2
+ require 'test/unit'
3
+
4
+ class LintTest < ActiveModel::TestCase
5
+ include ActiveModel::Lint::Tests
6
+
7
+ def setup
8
+ @model = SignupPresenter.new
9
+ end
10
+ end
data/test/test_helper.rb CHANGED
@@ -1,4 +1,3 @@
1
- require File.dirname(__FILE__)+'/../lib/active_presenter' unless defined?(ActivePresenter)
2
1
  require 'expectations'
3
2
  require 'logger'
4
3
 
@@ -51,7 +50,6 @@ ActiveRecord::Schema.define(:version => 0) do
51
50
  t.string :action, :default => ''
52
51
  t.datetime :created_at
53
52
  end
54
-
55
53
  end
56
54
 
57
55
  class User < ActiveRecord::Base
@@ -64,12 +62,12 @@ class User < ActiveRecord::Base
64
62
  if password.blank?
65
63
  attribute_name = I18n.t(:password, {:default => "Password", :scope => [:activerecord, :attributes, :user]})
66
64
  error_message = I18n.t(:blank, {:default => "can't be blank", :scope => [:activerecord, :errors, :messages]})
67
- errors.add_to_base("#{attribute_name} #{error_message}")
65
+ errors[:base] << ("#{attribute_name} #{error_message}")
68
66
  end
69
67
  end
70
68
  end
71
- class Account < ActiveRecord::Base; end
72
- class History < ActiveRecord::Base; end
69
+ class Account < ActiveRecord::Base ;end
70
+ class History < ActiveRecord::Base ;end
73
71
  class Address < ActiveRecord::Base; end
74
72
  class AccountInfo < ActiveRecord::Base; end
75
73
 
@@ -86,11 +84,6 @@ class EndingWithSPresenter < ActivePresenter::Base
86
84
  presents :address
87
85
  end
88
86
 
89
- class HistoricalPresenter < ActivePresenter::Base
90
- presents :user, :history
91
- attr_accessible :history_comment
92
- end
93
-
94
87
  class CantSavePresenter < ActivePresenter::Base
95
88
  presents :address
96
89
 
@@ -103,7 +96,7 @@ class SignupNoAccountPresenter < ActivePresenter::Base
103
96
  presents :account, :user
104
97
 
105
98
  def save?(key, instance)
106
- key != :account
99
+ key.to_sym != :account
107
100
  end
108
101
  end
109
102
 
@@ -212,7 +205,16 @@ class CallbackCantValidatePresenter < ActivePresenter::Base
212
205
  end
213
206
  end
214
207
 
208
+ class HistoricalPresenter < ActivePresenter::Base
209
+ presents :user, :history
210
+ attr_accessible :history_comment
211
+ end
212
+
215
213
  def hash_for_user(opts = {})
216
214
  {:login => 'jane', :password => 'seekrit' }.merge(opts)
217
215
  end
218
216
 
217
+ def returning(value)
218
+ yield(value)
219
+ value
220
+ end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_presenter
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
5
- prerelease:
4
+ hash: 10
5
+ prerelease: 5
6
6
  segments:
7
- - 1
8
- - 4
7
+ - 2
9
8
  - 0
10
- version: 1.4.0
9
+ - 0
10
+ - a
11
+ version: 2.0.0a
11
12
  platform: ruby
12
13
  authors:
13
14
  - James Golick & Daniel Haran
@@ -15,7 +16,8 @@ autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-09-23 00:00:00 Z
19
+ date: 2011-09-26 00:00:00 -07:00
20
+ default_executable:
19
21
  dependencies: []
20
22
 
21
23
  description: ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)
@@ -36,7 +38,9 @@ files:
36
38
  - lib/tasks/doc.rake
37
39
  - lib/tasks/gem.rake
38
40
  - test/base_test.rb
41
+ - test/lint_test.rb
39
42
  - test/test_helper.rb
43
+ has_rdoc: true
40
44
  homepage: http://jamesgolick.com/active_presenter
41
45
  licenses: []
42
46
 
@@ -59,16 +63,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
59
63
  required_rubygems_version: !ruby/object:Gem::Requirement
60
64
  none: false
61
65
  requirements:
62
- - - ">="
66
+ - - ">"
63
67
  - !ruby/object:Gem::Version
64
- hash: 3
68
+ hash: 25
65
69
  segments:
66
- - 0
67
- version: "0"
70
+ - 1
71
+ - 3
72
+ - 1
73
+ version: 1.3.1
68
74
  requirements: []
69
75
 
70
76
  rubyforge_project: active_presenter
71
- rubygems_version: 1.8.10
77
+ rubygems_version: 1.3.9.3
72
78
  signing_key:
73
79
  specification_version: 3
74
80
  summary: ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)