active_presenter 1.2.1 → 1.3.0

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.
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- require 'activerecord'
2
+ require 'active_record'
3
3
  Dir.glob(File.dirname(__FILE__)+'/active_presenter/**/*.rb').each { |l| require l }
4
4
 
5
5
  module ActivePresenter
@@ -6,6 +6,7 @@ module ActivePresenter
6
6
  define_callbacks :before_validation, :before_save, :after_save
7
7
 
8
8
  class_inheritable_accessor :presented
9
+ class_inheritable_accessor :attr_protected, :attr_accessible
9
10
  self.presented = {}
10
11
 
11
12
  # Indicates which models are to be presented by this presenter.
@@ -67,6 +68,30 @@ module ActivePresenter
67
68
  I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options))
68
69
  end
69
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
+
70
95
  # 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:
71
96
  #
72
97
  # 1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft')
@@ -96,8 +121,10 @@ module ActivePresenter
96
121
  #
97
122
  def attributes=(attrs)
98
123
  return if attrs.nil?
99
-
124
+
125
+ attrs = attrs.stringify_keys
100
126
  multi_parameter_attributes = {}
127
+ attrs = remove_attributes_protected_from_mass_assignment(attrs)
101
128
 
102
129
  attrs.each do |k,v|
103
130
  if (base_attribute = k.to_s.split("(").first) != k.to_s
@@ -148,6 +175,11 @@ module ActivePresenter
148
175
  end
149
176
  end
150
177
 
178
+ # Do any of the attributes have unsaved changes?
179
+ def changed?
180
+ presented_instances.map(&:changed?).any?
181
+ end
182
+
151
183
  # Save all of the presentables, wrapped in a transaction.
152
184
  #
153
185
  # Returns true or false based on success.
@@ -212,7 +244,7 @@ module ActivePresenter
212
244
  def id # :nodoc:
213
245
  nil
214
246
  end
215
-
247
+
216
248
  def new_record?
217
249
  true
218
250
  end
@@ -266,5 +298,18 @@ module ActivePresenter
266
298
  def run_callbacks_with_halt(callback)
267
299
  run_callbacks(callback) { |result, object| result == false }
268
300
  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(/\(.+/,""))}
309
+ else
310
+ raise "Declare either attr_protected or attr_accessible for #{self.class}, but not both."
311
+ end
312
+ end
313
+
269
314
  end
270
315
  end
@@ -1,8 +1,8 @@
1
1
  module ActivePresenter
2
2
  module VERSION
3
3
  MAJOR = 1
4
- MINOR = 2
5
- TINY = 1
4
+ MINOR = 3
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -305,7 +305,7 @@ Expectations do
305
305
  end.steps
306
306
  end
307
307
 
308
- expect ActiveRecord::Errors.any_instance.to.receive(:clear) do
308
+ expect ActiveRecord::Errors.any_instance.to.receive(:clear).twice do
309
309
  CallbackCantValidatePresenter.new.valid?
310
310
  end
311
311
 
@@ -335,4 +335,28 @@ Expectations do
335
335
  p.save
336
336
  p.secondary_address_street
337
337
  end
338
+
339
+ # attr_protected
340
+ expect "" do
341
+ p = SignupPresenter.new(:account_secret => 'swordfish')
342
+ p.account.secret
343
+ end
344
+
345
+ expect "comment" do
346
+ p = HistoricalPresenter.new(:history_comment => 'comment', :user => User.new(hash_for_user))
347
+ p.save
348
+ p.history_comment
349
+ end
350
+
351
+ expect false do
352
+ SignupPresenter.new.changed?
353
+ end
354
+
355
+ expect true do
356
+ p = SignupPresenter.new(:user => User.new(hash_for_user))
357
+ p.save
358
+ p.user_login = 'something_else'
359
+ p.changed?
360
+ end
361
+
338
362
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__)+'/../lib/active_presenter'
1
+ require File.dirname(__FILE__)+'/../lib/active_presenter' unless defined?(ActivePresenter)
2
2
  require 'expectations'
3
3
  require 'logger'
4
4
 
@@ -34,6 +34,7 @@ ActiveRecord::Schema.define(:version => 0) do
34
34
  create_table :accounts do |t|
35
35
  t.string :subdomain, :default => ''
36
36
  t.string :title, :default => ''
37
+ t.string :secret, :default => ''
37
38
  end
38
39
 
39
40
  create_table :addresses do |t|
@@ -43,6 +44,14 @@ ActiveRecord::Schema.define(:version => 0) do
43
44
  create_table :account_infos do |t|
44
45
  t.string :info
45
46
  end
47
+
48
+ create_table :histories do |t|
49
+ t.integer :user_id
50
+ t.string :comment, :default => ''
51
+ t.string :action, :default => ''
52
+ t.datetime :created_at
53
+ end
54
+
46
55
  end
47
56
 
48
57
  class User < ActiveRecord::Base
@@ -60,6 +69,7 @@ class User < ActiveRecord::Base
60
69
  end
61
70
  end
62
71
  class Account < ActiveRecord::Base; end
72
+ class History < ActiveRecord::Base; end
63
73
  class Address < ActiveRecord::Base; end
64
74
  class AccountInfo < ActiveRecord::Base; end
65
75
 
@@ -69,12 +79,18 @@ end
69
79
 
70
80
  class SignupPresenter < ActivePresenter::Base
71
81
  presents :account, :user
82
+ attr_protected :account_secret
72
83
  end
73
84
 
74
85
  class EndingWithSPresenter < ActivePresenter::Base
75
86
  presents :address
76
87
  end
77
88
 
89
+ class HistoricalPresenter < ActivePresenter::Base
90
+ presents :user, :history
91
+ attr_accessible :history_comment
92
+ end
93
+
78
94
  class CantSavePresenter < ActivePresenter::Base
79
95
  presents :address
80
96
 
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 3
9
+ - 0
10
+ version: 1.3.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - James Golick & Daniel Haran
@@ -9,7 +15,7 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2009-12-17 00:00:00 -08:00
18
+ date: 2010-10-19 00:00:00 -07:00
13
19
  default_executable:
14
20
  dependencies: []
15
21
 
@@ -42,21 +48,29 @@ rdoc_options: []
42
48
  require_paths:
43
49
  - lib
44
50
  required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
45
52
  requirements:
46
53
  - - ">="
47
54
  - !ruby/object:Gem::Version
55
+ hash: 61
56
+ segments:
57
+ - 1
58
+ - 8
59
+ - 5
48
60
  version: 1.8.5
49
- version:
50
61
  required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
51
63
  requirements:
52
64
  - - ">="
53
65
  - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
54
69
  version: "0"
55
- version:
56
70
  requirements: []
57
71
 
58
72
  rubyforge_project: active_presenter
59
- rubygems_version: 1.3.5
73
+ rubygems_version: 1.3.7
60
74
  signing_key:
61
75
  specification_version: 3
62
76
  summary: ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)