active_presenter 0.0.1
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/LICENSE +22 -0
- data/README +75 -0
- data/Rakefile +19 -0
- data/lib/active_presenter.rb +7 -0
- data/lib/active_presenter/base.rb +165 -0
- data/lib/active_presenter/version.rb +9 -0
- data/lib/tasks/gem.rake +62 -0
- data/test/base_test.rb +142 -0
- data/test/test_helper.rb +32 -0
- metadata +63 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2008 Daniel Haran, James Golick, GiraffeSoft, Inc.
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
= ActivePresenter
|
2
|
+
|
3
|
+
ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)
|
4
|
+
|
5
|
+
By acting nearly identically to ActiveRecord models, ActivePresenter makes presenters highly approachable to anybody who is already familiar with ActiveRecord.
|
6
|
+
|
7
|
+
== Get It
|
8
|
+
|
9
|
+
As a gem:
|
10
|
+
|
11
|
+
$ sudo gem install active_presenter
|
12
|
+
|
13
|
+
As a rails gem dependency:
|
14
|
+
|
15
|
+
config.gem 'active_presenter'
|
16
|
+
|
17
|
+
Or get the source from github:
|
18
|
+
|
19
|
+
$ git clone git://github.com/giraffesoft/active_presenter.git
|
20
|
+
|
21
|
+
(or fork it at http://github.com/giraffesoft/active_presenter)
|
22
|
+
|
23
|
+
== Usage
|
24
|
+
|
25
|
+
Creating a presenter is as simple as subclassing ActivePresenter::Base. Use the presents method to indicate which models the presenter should present.
|
26
|
+
|
27
|
+
class SignupPresenter < ActivePresenter::Base
|
28
|
+
presents User, Account
|
29
|
+
end
|
30
|
+
|
31
|
+
=== Instantiation
|
32
|
+
|
33
|
+
Then, you can instantiate the presenter using either, or both of two forms.
|
34
|
+
|
35
|
+
For example, if you had a SignupPresenter that presented User, and Account, you could specify arguments in the following two forms:
|
36
|
+
|
37
|
+
1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft')
|
38
|
+
|
39
|
+
- This form is useful for initializing a new presenter from the params hash: i.e. SignupPresenter.new(params[:signup_presenter])
|
40
|
+
|
41
|
+
2. SignupPresenter.new(:user => User.find(1), :account => Account.find(2))
|
42
|
+
|
43
|
+
- This form is useful if you have instances that you'd like to edit using the presenter. You can subsequently call presenter.update_attributes(params[:signup_presenter]) just like with a regular AR instance.
|
44
|
+
|
45
|
+
Both forms can also be mixed together: SignupPresenter.new(:user => User.find(1), :user_login => 'james').
|
46
|
+
|
47
|
+
In this case, the login attribute will be updated on the user instance provided.
|
48
|
+
|
49
|
+
If you don't specify an instance, one will be created by calling Model.new
|
50
|
+
|
51
|
+
=== Validation
|
52
|
+
|
53
|
+
The #valid? method will return true or false based on the validity of the presented objects.
|
54
|
+
|
55
|
+
This is calculated by calling #valid? on them.
|
56
|
+
|
57
|
+
You can retrieve the errors in two ways.
|
58
|
+
|
59
|
+
1. By calling #errors on the presenter, which returns an instance of ActiveRecord::Errors where all the attributes are in type_name_attribute_name form (i.e. You'd retrieve an error on User#login, by calling @presenter.errors.on(:user_login)).
|
60
|
+
|
61
|
+
2. By calling @presenter.user_errors, or @presenter.user.errors to retrieve the errors from one presentable.
|
62
|
+
|
63
|
+
Both of these methods are compatible with error_messages_for. It just depends whether you'd like to show all the errors in one block, or whether you'd prefer to break them up.
|
64
|
+
|
65
|
+
=== Saving
|
66
|
+
|
67
|
+
You can save your presenter the same way you'd save an ActiveRecord object. Both #save, and #save! behave the same way they do on a normal AR model.
|
68
|
+
|
69
|
+
== Credits
|
70
|
+
|
71
|
+
ActivePresenter was created, and is maintained by {Daniel Haran}[http://danielharan.com] and {James Golick}[http://jamesgolick.com] on the train ride to {RubyFringe}[http://rubyfringe.com] from Montreal.
|
72
|
+
|
73
|
+
== License
|
74
|
+
|
75
|
+
ActivePresenter is available under the {MIT License}[http://en.wikipedia.org/wiki/MIT_License]
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require File.dirname(__FILE__)+'/lib/active_presenter'
|
4
|
+
Dir.glob(File.dirname(__FILE__)+'/lib/tasks/**/*.rake').each { |l| load l }
|
5
|
+
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
task :test do
|
9
|
+
Dir['test/**/*_test.rb'].each { |l| require l }
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Generate documentation for the ResourceController plugin.'
|
13
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
14
|
+
rdoc.rdoc_dir = 'rdoc'
|
15
|
+
rdoc.title = 'ActivePresenter'
|
16
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
17
|
+
rdoc.rdoc_files.include('README')
|
18
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
19
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module ActivePresenter
|
2
|
+
# Base class for presenters. See README for usage.
|
3
|
+
#
|
4
|
+
class Base
|
5
|
+
class_inheritable_accessor :presented
|
6
|
+
self.presented = {}
|
7
|
+
|
8
|
+
# Indicates which models are to be presented by this presenter.
|
9
|
+
# i.e.
|
10
|
+
#
|
11
|
+
# class SignupPresenter < ActivePresenter::Base
|
12
|
+
# presents User, Account
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
#
|
16
|
+
def self.presents(*types)
|
17
|
+
attr_accessor *types
|
18
|
+
|
19
|
+
types.each do |t|
|
20
|
+
define_method("#{t}_errors") do
|
21
|
+
send(t).errors
|
22
|
+
end
|
23
|
+
|
24
|
+
presented[t] = t.to_s.classify.constantize
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.human_attribute_name(attribute_name)
|
29
|
+
presentable_type = presented.keys.detect do |type|
|
30
|
+
attribute_name.to_s.starts_with?("#{type}_")
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute_name.to_s.gsub("#{presentable_type}_", "").humanize
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_accessor :errors
|
37
|
+
|
38
|
+
# Accepts arguments in two forms. For example, if you had a SignupPresenter that presented User, and Account, you could specify arguments in the following two forms:
|
39
|
+
#
|
40
|
+
# 1. SignupPresenter.new(:user_login => 'james', :user_password => 'swordfish', :user_password_confirmation => 'swordfish', :account_subdomain => 'giraffesoft')
|
41
|
+
# - This form is useful for initializing a new presenter from the params hash: i.e. SignupPresenter.new(params[:signup_presenter])
|
42
|
+
# 2. SignupPresenter.new(:user => User.find(1), :account => Account.find(2))
|
43
|
+
# - This form is useful if you have instances that you'd like to edit using the presenter. You can subsequently call presenter.update_attributes(params[:signup_presenter]) just like with a regular AR instance.
|
44
|
+
#
|
45
|
+
# Both forms can also be mixed together: SignupPresenter.new(:user => User.find(1), :user_login => 'james')
|
46
|
+
# In this case, the login attribute will be updated on the user instance provided.
|
47
|
+
#
|
48
|
+
# If you don't specify an instance, one will be created by calling Model.new
|
49
|
+
#
|
50
|
+
def initialize(args = {})
|
51
|
+
presented.each do |type, klass|
|
52
|
+
send("#{type}=", args[type].is_a?(klass) ? args.delete(type) : klass.new)
|
53
|
+
end
|
54
|
+
|
55
|
+
self.attributes = args
|
56
|
+
end
|
57
|
+
|
58
|
+
# Set the attributes of the presentable instances using the type_attribute form (i.e. user_login => 'james')
|
59
|
+
#
|
60
|
+
def attributes=(attrs)
|
61
|
+
attrs.each { |k,v| send("#{k}=", v) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Makes sure that the presenter is accurate about responding to presentable's attributes, even though they are handled by method_missing.
|
65
|
+
#
|
66
|
+
def respond_to?(method)
|
67
|
+
presented_attribute?(method) || super
|
68
|
+
end
|
69
|
+
|
70
|
+
# Handles the decision about whether to delegate getters and setters to presentable instances.
|
71
|
+
#
|
72
|
+
def method_missing(method_name, *args, &block)
|
73
|
+
presented_attribute?(method_name) ? delegate_message(method_name, *args, &block) : super
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns an instance of ActiveRecord::Errors with all the errors from the presentables merged in using the type_attribute form (i.e. user_login).
|
77
|
+
#
|
78
|
+
def errors
|
79
|
+
@errors ||= ActiveRecord::Errors.new(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns boolean based on the validity of the presentables by calling valid? on each of them.
|
83
|
+
#
|
84
|
+
def valid?
|
85
|
+
presented.keys.each do |type|
|
86
|
+
presented_inst = send(type)
|
87
|
+
|
88
|
+
merge_errors(presented_inst, type) unless presented_inst.valid?
|
89
|
+
end
|
90
|
+
|
91
|
+
errors.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
# Save all of the presentables, wrapped in a transaction.
|
95
|
+
#
|
96
|
+
# Returns true or false based on success.
|
97
|
+
#
|
98
|
+
def save
|
99
|
+
saved = false
|
100
|
+
|
101
|
+
ActiveRecord::Base.transaction do
|
102
|
+
if valid?
|
103
|
+
saved = presented_instances.map { |i| i.save(false) }.all?
|
104
|
+
raise ActiveRecord::Rollback unless saved # TODO: Does this happen implicitly?
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
saved
|
109
|
+
end
|
110
|
+
|
111
|
+
# Save all of the presentables, by calling each of their save! methods, wrapped in a transaction.
|
112
|
+
#
|
113
|
+
# Returns true on success, will raise otherwise.
|
114
|
+
#
|
115
|
+
def save!
|
116
|
+
ActiveRecord::Base.transaction do
|
117
|
+
valid? # collect errors before potential exception raise
|
118
|
+
presented_instances.each { |i| i.save! }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Update attributes, and save the presentables
|
123
|
+
#
|
124
|
+
# Returns true or false based on success.
|
125
|
+
#
|
126
|
+
def update_attributes(attrs)
|
127
|
+
self.attributes = attrs
|
128
|
+
save
|
129
|
+
end
|
130
|
+
|
131
|
+
protected
|
132
|
+
def presented_instances
|
133
|
+
presented.keys.map { |key| send(key) }
|
134
|
+
end
|
135
|
+
|
136
|
+
def delegate_message(method_name, *args, &block)
|
137
|
+
presentable = presentable_for(method_name)
|
138
|
+
send(presentable).send(flatten_attribute_name(method_name, presentable), *args, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
def presentable_for(method_name)
|
142
|
+
presented.keys.detect do |type|
|
143
|
+
method_name.to_s.starts_with?(attribute_prefix(type))
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def presented_attribute?(method_name)
|
148
|
+
!presentable_for(method_name).nil?
|
149
|
+
end
|
150
|
+
|
151
|
+
def flatten_attribute_name(name, type)
|
152
|
+
name.to_s.gsub(/^#{attribute_prefix(type)}/, '')
|
153
|
+
end
|
154
|
+
|
155
|
+
def attribute_prefix(type)
|
156
|
+
"#{type}_"
|
157
|
+
end
|
158
|
+
|
159
|
+
def merge_errors(presented_inst, type)
|
160
|
+
presented_inst.errors.each do |att,msg|
|
161
|
+
errors.add(attribute_prefix(type)+att, msg)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/tasks/gem.rake
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rake/gempackagetask'
|
2
|
+
|
3
|
+
task :clean => :clobber_package
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = ActivePresenter::NAME
|
7
|
+
s.version = ActivePresenter::VERSION::STRING
|
8
|
+
s.summary =
|
9
|
+
s.description = "ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)"
|
10
|
+
s.author = "James Golick & Daniel Haran"
|
11
|
+
s.email = 'james@giraffesoft.ca'
|
12
|
+
s.homepage = 'http://jamesgolick.com/active_presenter'
|
13
|
+
s.rubyforge_project = 'active_presenter'
|
14
|
+
s.has_rdoc = true
|
15
|
+
|
16
|
+
s.required_ruby_version = '>= 1.8.5'
|
17
|
+
|
18
|
+
s.files = %w(README LICENSE Rakefile) +
|
19
|
+
Dir.glob("{lib,test}/**/*")
|
20
|
+
|
21
|
+
s.require_path = "lib"
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::GemPackageTask.new(spec) do |p|
|
25
|
+
p.gem_spec = spec
|
26
|
+
end
|
27
|
+
|
28
|
+
task :tag_warn do
|
29
|
+
puts "*" * 40
|
30
|
+
puts "Don't forget to tag the release:"
|
31
|
+
puts
|
32
|
+
puts " git tag -a v#{ActivePresenter::VERSION::STRING}"
|
33
|
+
puts
|
34
|
+
puts "or run rake tag"
|
35
|
+
puts "*" * 40
|
36
|
+
end
|
37
|
+
|
38
|
+
task :tag do
|
39
|
+
sh "git tag -a v#{ActivePresenter::VERSION::STRING}"
|
40
|
+
end
|
41
|
+
task :gem => :tag_warn
|
42
|
+
|
43
|
+
namespace :gem do
|
44
|
+
namespace :upload do
|
45
|
+
|
46
|
+
desc 'Upload gems (ruby & win32) to rubyforge.org'
|
47
|
+
task :rubyforge => :gem do
|
48
|
+
sh 'rubyforge login'
|
49
|
+
sh "rubyforge add_release giraffesoft active_presenter #{ActivePresenter::VERSION::STRING} pkg/#{spec.full_name}.gem"
|
50
|
+
sh "rubyforge add_file giraffesoft active_presenter #{ActivePresenter::VERSION::STRING} pkg/#{spec.full_name}.gem"
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
task :install => [:clobber, :package] do
|
57
|
+
sh "sudo gem install pkg/#{spec.full_name}.gem"
|
58
|
+
end
|
59
|
+
|
60
|
+
task :uninstall => :clean do
|
61
|
+
sh "sudo gem uninstall -v #{ActivePresenter::VERSION::STRING} -x #{ActivePresenter::NAME}"
|
62
|
+
end
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/test_helper'
|
2
|
+
|
3
|
+
Expectations do
|
4
|
+
expect :user => User, :account => Account do
|
5
|
+
SignupPresenter.presented
|
6
|
+
end
|
7
|
+
|
8
|
+
expect User.create!(hash_for_user) do |u|
|
9
|
+
SignupPresenter.new(:user => u.expected).user
|
10
|
+
end
|
11
|
+
|
12
|
+
expect User do
|
13
|
+
SignupPresenter.new.user
|
14
|
+
end
|
15
|
+
|
16
|
+
expect User.any_instance.to.receive(:login=).with('james') do
|
17
|
+
SignupPresenter.new(:user_login => 'james')
|
18
|
+
end
|
19
|
+
|
20
|
+
expect 'mymockvalue' do
|
21
|
+
User.any_instance.stubs(:login).returns('mymockvalue')
|
22
|
+
SignupPresenter.new.user_login
|
23
|
+
end
|
24
|
+
|
25
|
+
expect User.any_instance.to.receive(:login=).with('mymockvalue') do
|
26
|
+
SignupPresenter.new.user_login = 'mymockvalue'
|
27
|
+
end
|
28
|
+
|
29
|
+
expect SignupPresenter.new.not.to.be.valid?
|
30
|
+
expect SignupPresenter.new(:user => User.new(hash_for_user)).to.be.valid?
|
31
|
+
|
32
|
+
expect ActiveRecord::Errors do
|
33
|
+
s = SignupPresenter.new
|
34
|
+
s.valid?
|
35
|
+
s.errors
|
36
|
+
end
|
37
|
+
|
38
|
+
expect ActiveRecord::Errors do
|
39
|
+
s = SignupPresenter.new
|
40
|
+
s.valid?
|
41
|
+
s.user_errors
|
42
|
+
end
|
43
|
+
|
44
|
+
expect ActiveRecord::Errors do
|
45
|
+
s = SignupPresenter.new
|
46
|
+
s.valid?
|
47
|
+
s.account_errors
|
48
|
+
end
|
49
|
+
|
50
|
+
expect String do
|
51
|
+
s = SignupPresenter.new
|
52
|
+
s.valid?
|
53
|
+
s.errors.on(:user_login)
|
54
|
+
end
|
55
|
+
|
56
|
+
expect ActiveRecord::Base.to.receive(:transaction) do
|
57
|
+
s = SignupPresenter.new
|
58
|
+
s.save
|
59
|
+
end
|
60
|
+
|
61
|
+
expect User.any_instance.to.receive(:save) do
|
62
|
+
s = SignupPresenter.new :user => User.new(hash_for_user)
|
63
|
+
s.save
|
64
|
+
end
|
65
|
+
|
66
|
+
expect Account.any_instance.to.receive(:save) do
|
67
|
+
s = SignupPresenter.new :user => User.new(hash_for_user)
|
68
|
+
s.save
|
69
|
+
end
|
70
|
+
|
71
|
+
expect SignupPresenter.new.not.to.be.save
|
72
|
+
|
73
|
+
expect ActiveRecord::Rollback do
|
74
|
+
ActiveRecord::Base.stubs(:transaction).yields
|
75
|
+
User.any_instance.stubs(:save).returns(false)
|
76
|
+
Account.any_instance.stubs(:save).returns(false)
|
77
|
+
s = SignupPresenter.new :user => User.new(hash_for_user)
|
78
|
+
s.save
|
79
|
+
end
|
80
|
+
|
81
|
+
expect ActiveRecord::Base.to.receive(:transaction) do
|
82
|
+
s = SignupPresenter.new
|
83
|
+
s.save!
|
84
|
+
end
|
85
|
+
|
86
|
+
expect User.any_instance.to.receive(:save!) do
|
87
|
+
s = SignupPresenter.new
|
88
|
+
s.save!
|
89
|
+
end
|
90
|
+
|
91
|
+
expect Account.any_instance.to.receive(:save!) do
|
92
|
+
User.any_instance.stubs(:save!)
|
93
|
+
s = SignupPresenter.new
|
94
|
+
s.save!
|
95
|
+
end
|
96
|
+
|
97
|
+
expect ActiveRecord::RecordInvalid do
|
98
|
+
SignupPresenter.new.save!
|
99
|
+
end
|
100
|
+
|
101
|
+
expect SignupPresenter.new(:user => User.new(hash_for_user)).to.be.save!
|
102
|
+
|
103
|
+
expect SignupPresenter.new.to.be.respond_to?(:user_login)
|
104
|
+
expect SignupPresenter.new.to.be.respond_to?(:valid?) # just making sure i didn't break everything :)
|
105
|
+
|
106
|
+
expect User.create!(hash_for_user).not.to.be.login_changed? do |user|
|
107
|
+
s = SignupPresenter.new(:user => user)
|
108
|
+
s.update_attributes :user_login => 'Something Totally Different'
|
109
|
+
end
|
110
|
+
|
111
|
+
expect SignupPresenter.new(:user => User.create!(hash_for_user)).to.receive(:save) do |s|
|
112
|
+
s.update_attributes :user_login => 'Something'
|
113
|
+
end
|
114
|
+
|
115
|
+
expect 'Something Different' do
|
116
|
+
s = SignupPresenter.new
|
117
|
+
s.update_attributes :user_login => 'Something Different'
|
118
|
+
s.user_login
|
119
|
+
end
|
120
|
+
|
121
|
+
# this is a regression test to make sure that _title is working. we had a weird conflict with using String#delete
|
122
|
+
expect 'something' do
|
123
|
+
s = SignupPresenter.new :account_title => 'something'
|
124
|
+
s.account_title
|
125
|
+
end
|
126
|
+
|
127
|
+
expect String do
|
128
|
+
s = SignupPresenter.new
|
129
|
+
s.save
|
130
|
+
s.errors.on(:user_login)
|
131
|
+
end
|
132
|
+
|
133
|
+
expect String do
|
134
|
+
s = SignupPresenter.new
|
135
|
+
s.save! rescue
|
136
|
+
s.errors.on(:user_login)
|
137
|
+
end
|
138
|
+
|
139
|
+
expect 'Login' do
|
140
|
+
SignupPresenter.human_attribute_name(:user_login)
|
141
|
+
end
|
142
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__)+'/../lib/active_presenter'
|
2
|
+
require 'expectations'
|
3
|
+
|
4
|
+
ActiveRecord::Base.configurations = {'sqlite3' => {:adapter => 'sqlite3', :database => ':memory:'}}
|
5
|
+
ActiveRecord::Base.establish_connection('sqlite3')
|
6
|
+
|
7
|
+
ActiveRecord::Schema.define(:version => 0) do
|
8
|
+
create_table :users do |t|
|
9
|
+
t.boolean :admin, :default => false
|
10
|
+
t.string :login, :default => ''
|
11
|
+
t.string :password, :default => ''
|
12
|
+
end
|
13
|
+
|
14
|
+
create_table :accounts do |t|
|
15
|
+
t.string :subdomain, :default => ''
|
16
|
+
t.string :title, :default => ''
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class User < ActiveRecord::Base
|
21
|
+
validates_presence_of :login, :password
|
22
|
+
end
|
23
|
+
class Account < ActiveRecord::Base; end
|
24
|
+
|
25
|
+
class SignupPresenter < ActivePresenter::Base
|
26
|
+
presents :account, :user
|
27
|
+
end
|
28
|
+
|
29
|
+
def hash_for_user(opts = {})
|
30
|
+
{:login => 'jane', :password => 'seekrit' }.merge(opts)
|
31
|
+
end
|
32
|
+
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_presenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Golick & Daniel Haran
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-27 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)
|
17
|
+
email: james@giraffesoft.ca
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
28
|
+
- lib/active_presenter
|
29
|
+
- lib/active_presenter/base.rb
|
30
|
+
- lib/active_presenter/version.rb
|
31
|
+
- lib/active_presenter.rb
|
32
|
+
- lib/tasks
|
33
|
+
- lib/tasks/gem.rake
|
34
|
+
- test/base_test.rb
|
35
|
+
- test/test_helper.rb
|
36
|
+
has_rdoc: true
|
37
|
+
homepage: http://jamesgolick.com/active_presenter
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.8.5
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project: active_presenter
|
58
|
+
rubygems_version: 1.1.1
|
59
|
+
signing_key:
|
60
|
+
specification_version: 2
|
61
|
+
summary: ActivePresenter is the presenter library you already know! (...if you know ActiveRecord)
|
62
|
+
test_files: []
|
63
|
+
|