hobo 0.8.3 → 0.8.4
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/CHANGES.txt +330 -0
- data/Manifest +12 -4
- data/Rakefile +4 -6
- data/dryml_generators/rapid/cards.dryml.erb +5 -1
- data/dryml_generators/rapid/forms.dryml.erb +8 -10
- data/dryml_generators/rapid/pages.dryml.erb +65 -36
- data/hobo.gemspec +28 -15
- data/lib/active_record/association_collection.rb +3 -22
- data/lib/hobo.rb +25 -258
- data/lib/hobo/accessible_associations.rb +131 -0
- data/lib/hobo/authentication_support.rb +15 -9
- data/lib/hobo/composite_model.rb +1 -1
- data/lib/hobo/controller.rb +7 -8
- data/lib/hobo/dryml.rb +9 -10
- data/lib/hobo/dryml/dryml_builder.rb +7 -1
- data/lib/hobo/dryml/dryml_doc.rb +161 -0
- data/lib/hobo/dryml/dryml_generator.rb +18 -9
- data/lib/hobo/dryml/part_context.rb +76 -42
- data/lib/hobo/dryml/tag_parameters.rb +1 -0
- data/lib/hobo/dryml/taglib.rb +2 -1
- data/lib/hobo/dryml/template.rb +39 -29
- data/lib/hobo/dryml/template_environment.rb +79 -37
- data/lib/hobo/dryml/template_handler.rb +66 -21
- data/lib/hobo/guest.rb +2 -10
- data/lib/hobo/hobo_helper.rb +125 -53
- data/lib/hobo/include_in_save.rb +0 -1
- data/lib/hobo/lifecycles.rb +54 -24
- data/lib/hobo/lifecycles/actions.rb +95 -31
- data/lib/hobo/lifecycles/creator.rb +18 -23
- data/lib/hobo/lifecycles/lifecycle.rb +86 -62
- data/lib/hobo/lifecycles/state.rb +1 -2
- data/lib/hobo/lifecycles/transition.rb +22 -28
- data/lib/hobo/model.rb +64 -176
- data/lib/hobo/model_controller.rb +67 -54
- data/lib/hobo/model_router.rb +5 -2
- data/lib/hobo/permissions.rb +397 -0
- data/lib/hobo/permissions/associations.rb +167 -0
- data/lib/hobo/scopes.rb +15 -38
- data/lib/hobo/scopes/association_proxy_extensions.rb +15 -5
- data/lib/hobo/scopes/automatic_scopes.rb +43 -18
- data/lib/hobo/scopes/named_scope_extensions.rb +2 -2
- data/lib/hobo/user.rb +10 -4
- data/lib/hobo/user_controller.rb +6 -5
- data/lib/hobo/view_hints.rb +58 -0
- data/rails_generators/hobo/hobo_generator.rb +7 -3
- data/rails_generators/hobo/templates/guest.rb +1 -13
- data/rails_generators/hobo_front_controller/hobo_front_controller_generator.rb +1 -1
- data/rails_generators/hobo_model/hobo_model_generator.rb +4 -2
- data/rails_generators/hobo_model/templates/hints.rb +4 -0
- data/rails_generators/hobo_model/templates/model.rb +8 -8
- data/rails_generators/hobo_model_controller/hobo_model_controller_generator.rb +10 -0
- data/rails_generators/hobo_model_controller/templates/controller.rb +1 -1
- data/rails_generators/hobo_rapid/templates/hobo-rapid.js +91 -56
- data/rails_generators/hobo_rapid/templates/lowpro.js +15 -15
- data/rails_generators/hobo_rapid/templates/reset.css +36 -3
- data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +13 -17
- data/rails_generators/hobo_user_controller/templates/controller.rb +1 -1
- data/rails_generators/hobo_user_model/templates/model.rb +18 -16
- data/taglibs/core.dryml +60 -18
- data/taglibs/rapid.dryml +8 -401
- data/taglibs/rapid_core.dryml +586 -0
- data/taglibs/rapid_document_tags.dryml +28 -10
- data/taglibs/rapid_editing.dryml +92 -55
- data/taglibs/rapid_forms.dryml +406 -87
- data/taglibs/rapid_generics.dryml +1 -1
- data/taglibs/rapid_navigation.dryml +2 -1
- data/taglibs/rapid_pages.dryml +7 -16
- data/taglibs/rapid_plus.dryml +39 -14
- data/taglibs/rapid_support.dryml +1 -1
- data/taglibs/rapid_user_pages.dryml +14 -4
- data/tasks/{generate_tag_reference.rb → generate_tag_reference.rake} +49 -18
- data/tasks/hobo_tasks.rake +16 -0
- data/test/permissions/models/models.rb +134 -0
- data/test/permissions/models/schema.rb +55 -0
- data/test/permissions/models/test.sqlite3 +0 -0
- data/test/permissions/test_permissions.rb +436 -0
- metadata +27 -14
- data/lib/hobo/mass_assignment.rb +0 -64
- data/rails_generators/hobo/templates/patch_routing.rb +0 -30
- data/uninstall.rb +0 -1
data/lib/hobo.rb
CHANGED
@@ -7,26 +7,18 @@ rescue MissingSourceFile
|
|
7
7
|
# OK, Hobo won't do pagination then
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
ActiveSupport::Dependencies.load_paths |= [ File.dirname(__FILE__)]
|
11
11
|
|
12
12
|
# Hobo can be installed in /vendor/hobo, /vendor/plugins/hobo, vendor/plugins/hobo/hobo, etc.
|
13
13
|
::HOBO_ROOT = File.expand_path(File.dirname(__FILE__) + "/..")
|
14
14
|
|
15
|
-
|
16
|
-
# Modules that must *not* be auto-reloaded by activesupport
|
17
|
-
# (explicitly requiring them means they're never unloaded)
|
18
|
-
require 'hobo/model_router'
|
19
|
-
require 'hobo/undefined'
|
20
|
-
require 'hobo/user'
|
21
|
-
require 'hobo/dryml'
|
22
|
-
require 'hobo/dryml/template'
|
23
|
-
require 'hobo/dryml/dryml_generator'
|
24
|
-
|
25
15
|
class HoboError < RuntimeError; end
|
26
16
|
|
27
17
|
module Hobo
|
28
18
|
|
29
|
-
VERSION = "0.8.
|
19
|
+
VERSION = "0.8.4"
|
20
|
+
|
21
|
+
class PermissionDeniedError < RuntimeError; end
|
30
22
|
|
31
23
|
class RawJs < String; end
|
32
24
|
|
@@ -49,43 +41,8 @@ module Hobo
|
|
49
41
|
end
|
50
42
|
|
51
43
|
|
52
|
-
def
|
53
|
-
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def user_model
|
58
|
-
@user_model && @user_model.constantize
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
def object_from_dom_id(dom_id)
|
63
|
-
return nil if dom_id == 'nil'
|
64
|
-
|
65
|
-
_, name, id, attr = *dom_id.match(/^([a-z_]+)(?:_([0-9]+(?:_[0-9]+)*))?(?:_([a-z_]+))?$/)
|
66
|
-
raise ArgumentError.new("invalid model-reference in dom id") unless name
|
67
|
-
if name
|
68
|
-
model_class = name.camelize.constantize rescue (raise ArgumentError.new("no such class in dom-id"))
|
69
|
-
return nil unless model_class
|
70
|
-
|
71
|
-
if id
|
72
|
-
obj = if false and attr and model_class.reflections[attr.to_sym].klass.superclass == ActiveRecord::Base
|
73
|
-
# DISABLED - Eager loading is broken - doesn't support ordering
|
74
|
-
# http://dev.rubyonrails.org/ticket/3438
|
75
|
-
# Don't do this for STI subclasses - it breaks!
|
76
|
-
model_class.find(id, :include => attr)
|
77
|
-
else
|
78
|
-
model_class.find(id)
|
79
|
-
end
|
80
|
-
attr ? obj.send(attr) : obj
|
81
|
-
else
|
82
|
-
model_class
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def dom_id(obj, attr=nil)
|
88
|
-
attr ? "#{obj.typed_id}_#{attr}" : obj.typed_id
|
44
|
+
def typed_id(obj, attr=nil)
|
45
|
+
attr ? "#{obj.typed_id}:#{attr}" : obj.typed_id
|
89
46
|
end
|
90
47
|
|
91
48
|
def find_by_search(query, search_targets=nil)
|
@@ -130,16 +87,6 @@ module Hobo
|
|
130
87
|
end
|
131
88
|
|
132
89
|
|
133
|
-
def can_create_in_association?(array_or_reflection)
|
134
|
-
refl =
|
135
|
-
(array_or_reflection.is_a?(ActiveRecord::Reflection::AssociationReflection) and array_or_reflection) or
|
136
|
-
array_or_reflection.try.proxy_reflection or
|
137
|
-
(origin = array_or_reflection.try.origin and origin.send(array_or_reflection.origin_attribute).try.proxy_reflection)
|
138
|
-
|
139
|
-
refl && refl.macro == :has_many && (!refl.through_reflection) && (!refl.options[:conditions])
|
140
|
-
end
|
141
|
-
|
142
|
-
|
143
90
|
def get_field(object, field)
|
144
91
|
return nil if object.nil?
|
145
92
|
field_str = field.to_s
|
@@ -168,147 +115,6 @@ module Hobo
|
|
168
115
|
end
|
169
116
|
|
170
117
|
|
171
|
-
# --- Permissions --- #
|
172
|
-
|
173
|
-
|
174
|
-
def can_create?(person, object)
|
175
|
-
if object.is_a?(Class) and object < ActiveRecord::Base
|
176
|
-
object = object.new
|
177
|
-
object.set_creator(person)
|
178
|
-
elsif (refl = object.try.proxy_reflection) && refl.macro == :has_many
|
179
|
-
if Hobo.simple_has_many_association?(object)
|
180
|
-
object = object.new
|
181
|
-
object.set_creator(person)
|
182
|
-
else
|
183
|
-
return false
|
184
|
-
end
|
185
|
-
end
|
186
|
-
check_permission(:create, person, object)
|
187
|
-
end
|
188
|
-
|
189
|
-
|
190
|
-
def can_update?(person, object, new)
|
191
|
-
check_permission(:update, person, object, new)
|
192
|
-
end
|
193
|
-
|
194
|
-
|
195
|
-
def can_edit?(person, object, field)
|
196
|
-
return true if object.try.exempt_from_edit_checks?
|
197
|
-
# Can't view implies can't edit
|
198
|
-
return false if !can_view?(person, object, field)
|
199
|
-
|
200
|
-
if field.nil?
|
201
|
-
if object.has_hobo_method?(:editable_by?)
|
202
|
-
object.editable_by?(person)
|
203
|
-
elsif object.has_hobo_method?(:updatable_by?)
|
204
|
-
object.updatable_by?(person, nil)
|
205
|
-
else
|
206
|
-
false
|
207
|
-
end
|
208
|
-
|
209
|
-
else
|
210
|
-
attribute_name = field.to_s.sub /\?$/, ''
|
211
|
-
return false if !object.respond_to?("#{attribute_name}=")
|
212
|
-
|
213
|
-
refl = object.class.reflections[field.to_sym] if object.is_a?(ActiveRecord::Base)
|
214
|
-
|
215
|
-
# has_one and polymorphic associations are not editable (for now)
|
216
|
-
return false if refl and (refl.options[:polymorphic] or refl.macro == :has_one)
|
217
|
-
|
218
|
-
if object.has_hobo_method?("#{field}_editable_by?")
|
219
|
-
object.send("#{field}_editable_by?", person)
|
220
|
-
elsif object.has_hobo_method?(:editable_by?)
|
221
|
-
check_permission(:edit, person, object)
|
222
|
-
elsif refl._?.macro == :has_many
|
223
|
-
# The below technique to figure out edit permission based on
|
224
|
-
# update permission doesn't work for has_many associations
|
225
|
-
false
|
226
|
-
else
|
227
|
-
# Fake an edit test by setting the field in question to
|
228
|
-
# Hobo::Undefined and then testing for update/create permission
|
229
|
-
current = object.send(field)
|
230
|
-
new = object.duplicate
|
231
|
-
|
232
|
-
edit_test_value = if current == true
|
233
|
-
false
|
234
|
-
elsif current == false || (current.nil? && object.class.try.attr_type(field) == Hobo::Boolean)
|
235
|
-
true
|
236
|
-
elsif refl and refl.macro == :belongs_to
|
237
|
-
Hobo::Undefined.new(refl.klass)
|
238
|
-
else
|
239
|
-
Hobo::Undefined.new
|
240
|
-
end
|
241
|
-
|
242
|
-
new.metaclass.send(:define_method, attribute_name) { edit_test_value }
|
243
|
-
|
244
|
-
begin
|
245
|
-
if object.new_record?
|
246
|
-
check_permission(:create, person, new)
|
247
|
-
else
|
248
|
-
check_permission(:update, person, object, new)
|
249
|
-
end
|
250
|
-
rescue Hobo::UndefinedAccessError
|
251
|
-
# The permission method performed some test on the undefined value
|
252
|
-
# so this field is not editable
|
253
|
-
false
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
|
260
|
-
def can_delete?(person, object)
|
261
|
-
check_permission(:delete, person, object)
|
262
|
-
end
|
263
|
-
|
264
|
-
|
265
|
-
# can_view? has special behaviour if it's passed a class or an
|
266
|
-
# association-proxy -- it instantiates the class, or creates a new
|
267
|
-
# instance "in" the association, and tests the permission of this
|
268
|
-
# object. This means the permission methods in models can't rely
|
269
|
-
# on the instance being properly initialised. But it's important
|
270
|
-
# that it works like this because, in the case of an association
|
271
|
-
# proxy, we don't want to loose the information that the object
|
272
|
-
# belongs_to the proxy owner.
|
273
|
-
def can_view?(person, object, field=nil)
|
274
|
-
# Field can be a dot separated path
|
275
|
-
if field && field.is_a?(String) && (path = field.split(".")).length > 1
|
276
|
-
_, _, object = get_field_path(object, path[0..-2])
|
277
|
-
field = path.last
|
278
|
-
end
|
279
|
-
|
280
|
-
if field
|
281
|
-
field = field.to_sym if field.is_a? String
|
282
|
-
return false if object.class.respond_to?(:never_show?) && object.class.never_show?(field)
|
283
|
-
else
|
284
|
-
# Special support for classes (can view instances?)
|
285
|
-
if object.is_a?(Class) and object < Hobo::Model
|
286
|
-
object = object.new
|
287
|
-
elsif Hobo.simple_has_many_association?(object)
|
288
|
-
object = object.new
|
289
|
-
end
|
290
|
-
end
|
291
|
-
viewable = check_permission(:view, person, object, field)
|
292
|
-
if viewable and field and
|
293
|
-
( (field_val = get_field(object, field)).is_a?(Hobo::Model) or field_val.is_a?(Array) )
|
294
|
-
# also ask the current value if it is viewable
|
295
|
-
can_view?(person, field_val)
|
296
|
-
else
|
297
|
-
viewable
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
|
302
|
-
def can_call?(person, object, method)
|
303
|
-
return true if person.has_hobo_method?(:super_user?) && person.super_user?
|
304
|
-
|
305
|
-
m = "#{method}_callable_by?"
|
306
|
-
object.has_hobo_method?(m) && object.send(m, person)
|
307
|
-
end
|
308
|
-
|
309
|
-
# --- end permissions -- #
|
310
|
-
|
311
|
-
|
312
118
|
def static_tags
|
313
119
|
@static_tags ||= begin
|
314
120
|
path = if FileTest.exists?("#{RAILS_ROOT}/config/dryml_static_tags.txt")
|
@@ -328,58 +134,36 @@ module Hobo
|
|
328
134
|
@subsites ||= Dir["#{RAILS_ROOT}/app/controllers/*"].map { |f| File.basename(f) if File.directory?(f) }.compact
|
329
135
|
end
|
330
136
|
|
331
|
-
|
332
|
-
private
|
333
|
-
|
334
|
-
|
335
|
-
def check_permission(permission, person, object, *args)
|
336
|
-
return true if person.has_hobo_method?(:super_user?) and person.super_user?
|
337
|
-
|
338
|
-
return true if permission == :view && !(object.is_a?(ActiveRecord::Base) || object.is_a?(Hobo::CompositeModel))
|
339
|
-
|
340
|
-
obj_method = case permission
|
341
|
-
when :create; :creatable_by?
|
342
|
-
when :update; :updatable_by?
|
343
|
-
when :delete; :deletable_by?
|
344
|
-
when :edit; :editable_by?
|
345
|
-
when :view; :viewable_by?
|
346
|
-
end
|
347
|
-
p = if (obj_method.respond_to?(:has_hobo_method) ? object.has_hobo_method?(obj_method) : object.respond_to?(obj_method))
|
348
|
-
begin
|
349
|
-
object.send(obj_method, person, *args)
|
350
|
-
rescue Hobo::UndefinedAccessError
|
351
|
-
false
|
352
|
-
end
|
353
|
-
elsif object.class.respond_to?(obj_method)
|
354
|
-
object.class.send(obj_method, person, *args)
|
355
|
-
elsif !object.is_a?(Class) # No user fallback for class-level permissions
|
356
|
-
person_method = "can_#{permission}?".to_sym
|
357
|
-
if person.has_hobo_method?(person_method)
|
358
|
-
person.send(person_method, object, *args)
|
359
|
-
else
|
360
|
-
# The object does not define permissions - you can only view it
|
361
|
-
permission == :view
|
362
|
-
end
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
137
|
public
|
367
138
|
|
368
139
|
def enable
|
369
|
-
# Rails monkey patches
|
370
|
-
require 'active_record/association_collection'
|
371
|
-
require 'active_record/association_proxy'
|
372
|
-
require 'active_record/association_reflection'
|
373
140
|
require 'action_view_extensions/helpers/tag_helper'
|
374
141
|
|
142
|
+
# Modules that must *not* be auto-reloaded by activesupport
|
143
|
+
# (explicitly requiring them means they're never unloaded)
|
144
|
+
require 'hobo/model_router'
|
145
|
+
require 'hobo/undefined'
|
146
|
+
require 'hobo/user'
|
147
|
+
require 'hobo/dryml'
|
148
|
+
require 'hobo/dryml/template'
|
149
|
+
require 'hobo/dryml/dryml_generator'
|
150
|
+
|
151
|
+
Hobo::Model.enable
|
375
152
|
Hobo::Dryml.enable
|
153
|
+
Hobo::Permissions.enable
|
154
|
+
Hobo::ViewHints.enable
|
376
155
|
|
377
156
|
Hobo.developer_features = RAILS_ENV.in?(["development", "test"]) if Hobo.developer_features?.nil?
|
378
157
|
|
379
158
|
require 'hobo/dev_controller' if RAILS_ENV == Hobo.developer_features?
|
380
159
|
|
381
160
|
ActionController::Base.send(:include, Hobo::ControllerExtensions)
|
382
|
-
|
161
|
+
|
162
|
+
if defined? HoboFields
|
163
|
+
HoboFields.never_wrap(Hobo::Undefined)
|
164
|
+
end
|
165
|
+
|
166
|
+
ActiveSupport::Dependencies.load_paths |= [ "#{RAILS_ROOT}/app/viewhints" ]
|
383
167
|
end
|
384
168
|
|
385
169
|
end
|
@@ -402,18 +186,6 @@ module Hobo
|
|
402
186
|
|
403
187
|
end
|
404
188
|
|
405
|
-
|
406
|
-
ModelExtensions = classy_module do
|
407
|
-
def self.hobo_model
|
408
|
-
include Hobo::Model
|
409
|
-
end
|
410
|
-
def self.hobo_user_model
|
411
|
-
include Hobo::Model
|
412
|
-
include Hobo::User
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
|
417
189
|
# Empty class to represent the boolean type.
|
418
190
|
class Boolean; end
|
419
191
|
|
@@ -421,11 +193,6 @@ module Hobo
|
|
421
193
|
end
|
422
194
|
|
423
195
|
|
424
|
-
if defined? HoboFields
|
425
|
-
HoboFields.never_wrap(Hobo::Undefined)
|
426
|
-
end
|
427
|
-
|
428
|
-
|
429
196
|
# Add support for type metadata to arrays
|
430
197
|
class ::Array
|
431
198
|
|
@@ -437,7 +204,7 @@ class ::Array
|
|
437
204
|
end
|
438
205
|
|
439
206
|
def typed_id
|
440
|
-
origin and origin_id = origin.try.typed_id and "#{origin_id}
|
207
|
+
origin and origin_id = origin.try.typed_id and "#{origin_id}:#{origin_attribute}"
|
441
208
|
end
|
442
209
|
|
443
210
|
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Hobo
|
2
|
+
|
3
|
+
module AccessibleAssociations
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def prepare_has_many_assignment(association, association_name, array_or_hash)
|
8
|
+
owner = association.proxy_owner
|
9
|
+
|
10
|
+
array = params_hash_to_array(array_or_hash)
|
11
|
+
array.map! do |record_hash_or_string|
|
12
|
+
find_or_create_and_update(owner, association, association_name, record_hash_or_string) { association.build }
|
13
|
+
end
|
14
|
+
array.compact
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def find_or_create_and_update(owner, association, association_name, record_hash_or_string)
|
19
|
+
if record_hash_or_string.is_a?(String)
|
20
|
+
# An ID (if it starts '@') or else a name
|
21
|
+
record = find_record(association, record_hash_or_string)
|
22
|
+
|
23
|
+
elsif record_hash_or_string.is_a?(Hash)
|
24
|
+
# A hash of attributes
|
25
|
+
hash = record_hash_or_string
|
26
|
+
|
27
|
+
# Remove completely blank hashes
|
28
|
+
return nil if hash.values.join.blank?
|
29
|
+
|
30
|
+
id = hash.delete(:id)
|
31
|
+
|
32
|
+
record = if id
|
33
|
+
association.find(id) # TODO: We don't really want to find these one by one
|
34
|
+
else
|
35
|
+
record = yield
|
36
|
+
end
|
37
|
+
record.attributes = hash
|
38
|
+
owner.include_in_save(association_name, record) unless owner.new_record? && record.new_record?
|
39
|
+
|
40
|
+
else
|
41
|
+
# It's already a record
|
42
|
+
record = record_hash_or_string
|
43
|
+
end
|
44
|
+
record
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def params_hash_to_array(array_or_hash)
|
49
|
+
if array_or_hash.is_a?(Hash)
|
50
|
+
array = array_or_hash.get(*array_or_hash.keys.sort_by(&:to_i))
|
51
|
+
else
|
52
|
+
array_or_hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def find_record(association, id_or_name)
|
58
|
+
klass = association.member_class
|
59
|
+
if id_or_name =~ /^@(.*)/
|
60
|
+
id = $1
|
61
|
+
if id =~ /:/
|
62
|
+
Hobo::Model.find_by_typed_id(id)
|
63
|
+
else
|
64
|
+
klass.find(id)
|
65
|
+
end
|
66
|
+
else
|
67
|
+
klass.named(id_or_name, :conditions => association.conditions)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
classy_module(AccessibleAssociations) do
|
74
|
+
|
75
|
+
include IncludeInSave
|
76
|
+
|
77
|
+
# --- has_many mass assignment support --- #
|
78
|
+
|
79
|
+
def self.has_many_with_accessible(name, options={}, &block)
|
80
|
+
has_many_without_accessible(name, options, &block)
|
81
|
+
|
82
|
+
if options[:accessible]
|
83
|
+
class_eval %{
|
84
|
+
def #{name}_with_accessible=(array_or_hash)
|
85
|
+
items = Hobo::AccessibleAssociations.prepare_has_many_assignment(#{name}, :#{name}, array_or_hash)
|
86
|
+
self.#{name}_without_accessible = items
|
87
|
+
# ensure the loaded array contains any changed records
|
88
|
+
self.#{name}.proxy_target[0..-1] = items
|
89
|
+
end
|
90
|
+
}, __FILE__, __LINE__ - 7
|
91
|
+
alias_method_chain :"#{name}=", :accessible
|
92
|
+
end
|
93
|
+
end
|
94
|
+
metaclass.alias_method_chain :has_many, :accessible
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
# --- belongs_to assignment support --- #
|
99
|
+
|
100
|
+
def self.belongs_to_with_accessible(name, options={}, &block)
|
101
|
+
belongs_to_without_accessible(name, options, &block)
|
102
|
+
|
103
|
+
if options[:accessible]
|
104
|
+
class_eval %{
|
105
|
+
def #{name}_with_accessible=(record_hash_or_string)
|
106
|
+
record = Hobo::AccessibleAssociations.find_or_create_and_update(self, #{name}, :#{name}, record_hash_or_string) { self.class.reflections[:#{name}].klass.new }
|
107
|
+
self.#{name}_without_accessible = record
|
108
|
+
end
|
109
|
+
}, __FILE__, __LINE__ - 5
|
110
|
+
alias_method_chain :"#{name}=", :accessible
|
111
|
+
end
|
112
|
+
end
|
113
|
+
metaclass.alias_method_chain :belongs_to, :accessible
|
114
|
+
|
115
|
+
|
116
|
+
# Add :accessible to the valid keys so AR doesn't complain
|
117
|
+
|
118
|
+
def self.valid_keys_for_has_many_association_with_accessible
|
119
|
+
valid_keys_for_has_many_association_without_accessible + [:accessible]
|
120
|
+
end
|
121
|
+
metaclass.alias_method_chain :valid_keys_for_has_many_association, :accessible
|
122
|
+
|
123
|
+
def self.valid_keys_for_belongs_to_association_with_accessible
|
124
|
+
valid_keys_for_belongs_to_association_without_accessible + [:accessible]
|
125
|
+
end
|
126
|
+
metaclass.alias_method_chain :valid_keys_for_belongs_to_association, :accessible
|
127
|
+
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|