the_force 0.1.0 → 0.2.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/Rakefile CHANGED
@@ -7,13 +7,13 @@ exclude_file_globs = []
7
7
 
8
8
  spec = Gem::Specification.new do |s|
9
9
  s.name = "the_force"
10
- s.version = '0.1.0'
10
+ s.version = '0.2.0'
11
11
  s.author = "Ryan Ziegler"
12
12
  s.email = "info@symbolforce.com"
13
13
  s.homepage = "http://www.symbolforce.com"
14
14
  s.platform = Gem::Platform::RUBY
15
15
  s.summary = "Common code for Symbolforce"
16
- s.description = "Common code for Symbolforce. tests pass in 1.8.6, 1.8.7, 1.9.1, and jruby 1.4"
16
+ s.description = "Common code for Symbolforce"
17
17
  s.files = FileList[include_file_globs].to_a - FileList[exclude_file_globs].to_a
18
18
  s.require_path = "lib"
19
19
  s.test_files = FileList["test/**/test_*.rb"].to_a
@@ -0,0 +1,27 @@
1
+ #CRZ - any reason to support parameters in the block? would need instance_exec, and maybe some compat instance_exec for pre-1.8.7 rubies...
2
+
3
+ module TheForce
4
+ module ObjectSupport
5
+ module Memoization
6
+ def attr_memoize(attribute, &b)
7
+ raise ArgumentError, "attr_memoize requires a block" unless block_given?
8
+
9
+ ivar = "@#{attribute}"
10
+ self.class_eval do
11
+ define_method attribute.to_sym do |*args|
12
+ refresh = !!args[0]
13
+ if not instance_variable_defined?(ivar) or refresh
14
+ instance_variable_set(ivar, instance_eval(&b))
15
+ else
16
+ instance_variable_get(ivar)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ class Object
26
+ extend TheForce::ObjectSupport::Memoization
27
+ end
@@ -1,41 +1,21 @@
1
+ #--
1
2
  #CRZ - imitate andand to a great degree.
2
3
  # Could have something more complex than if or unless, but they're enough, and didnt want to introduce proc overhead.
3
4
  # - logic duplication, three ""inverted^ return ? caller : nil""s
4
5
  ### - better behavior for args WITH a block?
5
6
 
6
- if Module.constants.include?('BasicObject')
7
- class ConditionalReturningMe < BasicObject
8
- end
9
- else
10
- class ConditionalReturningMe
11
- instance_methods.reject { |m| m =~ /^__/ }.each { |m| undef_method m }
12
- end
13
- end
14
-
15
- class ConditionalReturningMe
16
- def initialize(me, inverted)
17
- super()
18
- @me = me
19
- @inverted = inverted
20
- end
21
-
22
- def method_missing(sym, *args, &b)
23
- (@inverted ^ @me.send(sym, *args, &b)) ? @me : nil
24
- end
25
- end
26
-
27
7
  module TheForce
28
8
  module ObjectSupport
29
- def if(*args, &b)
30
- ObjectSupport.conditional(self, false, *args, &b)
31
- end
32
-
33
- def unless(*args, &b)
34
- ObjectSupport.conditional(self, true, *args, &b)
9
+ if Module.constants.include?('BasicObject')
10
+ class ConditionalReturningMe < BasicObject
11
+ end
12
+ else
13
+ class ConditionalReturningMe
14
+ instance_methods.reject { |m| m =~ /^__/ }.each { |m| undef_method m }
15
+ end
35
16
  end
36
-
37
- private
38
- def self.conditional(who, inverted, *args, &b)
17
+
18
+ def self.conditional(who, inverted, *args, &b) # :doc:
39
19
  if block_given?
40
20
  (inverted ^ yield(who)) ? who : nil
41
21
  elsif args.length > 0
@@ -44,9 +24,65 @@ module TheForce
44
24
  ConditionalReturningMe.new(who, inverted)
45
25
  end
46
26
  end
27
+
28
+ # This is the blankslate object returned by the Object#if and Object#unless methods when called with no arguments or block.
29
+ class ConditionalReturningMe
30
+ def initialize(me, inverted)
31
+ super()
32
+ @me = me
33
+ @inverted = inverted
34
+ end
35
+
36
+ def method_missing(sym, *args, &b) # :doc:
37
+ (@inverted ^ @me.send(sym, *args, &b)) ? @me : nil
38
+ end
39
+ end
40
+
41
+ module InstanceMethods
42
+ # Will return a nil if the condition is false, otherwise it will return the receiver. The condition
43
+ # can be specified in 3 ways, as a list of arguments which are sent to Object#send, a block, or via essentially a
44
+ # delegate object, ala the andand gem.
45
+ #
46
+ # == Examples
47
+ # - 10.if(:>, 5) => 10
48
+ # - 10.if {|x| x == 5) => nil
49
+ # - 10.if.nonzero? => 10
50
+ #
51
+ # == Usage
52
+ # This becomes useful to simplify logic when you want to specify a default value,
53
+ # (particularly in Rails views) or you have a receiver which is the result of a lengthy expression.
54
+ #
55
+ # * number_of_products.if.nonzero? || "Don't you want to buy something?"
56
+ # * lovers.sort.reverse.unless.empty? || "Where's the fever? :("
57
+ #
58
+ # == Warning
59
+ # Do not try to do:
60
+ #
61
+ # * title.if.length > 20 || title.truncate[0,17] + "..."
62
+ #
63
+ # This would evaluate to:
64
+ #
65
+ # * title > 20 || title.truncate(17) + "..."
66
+ def if(*args, &b)
67
+ TheForce::ObjectSupport.conditional(self, false, *args, &b)
68
+ end
69
+
70
+ # Same as +if+, only with the predictably inverse logic.
71
+ #
72
+ # == Usage
73
+ # * title.unless.blank? || suggestion_html "please set your title on the edit page"
74
+ def unless(*args, &b)
75
+ TheForce::ObjectSupport.conditional(self, true, *args, &b)
76
+ end
77
+
78
+ def eigenclass #this could also be labeled 'self'?
79
+ class << self; self; end
80
+ end
81
+
82
+ end
47
83
  end
48
84
  end
49
85
 
50
86
  class Object
51
- include TheForce::ObjectSupport
87
+ include TheForce::ObjectSupport::InstanceMethods
52
88
  end
@@ -0,0 +1,63 @@
1
+ module TheForce
2
+ module RemoteIncludes
3
+ @@remotes = []
4
+
5
+ def self.[](name)
6
+ @@remotes.detect {|remote| remote.name == name }
7
+ end
8
+
9
+ def self.remotes
10
+ @@remotes
11
+ end
12
+
13
+ def self.add(attrs)
14
+ attrs[:name] ||= attrs[:url]
15
+ @@remotes << RemoteInclude.new(attrs) unless attrs[:url].blank?
16
+ end
17
+
18
+ def self.cache_url_with_partial_fallback(url, key, partial = nil)
19
+ begin
20
+ response = Net::HTTP.get_response(URI.parse(url))
21
+ Rails.cache.write(key, response.body) if response.class == Net::HTTPOK
22
+ rescue Exception => e
23
+ ensure
24
+ cache_from_partial(key, partial) if partial and not Rails.cache.read(key)
25
+ end
26
+ end
27
+
28
+ def self.cache_from_partial(key, partial)
29
+ av = ActionView::Base.new(Rails::Configuration.new.view_path)
30
+ Rails.cache.write(key, av.render(:partial => partial))
31
+ end
32
+
33
+ def self.recache!
34
+ Array(@@remotes).each do |remote|
35
+ remote.recache!
36
+ end
37
+ end
38
+ end
39
+
40
+ class RemoteInclude < OpenStruct
41
+ def [](key)
42
+ self.send(key.to_sym)
43
+ end
44
+
45
+ def key
46
+ name
47
+ end
48
+
49
+ def value
50
+ Rails.cache.read(key)
51
+ end
52
+
53
+ def recache!
54
+ RemoteIncludes.cache_url_with_partial_fallback(self.url, self.name, self.backup_partial)
55
+ end
56
+
57
+ def last_cached_at
58
+ return nil unless Rails.cache.instance_of? ActiveSupport::Cache::FileStore
59
+
60
+ File.mtime(Rails.cache.instance_eval("real_file_path('#{self.key}')")) rescue nil
61
+ end
62
+ end
63
+ end
data/lib/the_force.rb CHANGED
@@ -3,4 +3,5 @@ require File.join(ROOT, 'keep_trying')
3
3
  require File.join(ROOT, 'thread_pool')
4
4
  require File.join(ROOT, 'timer')
5
5
  #require File.join(ROOT, 'object_support')
6
+ require File.join(ROOT, 'remote_includes')
6
7
  true
@@ -0,0 +1,6 @@
1
+ #require 'active_support/testing/assertions'
2
+
3
+ begin
4
+ require 'redgreen'
5
+ rescue LoadError
6
+ end
@@ -0,0 +1,65 @@
1
+ require 'test/unit'
2
+ require 'memoize'
3
+
4
+ class Memoizer
5
+ def initialize
6
+ @value = 1
7
+ @other = 2
8
+ end
9
+
10
+ def inc
11
+ @value +=1
12
+ end
13
+
14
+ def meth
15
+ 3
16
+ end
17
+
18
+ attr_memoize :a do
19
+ @value
20
+ end
21
+
22
+ attr_memoize :test_instance_variable_access do
23
+ @other
24
+ end
25
+
26
+ attr_memoize :test_instance_method_access do
27
+ meth
28
+ end
29
+ end
30
+
31
+ class TestMemoize < Test::Unit::TestCase
32
+ def setup
33
+ @m = Memoizer.new
34
+ end
35
+
36
+ def test_raises_error_with_no_block
37
+ assert_raise ArgumentError do
38
+ Memoizer.class_eval('attr_memoize :b')
39
+ end
40
+ end
41
+
42
+ def test_memoizes_first_time
43
+ assert_equal 1, @m.a
44
+ end
45
+
46
+ def test_can_refer_to_instance_variables_inside_block
47
+ assert_equal 2, @m.test_instance_variable_access
48
+ end
49
+
50
+ def test_can_call_instance_method_inside_block
51
+ assert_equal 3, @m.test_instance_method_access
52
+ end
53
+
54
+ def test_does_not_rememoize_second_time
55
+ @m.a
56
+ @m.inc
57
+ assert_equal 1, @m.a
58
+ end
59
+
60
+ def test_memoizes_again_after_refresh
61
+ @m.a
62
+ @m.inc
63
+ assert_equal 2, @m.a(true)
64
+ end
65
+ end
@@ -1,9 +1,5 @@
1
1
  require 'test/unit'
2
- begin
3
- require File.join(File.dirname(__FILE__), '../../lib/the_force/object_support.rb')
4
- rescue LoadError
5
- require File.expand_path('../../lib/the_force/object_support.rb', __FILE__)
6
- end
2
+ require 'object_support'
7
3
 
8
4
  begin
9
5
  require 'active_support'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: the_force
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Ziegler
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-05-20 00:00:00 -04:00
18
+ date: 2010-10-03 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
22
- description: Common code for Symbolforce. tests pass in 1.8.6, 1.8.7, 1.9.1, and jruby 1.4
22
+ description: Common code for Symbolforce
23
23
  email: info@symbolforce.com
24
24
  executables: []
25
25
 
@@ -33,11 +33,15 @@ files:
33
33
  - Rakefile
34
34
  - init.rb
35
35
  - lib/the_force/keep_trying.rb
36
+ - lib/the_force/memoize.rb
36
37
  - lib/the_force/object_support.rb
38
+ - lib/the_force/remote_includes.rb
37
39
  - lib/the_force/thread_pool.rb
38
40
  - lib/the_force/timer.rb
39
41
  - lib/the_force.rb
42
+ - test/test_helper.rb
40
43
  - test/unit/test_keep_trying.rb
44
+ - test/unit/test_memoize.rb
41
45
  - test/unit/test_object_support.rb
42
46
  has_rdoc: true
43
47
  homepage: http://www.symbolforce.com
@@ -75,5 +79,7 @@ signing_key:
75
79
  specification_version: 3
76
80
  summary: Common code for Symbolforce
77
81
  test_files:
82
+ - test/test_helper.rb
78
83
  - test/unit/test_keep_trying.rb
84
+ - test/unit/test_memoize.rb
79
85
  - test/unit/test_object_support.rb