active_presenter 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|