the_force 0.1.0 → 0.2.0

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