presenter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Vladimir Bobes Tuzinsky
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,146 @@
1
+ = Presenter gem
2
+
3
+ This gem is mainly targeted at Rails developers who:
4
+
5
+ * need to execute a search based on request parameters
6
+ * load records from a database for cached fragments
7
+ * have a lot of view-related logic in models
8
+
9
+ It will help you to:
10
+
11
+ * process request parameters (with simple typecasting)
12
+ * cleanup your models and controller
13
+ * postpone querying database until really needed (if needed at all)
14
+ * ... more ...
15
+
16
+ == Installation
17
+
18
+ As usual:
19
+
20
+ gem install presenter
21
+
22
+ To keep your code organized, create a directory "app/presenters" in your project and add this line to your environment.rb (or application.rb if you use Rails 3):
23
+
24
+ config.load_paths << Rails.root.join("app", "presenters").to_s
25
+
26
+ Now you can have your presenters in the app/presenters directory and they'll be loaded automatically.
27
+
28
+ == Basic usage
29
+
30
+ Presenter:
31
+
32
+ # app/presenters/users_presenter.rb
33
+ class UsersPresenter < Presenter
34
+
35
+ # following parameters will be extracted from the params hash and
36
+ # properly typecasted. Nils, blanks and empty arrays will be discarded.
37
+ # If a parameter's value is an array, all values in the array will
38
+ # be typecasted
39
+ key :name, String
40
+ key :age, Integer
41
+
42
+ # this creates method "users", which calls and memoizes method "find_user".
43
+ presents :users
44
+
45
+ private
46
+
47
+ def find_users
48
+ scope = User
49
+ scope = scope.scoped(:conditions => { :name => name }) if first_name
50
+ scope = scope.scoped(:conditions => { :age => age }) if age
51
+ scope
52
+ end
53
+ end
54
+
55
+ Controller:
56
+
57
+ # app/controllers/users_controller.rb
58
+ class UsersController < ApplicationController
59
+
60
+ def index
61
+ @users_presenter = UsersPresenter.new(params)
62
+ end
63
+ end
64
+
65
+ View:
66
+
67
+ # app/views/users/index.html.haml
68
+ %ul
69
+ - @users_presenter.users.each do |user|
70
+ %li= user.name
71
+
72
+ == Mixins
73
+
74
+ If some of the code in your models is used only inside views (formatting and such),
75
+ you may extract this code to a module and mix it from the presenter:
76
+
77
+ # app/presenters/user_mixin.rb
78
+ module UserMixin
79
+ def age_cca
80
+ age < 20 ? "too young" : age >= 30 ? "30+" : age
81
+ end
82
+ end
83
+
84
+ Then tell the presented to use the module:
85
+
86
+ # app/presenters/users_presenter.rb
87
+ ...
88
+ presents :users, UserMixin
89
+ ...
90
+
91
+ Now you can use the new method in your views:
92
+
93
+ # app/views/users/index.html.haml
94
+ %ul
95
+ - @users_presenter.users.each do |user|
96
+ %li
97
+ = user.name
98
+ = user.age_cca
99
+
100
+ == Typecasting
101
+
102
+ These types are supported out of the box:
103
+ +Object+, +Boolean+, +Float+, +Integer+, +String+, +Time+.
104
+
105
+ All of these can be +nil+, single value or an array of values.
106
+
107
+ It is also possible to add support for your custom types by implementing class
108
+ method "typecast" for the given class. This would add support for price type:
109
+
110
+ # lib/price.rb
111
+ class Price
112
+
113
+ attr :value
114
+
115
+ def initialize(value)
116
+ @value = value
117
+ end
118
+
119
+ def to_s
120
+ if @value
121
+ "$" + @value.to_s.reverse.scan(/\d{1,3}/).join(",").reverse
122
+ else
123
+ ""
124
+ end
125
+ end
126
+
127
+ def self.typecast(value, options = {})
128
+ new value.to_s.scan(/\d+/).join.to_i if value
129
+ end
130
+ end
131
+
132
+ == Note on Patches/Pull Requests
133
+
134
+ As usual:
135
+
136
+ * Fork the project.
137
+ * Make your feature addition or bug fix.
138
+ * Add tests for it. This is important so I don't break it in a
139
+ future version unintentionally.
140
+ * Commit, do not mess with rakefile, version, or history.
141
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
142
+ * Send me a pull request. Bonus points for topic branches.
143
+
144
+ == Copyright
145
+
146
+ Copyright (c) 2010 Vladimir Bobes Tuzinsky. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "presenter"
8
+ gem.summary = %Q{Simplifies usage of Presenter pattern in Rails}
9
+ gem.description = %Q{Simplifies usage of Presenter pattern in Rails}
10
+ gem.email = "vladimir.tuzinsky@gmail.com"
11
+ gem.homepage = "http://github.com/bobes/presenter"
12
+ gem.authors = ["Vladimir Bobes Tuzinsky"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/test_*.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+ task :test => :check_dependencies
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "presenter #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,3 @@
1
+ major: 0
2
+ minor: 1
3
+ patch: 0
data/lib/presenter.rb ADDED
@@ -0,0 +1,11 @@
1
+ gem 'activesupport', '>= 2.3'
2
+
3
+ require 'active_support'
4
+
5
+ class Presenter
6
+ end
7
+
8
+ Dir[File.join(File.dirname(__FILE__), "presenter", "*.rb")].each do |file|
9
+ require file
10
+ end
11
+
@@ -0,0 +1,98 @@
1
+ class Presenter
2
+
3
+ module Core
4
+
5
+ def self.included(model)
6
+ model.class_eval do
7
+ extend ClassMethods
8
+ include InstanceMethods
9
+ end
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def key(*args)
16
+ key = Key.new(*args)
17
+ keys[key.name.to_sym] = key
18
+ create_accessors_for(key)
19
+ end
20
+
21
+ def presents(*names)
22
+ mixin = names.pop if names.last.is_a?(Module)
23
+ names.each { |name| create_finder_for(name, mixin) }
24
+ end
25
+
26
+ def keys
27
+ @keys ||= superclass.respond_to?(:keys) ? superclass.keys.dup : {}
28
+ end
29
+
30
+ private
31
+
32
+ def create_accessors_for(key)
33
+ module_eval <<-EOS, __FILE__, __LINE__ + 1
34
+ def #{key.name}
35
+ values.include?(:#{key.name}) ? values[:#{key.name}] : keys[:#{key.name}].default_value
36
+ end
37
+
38
+ def #{key.name}=(value)
39
+ values[:#{key.name}] = keys[:#{key.name}].typecast(value)
40
+ end
41
+
42
+ def #{key.name}?
43
+ #{key.name}.respond_to?(:empty?) ? !#{key.name}.empty? : !!#{key.name}
44
+ end
45
+ EOS
46
+ end
47
+
48
+ def create_finder_for(name, mixin = nil)
49
+ @mixins ||= {}
50
+ @mixins[name] = mixin
51
+ module_eval <<-EOS, __FILE__, __LINE__ + 1
52
+ def #{name}
53
+ @collections ||= {}
54
+ @collections[:#{name}] ||= wrap_#{name}(find_#{name})
55
+ end
56
+
57
+ private
58
+
59
+ def wrap_#{name}(items)
60
+ if mixin = self.class.instance_variable_get("@mixins")[:#{name}]
61
+ items.each { |item| item.extend(mixin) }
62
+ end
63
+ items
64
+ end
65
+
66
+ def find_#{name}
67
+ raise NotImplementedError.new("find_#{name} method not implemented")
68
+ end
69
+ EOS
70
+ end
71
+ end
72
+
73
+ module InstanceMethods
74
+
75
+ def initialize(params = nil)
76
+ if params
77
+ params.each do |name, value|
78
+ self.send "#{name}=", value if keys[name.to_sym]
79
+ end
80
+ end
81
+ end
82
+
83
+ def keys
84
+ self.class.keys
85
+ end
86
+
87
+ def values
88
+ @values ||= {}
89
+ end
90
+
91
+ def params
92
+ @values.delete_if { |key, value| value.nil? || (value.respond_to?(:empty?) && value.empty?) }
93
+ end
94
+ end
95
+
96
+ include Core
97
+ end
98
+
@@ -0,0 +1,31 @@
1
+ class Key
2
+
3
+ attr_accessor :name
4
+
5
+ def initialize(*args)
6
+ @options = args.last.is_a?(Hash) ? args.pop : {}
7
+ @name, @type = args.shift.to_s, args.shift || Object
8
+ @default_value = @options.delete(:default)
9
+ @options = nil if @type.method(:typecast).arity == 1
10
+ end
11
+
12
+ def typecast(value)
13
+ if value.is_a?(Array)
14
+ array = value.map { |v| typecast(v) }.compact
15
+ array.any? ? array : nil
16
+ elsif value.nil? || (value.respond_to?(:empty?) && value.empty?)
17
+ nil
18
+ else
19
+ @options ? @type.typecast(value, @options) : @type.typecast(value)
20
+ end
21
+ end
22
+
23
+ def default_value
24
+ value = @default_value.is_a?(Proc) ? @default_value.call : @default_value
25
+ @type.typecast(value)
26
+ end
27
+
28
+ def to_s
29
+ "#<Key: name=#{name}, type=#{type}>"
30
+ end
31
+ end
@@ -0,0 +1,64 @@
1
+ class Boolean
2
+
3
+ def self.typecast(value)
4
+ if ["true", "1"].include?(value.to_s.downcase)
5
+ true
6
+ elsif ["false", "0"].include?(value.to_s.downcase)
7
+ false
8
+ else
9
+ nil
10
+ end
11
+ end
12
+ end
13
+
14
+ class Float
15
+
16
+ def self.typecast(value)
17
+ value_to_f = value.to_f
18
+ value_to_f == 0 && value.to_s !~ /^0*\.?0+/ ? nil : value_to_f
19
+ end
20
+ end
21
+
22
+ class Integer
23
+
24
+ def self.typecast(value)
25
+ value_to_i = value.to_i
26
+ value_to_i == 0 && value.to_s !~ /^(0x|0b)?0+/ ? nil : value_to_i
27
+ end
28
+ end
29
+
30
+ class Object
31
+
32
+ def self.typecast(value)
33
+ value
34
+ end
35
+ end
36
+
37
+ class String
38
+
39
+ def self.typecast(value)
40
+ value.nil? ? nil : value.to_s
41
+ end
42
+ end
43
+
44
+ class Time
45
+
46
+ def self.typecast(value, options = {})
47
+ if value.is_a?(Time)
48
+ value
49
+ elsif value.is_a?(Hash)
50
+ Time.local(*value.values_at(:year, :month, :day, :hour, :minute, :second))
51
+ elsif value.is_a?(Date)
52
+ Time.local(value.year, value.month, value.day)
53
+ else
54
+ begin
55
+ dt = Date._strptime(value.to_s, options[:format] || "%a %b %d %H:%M:%S %Z %Y")
56
+ time = Time.local(dt[:year], dt[:mon], dt[:mday], dt[:hour], dt[:min], dt[:sec])
57
+ time += (time.utc_offset - dt[:offset]) if dt[:offset]
58
+ time
59
+ rescue StandardError => e
60
+ nil
61
+ end
62
+ end
63
+ end
64
+ end
data/presenter.gemspec ADDED
@@ -0,0 +1,60 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{presenter}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Vladimir Bobes Tuzinsky"]
12
+ s.date = %q{2010-03-31}
13
+ s.description = %q{Simplifies usage of Presenter pattern in Rails}
14
+ s.email = %q{vladimir.tuzinsky@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION.yml",
26
+ "lib/presenter.rb",
27
+ "lib/presenter/core.rb",
28
+ "lib/presenter/key.rb",
29
+ "lib/presenter/types.rb",
30
+ "presenter.gemspec",
31
+ "test/helper.rb",
32
+ "test/test_core.rb",
33
+ "test/test_key.rb",
34
+ "test/test_presenter.rb",
35
+ "test/test_types.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/bobes/presenter}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.6}
41
+ s.summary = %q{Simplifies usage of Presenter pattern in Rails}
42
+ s.test_files = [
43
+ "test/helper.rb",
44
+ "test/test_core.rb",
45
+ "test/test_key.rb",
46
+ "test/test_presenter.rb",
47
+ "test/test_types.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
55
+ else
56
+ end
57
+ else
58
+ end
59
+ end
60
+
data/test/helper.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ require 'presenter'
7
+
8
+ class Test::Unit::TestCase
9
+
10
+ def self.test(name, &block)
11
+ test_name = "test_#{name.gsub(/\s+/,'_')}".downcase
12
+ define_method(test_name, &block)
13
+ end
14
+ end
data/test/test_core.rb ADDED
@@ -0,0 +1,142 @@
1
+ require "helper"
2
+
3
+ class TestCode < Test::Unit::TestCase
4
+
5
+ test "module can be included" do
6
+ klass = Class.new do
7
+ include Presenter::Core
8
+ key :name
9
+ end
10
+ instance = klass.new
11
+ instance.name = "Fred"
12
+ end
13
+
14
+ test "key defines accessors" do
15
+ klass = Class.new do
16
+ include Presenter::Core
17
+ key :name
18
+ end
19
+ instance = klass.new
20
+ instance.name = "Fred"
21
+ assert_equal "Fred", instance.name
22
+ assert_equal true, instance.name?
23
+ end
24
+
25
+ test "keys are inheritable" do
26
+ a = Class.new do
27
+ include Presenter::Core
28
+ key :name
29
+ end
30
+ b = Class.new(a) do
31
+ key :age
32
+ end
33
+ c = Class.new(a) do
34
+ key :role
35
+ end
36
+ assert a.keys[:name], b.keys[:name]
37
+ assert c.keys[:age].nil?
38
+ end
39
+
40
+ test "setter casts" do
41
+ klass = Class.new do
42
+ include Presenter::Core
43
+ Object.const_set :CustomType, Class.new
44
+ def CustomType.typecast(value)
45
+ value.to_s.reverse
46
+ end
47
+ key :name, CustomType
48
+ end
49
+ instance = klass.new
50
+ instance.name = "Fred"
51
+ assert_equal "derF", instance.name
52
+ end
53
+
54
+ test "accepts params in initializer" do
55
+ klass = Class.new do
56
+ include Presenter::Core
57
+ key :name, String
58
+ key :age, Integer
59
+ end
60
+ instance = klass.new(:name => "Fred", "age" => "35")
61
+ assert_equal "Fred", instance.name
62
+ assert_equal 35, instance.age
63
+ end
64
+
65
+ test "getters return default values" do
66
+ klass = Class.new do
67
+ include Presenter::Core
68
+ key :name, :default => "Unknown"
69
+ end
70
+ assert_equal "Unknown", klass.new.name
71
+ end
72
+
73
+ test "nil in params takes precendence before default value" do
74
+ klass = Class.new do
75
+ include Presenter::Core
76
+ key :name, :default => "Unknown"
77
+ end
78
+ instance = klass.new :name => nil
79
+ assert_nil instance.name
80
+ end
81
+
82
+ test "getters cast default values" do
83
+ klass = Class.new do
84
+ include Presenter::Core
85
+ key :age, String, :default => 35
86
+ end
87
+ assert_equal "35", klass.new.age
88
+ end
89
+
90
+ test "default values support procs" do
91
+ age = Time.now.to_i
92
+ klass = Class.new do
93
+ include Presenter::Core
94
+ key :age, String, :default => lambda { age }
95
+ end
96
+ assert_equal age.to_s, klass.new.age
97
+ end
98
+
99
+ test "presents defines collection reader" do
100
+ klass = Class.new do
101
+ include Presenter::Core
102
+ presents :users
103
+ def find_users; ["user1", "user2"] end
104
+ end
105
+ assert_equal ["user1", "user2"], klass.new.users
106
+ end
107
+
108
+ test "collection readers cache finders results" do
109
+ klass = Class.new do
110
+ include Presenter::Core
111
+ presents :hits
112
+ def find_hits; @count ||= 0; @count += 1 end
113
+ end
114
+ assert_equal 1, klass.new.hits
115
+ assert_equal 1, klass.new.hits
116
+ end
117
+
118
+ test "collection readers can mixin module in items" do
119
+ mod = Module.new do
120
+ def name; "John Doe" end
121
+ end
122
+ klass = Class.new do
123
+ include Presenter::Core
124
+ presents :users, mod
125
+ def find_users; ["user1", "user2"] end
126
+ end
127
+ users = klass.new.users
128
+ assert_equal ["user1", "user2"], users
129
+ assert_equal "John Doe", users.first.name
130
+ end
131
+
132
+ test "params returns cleaned up value hash" do
133
+ klass = Class.new do
134
+ include Presenter::Core
135
+ key :name
136
+ key :age
137
+ key :role, :default => :guest
138
+ end
139
+ instance = klass.new :name => "John Doe"
140
+ assert_equal({ :name => "John Doe" }, instance.params)
141
+ end
142
+ end
data/test/test_key.rb ADDED
@@ -0,0 +1,12 @@
1
+ require "helper"
2
+
3
+ class TestKey < Test::Unit::TestCase
4
+
5
+ test "cast to array" do
6
+ key = Key.new :name, String
7
+ assert_equal ["1", "2", "three"], key.typecast([1, "2", "three"])
8
+ assert_equal ["1", "three"], key.typecast([1, nil, "three"])
9
+ assert_equal nil, key.typecast([""])
10
+ assert_equal nil, key.typecast([nil])
11
+ end
12
+ end
@@ -0,0 +1,8 @@
1
+ require "helper"
2
+
3
+ class TestPresenter < Test::Unit::TestCase
4
+
5
+ test "includes Core" do
6
+ assert Presenter.constants.include?("Core")
7
+ end
8
+ end
@@ -0,0 +1,48 @@
1
+ require "helper"
2
+
3
+ class TestTypes < Test::Unit::TestCase
4
+
5
+ test "cast to boolean" do
6
+ assert_equal true, Boolean.typecast(true)
7
+ assert_equal true, Boolean.typecast("true")
8
+ assert_equal true, Boolean.typecast(1)
9
+ assert_equal true, Boolean.typecast("1")
10
+ assert_equal false, Boolean.typecast(false)
11
+ assert_equal false, Boolean.typecast("false")
12
+ assert_equal false, Boolean.typecast(0)
13
+ assert_equal false, Boolean.typecast("0")
14
+ assert_nil Boolean.typecast(123)
15
+ assert_nil Boolean.typecast("huh?")
16
+ end
17
+
18
+ test "cast to float" do
19
+ assert_equal 35.5, Float.typecast("35.5")
20
+ assert_nil Float.typecast("huh?")
21
+ end
22
+
23
+ test "cast to integer" do
24
+ assert_equal 35, Integer.typecast(35)
25
+ assert_equal 35, Integer.typecast("35")
26
+ assert_equal 35, Integer.typecast("35.5")
27
+ assert_nil Integer.typecast("huh?")
28
+ end
29
+
30
+ test "cast to string" do
31
+ assert_equal "35", String.typecast(35)
32
+ assert_equal "true", String.typecast(true)
33
+ assert_equal "false", String.typecast(false)
34
+ assert_equal "anything", String.typecast("anything")
35
+ assert_nil String.typecast(nil)
36
+ end
37
+
38
+ test "cast to time" do
39
+ assert_equal Time.local(2009, 12, 28, 10, 35, 25), Time.typecast({
40
+ :year => "2009", :month => "12", :day => "28", :hour => "10", :minute => "35", :second => "25"
41
+ })
42
+ assert_equal Time.utc(2009, 12, 28, 9, 35, 25), Time.typecast("Mon Dec 28 11:35:25 +0200 2009")
43
+ assert_equal Time.local(2009, 12, 28, 9, 35), Time.typecast("28/12/2009 09:35", :format => "%d/%m/%Y %H:%M")
44
+ assert_equal Time.local(2009, 12, 28, 10, 35, 25), Time.typecast(Time.local(2009, 12, 28, 10, 35, 25))
45
+ assert_equal Time.utc(2009, 12, 28, 10, 35, 25), Time.typecast(Time.utc(2009, 12, 28, 10, 35, 25))
46
+ assert_equal Time.local(2009, 12, 28), Time.typecast(Date.new(2009, 12, 28))
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: presenter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Vladimir Bobes Tuzinsky
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-03-31 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Simplifies usage of Presenter pattern in Rails
22
+ email: vladimir.tuzinsky@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - LICENSE
29
+ - README.rdoc
30
+ files:
31
+ - .document
32
+ - .gitignore
33
+ - LICENSE
34
+ - README.rdoc
35
+ - Rakefile
36
+ - VERSION.yml
37
+ - lib/presenter.rb
38
+ - lib/presenter/core.rb
39
+ - lib/presenter/key.rb
40
+ - lib/presenter/types.rb
41
+ - presenter.gemspec
42
+ - test/helper.rb
43
+ - test/test_core.rb
44
+ - test/test_key.rb
45
+ - test/test_presenter.rb
46
+ - test/test_types.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/bobes/presenter
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.6
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Simplifies usage of Presenter pattern in Rails
77
+ test_files:
78
+ - test/helper.rb
79
+ - test/test_core.rb
80
+ - test/test_key.rb
81
+ - test/test_presenter.rb
82
+ - test/test_types.rb