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.
- data/lib/active_presenter.rb +1 -1
- data/lib/active_presenter/base.rb +47 -2
- data/lib/active_presenter/version.rb +2 -2
- data/test/base_test.rb +25 -1
- data/test/test_helper.rb +17 -1
- metadata +19 -5
data/lib/active_presenter.rb
CHANGED
@@ -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
|
data/test/base_test.rb
CHANGED
@@ -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
|
data/test/test_helper.rb
CHANGED
@@ -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
|
-
|
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:
|
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.
|
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)
|