prepro 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ h1. How to cut a new version
2
+
3
+ # after all changes are made
4
+ # update the version in lib/version.rb, following semantic versioning
5
+ # cd into prepro root dir
6
+ # gem build prepro.gemspec
7
+ # gem push prepro-x.x.x.gem
8
+ # commit all changes to git
@@ -0,0 +1,6 @@
1
+ # Defines an error to raise when permissions are transgressed.
2
+ module Prepro
3
+
4
+ class AuthorizationError < StandardError; end
5
+
6
+ end
@@ -10,10 +10,14 @@ module Prepro
10
10
  # @param[User, AnonymousUser] actor the actor who will view the model
11
11
  # @param[ActionView::Base] view_context An instance of a view class. The default view class is
12
12
  # ActionView::Base
13
- # @param[Hash, optional] options
13
+ # @param[Hash, optional] options:
14
+ # * :enforce_permissions - default true
14
15
  # @return[DecoratedModel, Array<DecoratedModel>] a model or collection thereof, decorated for
15
16
  # presentation
16
17
  def self.new(id_model_hash_collection, actor, view_context, options = {})
18
+ options = {
19
+ :enforce_permissions => true
20
+ }.merge(options)
17
21
  case id_model_hash_collection
18
22
  when Array, ActiveRecord::Relation
19
23
  present_collection(id_model_hash_collection, actor, view_context, options)
@@ -21,7 +25,7 @@ module Prepro
21
25
  present_single(id_model_hash_collection, actor, view_context, options)
22
26
  end
23
27
  end
24
-
28
+
25
29
  # Alias the basic access methods, so that they can be called for classes further down the
26
30
  # inheritance chain, after another class overrode the method
27
31
  # Aliasing class methods can only be done in the singleton method
@@ -38,12 +42,16 @@ module Prepro
38
42
  # @param[Hash, optional] options
39
43
  # @return[Array<DecoratedModel>] An array of models, each decorated for presentation
40
44
  def self.present_collection(model_instances, actor, view_context, options = {})
41
- presenter_attrs = OpenStruct.new(:actor => actor, :view_context => view_context, :options => options)
42
- enforce_permissions(model_class.listable_by?(actor))
45
+ presenter_attrs = OpenStruct.new(
46
+ :actor => actor, :view_context => view_context, :options => options
47
+ )
48
+ if options[:enforce_permissions]
49
+ enforce_permissions(model_class.listable_by?(actor))
50
+ end
43
51
  model_instances.each { |e| make_presentable!(e, presenter_attrs) }
44
52
  model_instances
45
53
  end
46
-
54
+
47
55
  # Prepares a model instance for presentation
48
56
  # @param[Integer, String(number), Model] id_hash_model id of model, attributes for model, or model
49
57
  # to present
@@ -55,11 +63,13 @@ module Prepro
55
63
  def self.present_single(id_hash_model, actor, view_context, options = {})
56
64
  presenter_attrs = OpenStruct.new(:actor => actor, :view_context => view_context, :options => options)
57
65
  model_instance = load_model_instance(id_hash_model)
58
- enforce_permissions(model_instance.viewable_by?(actor))
66
+ if options[:enforce_permissions]
67
+ enforce_permissions(model_instance.viewable_by?(actor))
68
+ end
59
69
  make_presentable!(model_instance, presenter_attrs)
60
70
  model_instance
61
71
  end
62
-
72
+
63
73
  # Returns a model_instance, based on given id_hash_model
64
74
  def self.load_model_instance(id_hash_model)
65
75
  case id_hash_model
@@ -76,22 +86,24 @@ module Prepro
76
86
  def self.model_class
77
87
  raise "Implement me in concrete presenter"
78
88
  end
79
-
80
- # Override this in your concrete presenters with your own permission handling code.
89
+
90
+ # Raises an AuthorizationError if actor doesn't have permission
91
+ # @param[Boolean] has_permission indicates whether actor has permission
92
+ # @return[Nil] nil, or raises AuthorizationError
81
93
  def self.enforce_permissions(has_permission)
82
- raise "Implement me in concrete presenter"
94
+ raise Prepro::AuthorizationError unless has_permission
83
95
  end
84
-
96
+
85
97
  module DecoratorMixin
86
-
98
+
87
99
  def presenter_attrs=(the_presenter_attrs)
88
100
  @presenter_attrs = the_presenter_attrs
89
101
  end
90
-
102
+
91
103
  def presenter_attrs
92
104
  @presenter_attrs
93
105
  end
94
-
106
+
95
107
  # Formats a_datetime
96
108
  # @param[DateTime, Nil] a_datetime the datetime to format
97
109
  # @param[Symbol] output_format the format to be applied: :distance_in_words,
@@ -167,8 +179,8 @@ module Prepro
167
179
  def indicate_blank
168
180
  presenter_attrs.view_context.content_tag :span, "None Given", :class => 'label'
169
181
  end
170
-
182
+
171
183
  end
172
-
184
+
173
185
  end
174
186
  end
@@ -3,24 +3,33 @@
3
3
  # Use it for the create, update, and destroy actions in a rails app.
4
4
  module Prepro
5
5
  class Processor
6
-
6
+
7
7
  # Creates a new model_instance based on model_attrs.
8
8
  # @param[Hash] model_attrs The attributes for the new model_instance. Includes DB columns,
9
9
  # associated objects, nested attributes, etc.
10
10
  # @param[User, AnonymousUser, Nil] actor The actor who creates the model_instance
11
+ # @param[Hash, optional] options:
12
+ # * :enforce_permissions - default true
11
13
  # @return[Array<ModelInstance, Boolean>] A tuple with the newly created model_instance and a
12
14
  # success flag.
13
15
  def self.create(model_attrs, actor, options = {})
14
- processor_attrs = OpenStruct.new(:attributes => model_attrs, :actor => actor, :options => options)
16
+ options = {
17
+ :enforce_permissions => true
18
+ }.merge(options)
19
+ processor_attrs = OpenStruct.new(
20
+ :attributes => model_attrs, :actor => actor, :options => options
21
+ )
15
22
  model_instance = model_class.new
16
- enforce_permissions(model_instance.creatable_by?(actor))
23
+ if options[:enforce_permissions]
24
+ enforce_permissions(model_instance.creatable_by?(actor))
25
+ end
17
26
  before_assign_attributes_on_create(model_instance, processor_attrs)
18
27
  model_instance.assign_attributes(model_attrs, :as => options[:as])
19
28
  before_save_on_create(model_instance, processor_attrs)
20
29
  success = model_instance.save
21
30
  [model_instance, success]
22
31
  end
23
-
32
+
24
33
  # Updates an existing model_instance based on model_attrs.
25
34
  # @param[Hash] model_attrs The attributes for the updated model_instance. Includes DB columns,
26
35
  # the model's id, associated objects, nested attributes, etc.
@@ -29,21 +38,25 @@ module Prepro
29
38
  def self.update(model_attrs, actor, options = {})
30
39
  processor_attrs = OpenStruct.new(:attributes => model_attrs, :actor => actor, :options => options)
31
40
  model_instance = model_class.find(model_attrs[:id])
32
- enforce_permissions(model_instance.updatable_by?(actor))
41
+ if options[:enforce_permissions]
42
+ enforce_permissions(model_instance.updatable_by?(actor))
43
+ end
33
44
  before_assign_attributes_on_update(model_instance, processor_attrs)
34
45
  model_instance.assign_attributes(model_attrs, :as => options[:as])
35
46
  before_save_on_update(model_instance, processor_attrs)
36
47
  success = model_instance.save
37
48
  [model_instance, success]
38
49
  end
39
-
50
+
40
51
  # Destroys an existing model_instance based on model_id
41
52
  # @param[Integer, String<Number>] model_id The id of the model_instance to be destroyed
42
53
  # @param[User, AnonymousUser, Nil] actor The actor who updates the model_instance
43
54
  # @return[Array<ModelInstance, Boolean>] A tuple with the destroyed model_instance and a success flag.
44
55
  def self.destroy(model_id, actor, options = {})
45
56
  model_instance = model_class.find(model_id)
46
- enforce_permissions(model_instance.destroyable_by?(actor))
57
+ if options[:enforce_permissions]
58
+ enforce_permissions(model_instance.destroyable_by?(actor))
59
+ end
47
60
  model_instance.destroy
48
61
  [model_instance, true]
49
62
  end
@@ -74,15 +87,17 @@ module Prepro
74
87
  def self.model_class
75
88
  raise "Implement me in concrete processor"
76
89
  end
77
-
78
- # Override this in your concrete processors with your own permission handling code.
90
+
91
+ # Raises an AuthorizationError if actor doesn't have permission
92
+ # @param[Boolean] has_permission indicates whether actor has permission
93
+ # @return[Nil] nil, or raises AuthorizationError
79
94
  def self.enforce_permissions(has_permission)
80
- raise "Implement me in concrete processor"
95
+ raise Prepro::AuthorizationError unless has_permission
81
96
  end
82
-
97
+
83
98
  def self.make_processable(model_instance, processor_attrs)
84
99
  # nothing to do here, override in specific processors
85
100
  end
86
-
101
+
87
102
  end
88
103
  end
@@ -1,3 +1,3 @@
1
1
  module Prepro
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/prepro-0.0.3.gem ADDED
Binary file
data/readme.textile CHANGED
@@ -2,3 +2,42 @@ Prepro gives your Rails app presenters and processors to slim down both controll
2
2
 
3
3
  This is still a work in progress. I use it for production, however the API might change and it
4
4
  requires a lot more documentation.
5
+
6
+ Requires Rails 3.1 or greater.
7
+
8
+
9
+ h1. How Prepro fits into the Rails picture
10
+
11
+ * Rails models, ActiveRecord based.
12
+ * Prepro Presenters: wrapped around a Rails model to take care of data output. You would typically
13
+ use a presenter in the following controller actions: index, show, new, edit
14
+ * Prepro Processors: wrapped around a Rails model to take care of data input.
15
+
16
+
17
+ h2. What to put into Rails Models
18
+
19
+ Try to encapsulate all but the simplest references to ActiveRecord in the model. Don't let AR spill
20
+ out into your entire app. This will make testing a lot simpler.
21
+
22
+ * Complex AR methods like composed AREL methods or scopes
23
+ * Data manipulation
24
+ * validation
25
+ * delegation
26
+ * conversion
27
+ * getter and setter overrides for DB column based attributes
28
+
29
+ h2. What to put into Presenters
30
+
31
+ Anything that is related to data output and display.
32
+
33
+ * Display related methods
34
+ * output in alternative formats like PDF, CSV, ATOM
35
+ * methods used for form population (e.g., Select options)
36
+
37
+ h2. What to put into Processors
38
+
39
+ Anything related to data input.
40
+
41
+ * methods to create/update records from complex data, e.g., params hash. This is comparable to DCI
42
+ contexts.
43
+ * form data processing
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prepro
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jo Hund
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-25 00:00:00 -08:00
18
+ date: 2012-02-02 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -28,11 +28,14 @@ extensions: []
28
28
  extra_rdoc_files: []
29
29
 
30
30
  files:
31
+ - doc/gem_workflow.textile
31
32
  - lib/prepro.rb
33
+ - lib/prepro/authorization_error.rb
32
34
  - lib/prepro/presenter.rb
33
35
  - lib/prepro/processor.rb
34
36
  - lib/prepro/version.rb
35
37
  - prepro-0.0.2.gem
38
+ - prepro-0.0.3.gem
36
39
  - prepro.gemspec
37
40
  - readme.textile
38
41
  has_rdoc: true