xhive 1.4.0.pre → 1.5.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -268,6 +268,26 @@ end
268
268
 
269
269
  Using this feature you can let the designers implement the HTML/CSS to display the posts in your site without your intervention.
270
270
 
271
+ ## Policy based mapping
272
+
273
+ If you need more customization in the page mapping process, you can pass a policy class name as the last attribute.
274
+
275
+ ```ruby
276
+ class MyPolicyClass
277
+ def call(opts={})
278
+ opts[:user].country == 'US' && opts[:user].age > 18
279
+ end
280
+ end
281
+
282
+ mapper = Xhive::Mapper.map_resource(site, posts_page, 'posts', 'index', post.id, 'MyPolicyClass')
283
+
284
+ # It will only use the page if the user is an adult from the US
285
+ render_page_with @post.id, :post => @post, :user => @user
286
+
287
+ ```
288
+ Note: the mailer instance variables will be passed along to the policy class. This allows you to customize the email templates
289
+ depending on the user properties. See below for ActionMailer integration.
290
+
271
291
  ## ActionMailer integration
272
292
 
273
293
  Using xhive you can extend the CMS capabilities to your system generated emails.
@@ -316,6 +336,9 @@ mapper.page = email_for_spanish_users
316
336
  mapper.save
317
337
  ```
318
338
 
339
+ Note: the page title will be used as the email subject. You can also make use of the instance variables
340
+ inside the page title as is treated as a Liquid template string.
341
+
319
342
  ### Inline stylesheets for your emails
320
343
 
321
344
  If you add the inline widget to your cell routes you can use inline stylesheets within your email pages:
@@ -346,14 +369,17 @@ Then you can add your inline page into your email page using the corresponding t
346
369
 
347
370
  `{% inline_page id:email_header %}`
348
371
 
349
- TODO
350
- ====
372
+ ## TODO
351
373
 
352
374
  * Remove as many dependencies as possible
353
375
  * Improve test coverage
354
376
 
355
- Disclaimer
356
- ==========
377
+ ## Disclaimer
378
+
357
379
  This is a work in progress and still a proof of concept. Use at your own risk.
358
380
 
359
381
  Please let me know of any problems, ideas, improvements, etc.
382
+
383
+ ## Special Thanks
384
+
385
+ * Thanks to [Daniel Cadenas](https://github.com/dcadenas) for the Policy class inspiration.
@@ -17,7 +17,7 @@ module Xhive
17
17
  # Returns: the rendered page.
18
18
  #
19
19
  def render_page_with(key = nil, options={}, &block)
20
- page = Xhive::Mapper.page_for(current_site, controller_path, action_name, key)
20
+ page = Xhive::Mapper.page_for(current_site, controller_path, action_name, key, options)
21
21
  if page.present?
22
22
  render :inline => page.present_content(options), :layout => true
23
23
  else
@@ -2,7 +2,7 @@ module Xhive
2
2
  # Maps resources to pages.
3
3
  #
4
4
  class Mapper < ActiveRecord::Base
5
- attr_accessible :action, :page_id, :site_id, :resource, :key
5
+ attr_accessible :action, :page_id, :site_id, :resource, :key, :policy
6
6
 
7
7
  belongs_to :site
8
8
  belongs_to :page
@@ -18,11 +18,12 @@ module Xhive
18
18
  # resource - The String containing the resource name filter.
19
19
  # action - The String containing the action name filter.
20
20
  # key - The String containing the key filter.
21
+ # opts - The Hash containing extra values for policy-based filters.
21
22
  #
22
23
  # Returns: the mapped page or nil if not found.
23
24
  #
24
- def self.page_for(site, resource, action, key = nil)
25
- mapper = find_map(site, resource, action, key)
25
+ def self.page_for(site, resource, action, key = nil, opts = {})
26
+ mapper = find_map(site, resource, action, key, opts)
26
27
  page = mapper.try(:page)
27
28
  end
28
29
 
@@ -33,13 +34,17 @@ module Xhive
33
34
  # resource - The String containing the associated resource name.
34
35
  # action - The String containing the associated action name.
35
36
  # key - The String containing the associated key.
37
+ # policy - The String containing the policy class.
36
38
  #
37
39
  # Returns: true if created. False otherwise.
38
40
  #
39
- def self.map_resource(site, page, resource, action, key = nil)
40
- mapper = find_map(site, resource, action, key)
41
+ def self.map_resource(site, page, resource, action, key = nil, policy = nil)
42
+ check_policy_class(policy) if policy.present?
43
+
44
+ mapper = find_exact_map(site, resource, action, key, policy)
41
45
  mapper = new(:site_id => site.id, :resource => resource,
42
- :action => action, :key => key.present? ? key : nil) unless mapper.present?
46
+ :action => action, :policy => policy,
47
+ :key => key.present? ? key : nil) unless mapper.present?
43
48
  mapper.page = page
44
49
  mapper.save
45
50
  end
@@ -55,6 +60,16 @@ module Xhive
55
60
  where(:site_id => site.id).where(:resource => resource)
56
61
  end
57
62
 
63
+ class InvalidPolicyError < StandardError
64
+ def initialize(name)
65
+ @name = name
66
+ end
67
+
68
+ def message
69
+ "#{@name} must implement a ::call method"
70
+ end
71
+ end
72
+
58
73
  private
59
74
 
60
75
  # Private: looks for a mapper object.
@@ -63,15 +78,75 @@ module Xhive
63
78
  # resource - The String containing the resource name filter.
64
79
  # action - The String containing the action name filter.
65
80
  # key - The String containing the key filter.
81
+ # opts - The Hash containing extra values for policy-based filters.
82
+ #
83
+ # Returns:
84
+ #
85
+ # - The mapper object if it finds a key.
86
+ # - The default mapper if it does not find a key.
87
+ # - Nil if there is no default mapper.
88
+ #
89
+ def self.find_map(site, resource, action, key, opts)
90
+ # Create filtering scopes
91
+ scope = where(:site_id => site.id)
92
+ scope = scope.where(:resource => resource)
93
+ scope = scope.where(:action => action)
94
+
95
+ # Fetch mappers
96
+ mappers = scope.where(:key => key.present? ? key : nil)
97
+ mappers = scope.where(:key => nil) if mappers.empty?
98
+
99
+ # Check policies and select the first that passes
100
+ select_by_policy(mappers, opts)
101
+ end
102
+
103
+ # Private: looks for an exact mapper object.
104
+ #
105
+ # site - The Site to look into.
106
+ # resource - The String containing the resource name filter.
107
+ # action - The String containing the action name filter.
108
+ # key - The String containing the key filter.
109
+ # policy - The String containing the policy class.
66
110
  #
67
111
  # Returns: the mapper object or nil if not found.
68
112
  #
69
- def self.find_map(site, resource, action, key)
113
+ def self.find_exact_map(site, resource, action, key, policy)
70
114
  mapper = where(:site_id => site.id)
71
115
  mapper = mapper.where(:resource => resource)
72
116
  mapper = mapper.where(:action => action)
73
117
  mapper = mapper.where(:key => key.present? ? key : nil)
118
+ mapper = mapper.where(:policy => policy.present? ? policy : nil)
74
119
  mapper.first
75
120
  end
121
+
122
+ # Private: selects the first mapper that fulfills the policy
123
+ #
124
+ # mappers - The Array containing the mapper objects.
125
+ # opts - The Hash containing the policy filter data.
126
+ #
127
+ # Returns: the first matching mapper or nil if no one matches
128
+ #
129
+ def self.select_by_policy(mappers, opts)
130
+ mappers.sort_by {|m| m.policy.to_s }.reverse.select {|m| m.send(:verify_policy, opts) }.first
131
+ end
132
+
133
+ # Private: checks the mapper policy against its class
134
+ #
135
+ # opts - The Hash containing the policy filter data.
136
+ #
137
+ # Return: true if it fulfills the policy and false if it does not.
138
+ #
139
+ def verify_policy(opts)
140
+ result = policy.constantize.call(opts)
141
+ rescue NameError
142
+ result = true
143
+ ensure
144
+ return result
145
+ end
146
+
147
+ def self.check_policy_class(policy)
148
+ klass = policy.constantize
149
+ fail InvalidPolicyError.new(policy) unless klass.respond_to?(:call)
150
+ end
76
151
  end
77
152
  end
@@ -0,0 +1,5 @@
1
+ class AddPolicyToXhiveMappers < ActiveRecord::Migration
2
+ def change
3
+ add_column :xhive_mappers, :policy, :string, :null => true, :default => nil
4
+ end
5
+ end
data/lib/xhive/mailer.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Xhive
2
2
  class Mailer
3
- attr :site, :resource, :action, :key, :mailer, :content, :page
3
+ attr :site, :resource, :action, :key, :mailer, :content, :page, :vars
4
4
 
5
5
  def initialize(site, mailer, key = nil)
6
6
  @site = site
@@ -8,7 +8,8 @@ module Xhive
8
8
  @mailer = mailer
9
9
  @action = mailer.action_name
10
10
  @key = key
11
- @page = Xhive::Mapper.page_for(@site, @resource, @action, @key)
11
+ @vars = mailer_instance_variables(mailer)
12
+ @page = Xhive::Mapper.page_for(@site, @resource, @action, @key, @vars)
12
13
  end
13
14
 
14
15
  # Public: sends the email to the specified recipients.
@@ -38,7 +39,7 @@ module Xhive
38
39
  #
39
40
  def content
40
41
  return @content if @content.present?
41
- @content = page.present? ? page.present_content(mailer_instance_variables(mailer)) : mailer.render
42
+ @content = page.present? ? page.present_content(vars) : mailer.render
42
43
  end
43
44
 
44
45
  # Public: returns the email subject.
@@ -46,7 +47,7 @@ module Xhive
46
47
  # Returns: the rendered template or the mapped page content body.
47
48
  #
48
49
  def subject
49
- @subject = page.present? ? page.present_title(mailer_instance_variables(mailer)) : nil
50
+ @subject = page.present? ? page.present_title(vars) : nil
50
51
  end
51
52
 
52
53
  private
data/lib/xhive/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Xhive
2
- VERSION = "1.4.0.pre"
2
+ VERSION = "1.5.0.pre"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xhive
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.pre
4
+ version: 1.5.0.pre
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-22 00:00:00.000000000 Z
12
+ date: 2012-11-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -187,22 +187,6 @@ dependencies:
187
187
  - - ! '>='
188
188
  - !ruby/object:Gem::Version
189
189
  version: '0'
190
- - !ruby/object:Gem::Dependency
191
- name: debugger
192
- requirement: !ruby/object:Gem::Requirement
193
- none: false
194
- requirements:
195
- - - ! '>='
196
- - !ruby/object:Gem::Version
197
- version: '0'
198
- type: :development
199
- prerelease: false
200
- version_requirements: !ruby/object:Gem::Requirement
201
- none: false
202
- requirements:
203
- - - ! '>='
204
- - !ruby/object:Gem::Version
205
- version: '0'
206
190
  - !ruby/object:Gem::Dependency
207
191
  name: mocha
208
192
  requirement: !ruby/object:Gem::Requirement
@@ -264,6 +248,7 @@ files:
264
248
  - db/migrate/20121019185702_create_xhive_mappers.rb
265
249
  - db/migrate/20121031192552_add_key_to_xhive_mappers.rb
266
250
  - db/migrate/20121101124925_create_xhive_images.rb
251
+ - db/migrate/20121127230527_add_policy_to_xhive_mappers.rb
267
252
  - lib/tasks/xhive_tasks.rake
268
253
  - lib/xhive/base_tag.rb
269
254
  - lib/xhive/controller.rb
@@ -298,7 +283,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
298
283
  version: '0'
299
284
  segments:
300
285
  - 0
301
- hash: 679411744217455480
286
+ hash: -2539444549338109190
302
287
  required_rubygems_version: !ruby/object:Gem::Requirement
303
288
  none: false
304
289
  requirements: