dao 5.5.1 → 8.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8027aaf83bcaae5677e03b94f45a721af6e0a9b85452a495757bca6fda993775
4
+ data.tar.gz: 904f11383d38fe16ad1c03013e986ee12abab72b60bfa2e86420c3681ad5e0a1
5
+ SHA512:
6
+ metadata.gz: 7ae990d1a7101ef449a2d09ab244221071fa7b5d9abb6b261c23e74f7410d9a710a437f458aec91475811b451a14fc5e982c11fda9e268550395e5eb2793cfa3
7
+ data.tar.gz: 49ce79df7587bdf270d72e08f2f0f7586efb1fd9573feb63a9996a74a2df62dd5f5a2536b08bcebb329be3730d5fef8f77c2b40e0a5f7dc703649235a091ef9b
@@ -0,0 +1,258 @@
1
+ # dao
2
+
3
+ ## SYNOPSIS
4
+
5
+ a sa-weet-ass library for structuring rails applications using the 'data
6
+ access object' design pattern. dao consists of two main data access
7
+ objects, *api* objects and *conducer* objects. conducers combine the
8
+ presenter pattern with the conductor pattern.
9
+
10
+
11
+ ### API
12
+
13
+ class Api < Dao::Api
14
+ call('/posts') do
15
+ get do
16
+ data[:posts] = Post.all.map{|post| post.attributes}
17
+ end
18
+
19
+ post do
20
+ post = Post.new(params[:post])
21
+
22
+ if post.save
23
+ data[:post] = post.attributes
24
+ else
25
+ status 420
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ ### CONDUCER
32
+
33
+ * TODO
34
+
35
+ wikipedia has this to say about dao in general
36
+
37
+ >
38
+ > In computer software, a data access object (DAO) is an object that
39
+ > provides an abstract interface to some type of database or other
40
+ > persistence mechanism. By mapping application calls to the persistence
41
+ > layer, DAOs provide some specific data operations without exposing
42
+ > details of the database. This isolation supports the single
43
+ > responsibility principle. It separates what data accesses the
44
+ > application needs, in terms of domain-specific objects and data types
45
+ > (the public interface of the DAO), from how these needs can be satisfied
46
+ > with a specific DBMS, database schema, etc. (the implementation of the
47
+ > DAO).
48
+ >
49
+ -- http://en.wikipedia.org/wiki/Data_access_object
50
+
51
+ and this to say about the single responsibility principle
52
+
53
+ >
54
+ > In object-oriented programming, the single responsibility principle
55
+ > states that every class should have a single responsibility, and that
56
+ > responsibility should be entirely encapsulated by the class. All its
57
+ > services should be narrowly aligned with that responsibility.
58
+
59
+ > Responsibility [is defined] as a reason to change, and [single
60
+ > responsibility means] that a class or module should have one, and only
61
+ > one, reason to change. As an example, consider a module that compiles and
62
+ > prints a report. Such a module can be changed for two reasons. First,
63
+ > the content of the report can change. Second, the format of the report
64
+ > can change. These two things change for very different causes; one
65
+ > substantive, and one cosmetic. The single responsibility principle says
66
+ > that these two aspects of the problem are really two separate
67
+ > responsibilities, and should therefore be in separate classes or
68
+ > modules. It would be a bad design to couple two things that change for
69
+ > different reasons at different times.
70
+ >
71
+ -- http://en.wikipedia.org/wiki/Single_responsibility_principle
72
+
73
+ even though rails is the sweet, its ActiveRecord class violates (or, at
74
+ least, encourages a programmer to violate) the single responsibility
75
+ principle
76
+
77
+ this leads to obvious problems
78
+
79
+ >
80
+ > Jim Weirich, at the end of his SOLID Ruby Talk at the 2009 Ruby
81
+ > Conference, asks the audience: "ActiveRecord objects implement a domain
82
+ > concept and a persistence concept. Does this violate the SRP (Single
83
+ > Responsibility Principle)?" The audience agrees that it does violate the
84
+ > SRP. Jim asks if this bothers them. Many members of the audience say
85
+ > yes. Why? It makes testing harder. It makes the persistence object a lot
86
+ > heavier.
87
+ >
88
+ -- http://programmers.stackexchange.com/questions/119352/does-the-activerecord-pattern-follow-encourage-the-solid-design-principles#comment293734_119352
89
+
90
+ and subtle yet sweeping consequences (as described by uncle bob)
91
+
92
+ >
93
+ > The problem I have with ActiveRecord is that it creates confusion about
94
+ > ... two very different styles of programming. A database table is a
95
+ > data structure. It has exposed data and no behavior. But an ActiveRecord
96
+ > appears to be an object. It has “hidden” data, and exposed behavior. I
97
+ > put the word “hidden” in quotes because the data is, in fact, not
98
+ > hidden. Almost all ActiveRecord derivatives export the database columns
99
+ > through accessors and mutators. Indeed, the Active Record is meant to be
100
+ > used like a data structure.
101
+
102
+ > On the other hand, many people put business rule methods in their
103
+ > ActiveRecord classes; which makes them appear to be objects. This leads
104
+ > to a dilemma. On which side of the line does the Active Record really
105
+ > fall? Is it an object? Or is it a data structure?
106
+
107
+ > This dilemma is the basis for the oft-cited impedance mismatch between
108
+ > relational databases and object oriented languages. Tables are data
109
+ > structures, not classes. Objects are encapsulated behavior, not database
110
+ > rows.
111
+
112
+ > ...
113
+
114
+ > The problem is that Active Records are data structures. Putting business
115
+ > rule methods in them doesn’t turn them into true objects. In the end,
116
+ > the algorithms that employ ActiveRecords are vulnerable to changes in
117
+ > schema, and changes in type. They are not immune to changes in type, the
118
+ > way algorithms that use objects are.
119
+
120
+ > ...
121
+
122
+ > So applications built around ActiveRecord are applications built around
123
+ > data structures. And applications that are built around data structures
124
+ > are procedural—they are not object oriented. The opportunity we miss
125
+ > when we structure our applications around ActiveRecord is the
126
+ > opportunity to use object oriented design.
127
+ >
128
+ -- https://sites.google.com/site/unclebobconsultingllc/active-record-vs-objects
129
+
130
+ and a clear solution (again, uncle bob)
131
+
132
+ > I am not recommending against the use of ActiveRecord. I think the
133
+ > pattern is very useful. What I am advocating is a separation between the
134
+ > application and ActiveRecord.
135
+
136
+ > ActiveRecord belongs in the layer that separates the database from the
137
+ > application. It makes a very convenient halfway-house between the hard
138
+ > data structures of database tables, and the behavior exposing objects in
139
+ > the application.
140
+
141
+ > Applications should be designed and structured around objects, not data
142
+ > structures. Those objects should expose business behaviors, and hide any
143
+ > vestige of the database.
144
+ >
145
+ -- https://sites.google.com/site/unclebobconsultingllc/active-record-vs-objects
146
+
147
+ welcome to the dao
148
+
149
+
150
+ ## DESCRIPTION
151
+
152
+ ### API
153
+
154
+ applications that are written on dao look like this in ruby
155
+
156
+ result = api.call('/posts/new', params)
157
+
158
+ and like this in javascript
159
+
160
+ result = api.call('/posts/new', params)
161
+
162
+ in command-line applications they look like this
163
+
164
+ result = api.call('/posts/new', params)
165
+
166
+ and in tests this syntax is used
167
+
168
+ result = api.call('/posts/new', params)
169
+
170
+ when a developer wants to understand the interface of a dao application she does
171
+ this
172
+
173
+ vi app/api.rb
174
+
175
+ when a developer of a dao application wants to play with a dao application
176
+ interactively she does
177
+
178
+ (rails console)
179
+
180
+ > api = Api.new result = api.call('/posts/new', params)
181
+
182
+ when a remote client wants to understand the api of a dao application she
183
+ does
184
+
185
+ curl --silent http://dao.app.com/api | less
186
+
187
+
188
+
189
+ this kind of brutally consistent interface is made possible by structuring
190
+ access to data around the finest data structure of all time - the hash.
191
+ in the case of dao the hash is a well structured and slightly clever hash,
192
+ but a simple hash interface is the basis of every bit of goodness dao has
193
+ to offer.
194
+
195
+ in dao, application developers do not bring models into controllers and,
196
+ especially not into views. instead, a unified interface to application
197
+ logic and data is used everywhere: in tests, in controllers, from the
198
+ command-line, and also from javascript.
199
+
200
+ this seperation of concerns brings with it many, many desirable qualities:
201
+
202
+ - total seperation of concerns between the front and back end of a web
203
+ application. when developers are using dao changes to the data model
204
+ have zero effect on controllers and views.
205
+
206
+ - issues related to having models in controllers and views such as
207
+ difficulty reasoning about caching and n+1 queries in views killing
208
+ the db simply disappear.
209
+
210
+ - bad programming practices like using quasi-global variables
211
+ (current_user) or decorating models with view specific attributes
212
+ (password_verification) are no longer needed.
213
+
214
+ - developers are able to reason over the abilities of an application by
215
+ reading only a few source files.
216
+
217
+ - databases can be swapped, mixed, or alternate storage/caching
218
+ mechanisms added at any time without affecting the application's
219
+ controllers or views.
220
+
221
+ - transition from form based views to semi-ajax ones to fully-ajax ones
222
+ is direct.
223
+
224
+ - forms and interfaces that involve dozens of models are as easy to deal
225
+ with as simple ones.
226
+
227
+ - code can be optimized at the interface.
228
+
229
+ ## READING
230
+
231
+ * http://blog.plataformatec.com.br/2012/03/barebone-models-to-use-with-actionpack-in-rails-4-0/
232
+ * http://martinfowler.com/eaaCatalog/serviceLayer.html
233
+ * http://blog.firsthand.ca/2011/10/rails-is-not-your-application.html
234
+ * http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/dao.html
235
+ * http://www.codefutures.com/data-access-object/
236
+ * http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
237
+ * http://www.paperplanes.de/2010/5/7/activerecord_callbacks_ruined_my_life.html
238
+ * http://google-styleguide.googlecode.com/svn/trunk/jsoncstyleguide.xml
239
+ * http://pragdave.blogs.pragprog.com/pragdave/2007/03/the_radar_archi.html
240
+ * http://borisstaal.com/post/22586260753/mvc-in-a-browser-vs-reality
241
+
242
+
243
+ ## INSTALL
244
+
245
+ gem 'dao', :path => File.expand_path('..') ### Gemfile
246
+ rails generate dao api
247
+ vim -o app/api.rb app/controllers/api_controller.rb
248
+ curl --silent http://0.0.0.0:3000/api
249
+ curl --silent http://0.0.0.0:3000/api/ping
250
+
251
+ ## HISTORY
252
+
253
+ ### 4.0.0
254
+ - dao depends has tied itself to rails, for better or worse...
255
+ - drop custom form encoding. just use a rack-like approach.
256
+ - dao form parameter encoding has changed slightly to 'dao[/api/path][x,y,z]=42'
257
+ - dao form paramters are now preparsed in a before filter
258
+
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- This.rubyforge_project = 'codeforpeople'
1
+ #This.rubyforge_project = 'codeforpeople'
2
2
  This.author = "Ara T. Howard"
3
3
  This.email = "ara.t.howard@gmail.com"
4
4
  This.homepage = "https://github.com/ahoward/#{ This.lib }"
5
5
 
6
6
  task :license do
7
- open('LICENSE', 'w'){|fd| fd.puts "same as ruby's"}
7
+ open('LICENSE', 'w'){|fd| fd.puts "Ruby"}
8
8
  end
9
9
 
10
10
  task :default do
@@ -32,7 +32,7 @@ def run_tests!(which = nil)
32
32
 
33
33
  test_rbs.each_with_index do |test_rb, index|
34
34
  testno = index + 1
35
- command = "#{ This.ruby } -I ./lib -I ./test/lib #{ test_rb }"
35
+ command = "#{ This.ruby } -w -I ./lib -I ./test/lib #{ test_rb }"
36
36
 
37
37
  puts
38
38
  say(div, :color => :cyan, :bold => true)
@@ -93,7 +93,7 @@ task :gemspec do
93
93
  test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
94
94
  summary = object.respond_to?(:summary) ? object.summary : "summary: #{ lib } kicks the ass"
95
95
  description = object.respond_to?(:description) ? object.description : "description: #{ lib } kicks the ass"
96
- license = object.respond_to?(:license) ? object.license : "same as ruby's"
96
+ license = object.respond_to?(:license) ? object.license : "Ruby"
97
97
 
98
98
  if This.extensions.nil?
99
99
  This.extensions = []
@@ -145,7 +145,6 @@ task :gemspec do
145
145
 
146
146
  spec.extensions.push(*<%= extensions.inspect %>)
147
147
 
148
- spec.rubyforge_project = <%= This.rubyforge_project.inspect %>
149
148
  spec.author = <%= This.author.inspect %>
150
149
  spec.email = <%= This.email.inspect %>
151
150
  spec.homepage = <%= This.homepage.inspect %>
@@ -297,7 +296,7 @@ BEGIN {
297
296
 
298
297
  # discover full path to this ruby executable
299
298
  #
300
- c = Config::CONFIG
299
+ c = RbConfig::CONFIG
301
300
  bindir = c["bindir"] || c['BINDIR']
302
301
  ruby_install_name = c['ruby_install_name'] || c['RUBY_INSTALL_NAME'] || 'ruby'
303
302
  ruby_ext = c['EXEEXT'] || ''
@@ -3,22 +3,20 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "dao"
6
- spec.version = "5.5.1"
6
+ spec.version = "8.0.1"
7
7
  spec.platform = Gem::Platform::RUBY
8
8
  spec.summary = "dao"
9
- spec.description = "presenter, conducer, api, and better form objects for you rails' pleasure"
10
- spec.license = "same as ruby's"
9
+ spec.description = "presenter, conductor, api, and better form objects for you rails' pleasure"
10
+ spec.license = "Ruby"
11
11
 
12
12
  spec.files =
13
- ["Gemfile",
14
- "Gemfile.lock",
15
- "README",
13
+ ["README.md",
16
14
  "Rakefile",
17
- "a.rb",
18
15
  "dao.gemspec",
19
16
  "lib",
20
17
  "lib/dao",
21
18
  "lib/dao.rb",
19
+ "lib/dao/_lib.rb",
22
20
  "lib/dao/active_record.rb",
23
21
  "lib/dao/api",
24
22
  "lib/dao/api.rb",
@@ -29,6 +27,7 @@ Gem::Specification::new do |spec|
29
27
  "lib/dao/api/modes.rb",
30
28
  "lib/dao/api/routes.rb",
31
29
  "lib/dao/blankslate.rb",
30
+ "lib/dao/coerce.rb",
32
31
  "lib/dao/conducer",
33
32
  "lib/dao/conducer.rb",
34
33
  "lib/dao/conducer/active_model.rb",
@@ -43,6 +42,7 @@ Gem::Specification::new do |spec|
43
42
  "lib/dao/endpoint.rb",
44
43
  "lib/dao/engine.rb",
45
44
  "lib/dao/errors.rb",
45
+ "lib/dao/errors2html.rb",
46
46
  "lib/dao/exceptions.rb",
47
47
  "lib/dao/extractor.rb",
48
48
  "lib/dao/form.rb",
@@ -86,8 +86,13 @@ Gem::Specification::new do |spec|
86
86
  "lib/dao/validations/common.rb",
87
87
  "lib/dao/validations/instance.rb",
88
88
  "lib/dao/validations/validator.rb",
89
- "notes",
90
- "notes/ara.txt",
89
+ "lib/dao/wrap.rb",
90
+ "public",
91
+ "public/system",
92
+ "public/system/uploads",
93
+ "tasks",
94
+ "tasks/default.rake",
95
+ "tasks/this.rb",
91
96
  "test",
92
97
  "test/active_model_conducer_lint_test.rb",
93
98
  "test/api_test.rb",
@@ -96,10 +101,11 @@ Gem::Specification::new do |spec|
96
101
  "test/data/han-solo.jpg",
97
102
  "test/errors_test.rb",
98
103
  "test/form_test.rb",
99
- "test/helper.rb",
100
104
  "test/leak.rb",
105
+ "test/rake_rerun_reporter.rb",
101
106
  "test/support_test.rb",
102
- "test/testing.rb",
107
+ "test/test_helper.rb",
108
+ "test/util.rb",
103
109
  "test/validations_test.rb"]
104
110
 
105
111
  spec.executables = []
@@ -109,30 +115,19 @@ Gem::Specification::new do |spec|
109
115
  spec.test_files = nil
110
116
 
111
117
 
112
- spec.add_dependency(*["rails", " ~> 3.1"])
118
+ spec.add_dependency(*["rails", " ~> 6.0"])
113
119
 
114
- spec.add_dependency(*["map", " >= 6.0.0"])
120
+ spec.add_dependency(*["map", " ~> 6.6"])
115
121
 
116
- spec.add_dependency(*["fattr", " >= 2.2"])
122
+ spec.add_dependency(*["fattr", " ~> 2.4"])
117
123
 
118
- spec.add_dependency(*["coerce", " >= 0.0.3"])
124
+ spec.add_dependency(*["tagz", " ~> 9.10"])
119
125
 
120
- spec.add_dependency(*["tagz", " >= 9.9.2"])
121
-
122
- spec.add_dependency(*["multi_json", " >= 1.0.3"])
123
-
124
- spec.add_dependency(*["uuidtools", " >= 2.1.2"])
125
-
126
- spec.add_dependency(*["wrap", " >= 1.5.0"])
127
-
128
- spec.add_dependency(*["rails_current", " >= 1.8.0"])
129
-
130
- spec.add_dependency(*["rails_errors2html", " >= 1.3.0"])
126
+ spec.add_dependency(*["rails_current", " ~> 2.2"])
131
127
 
132
128
 
133
129
  spec.extensions.push(*[])
134
130
 
135
- spec.rubyforge_project = "codeforpeople"
136
131
  spec.author = "Ara T. Howard"
137
132
  spec.email = "ara.t.howard@gmail.com"
138
133
  spec.homepage = "https://github.com/ahoward/dao"
data/lib/dao.rb CHANGED
@@ -7,86 +7,49 @@
7
7
  require 'cgi'
8
8
  require 'tmpdir'
9
9
  require 'yaml'
10
+ require 'securerandom'
11
+ require 'json'
10
12
 
11
- # dao libs
12
13
  #
13
- module Dao
14
- Version = '5.5.1' unless defined?(Version)
15
-
16
- def version
17
- Dao::Version
18
- end
19
-
20
- def dependencies
21
- {
22
- 'rails' => [ 'rails' , ' ~> 3.1' ] ,
23
- 'map' => [ 'map' , ' >= 6.0.0' ] ,
24
- 'fattr' => [ 'fattr' , ' >= 2.2' ] ,
25
- 'coerce' => [ 'coerce' , ' >= 0.0.3' ] ,
26
- 'tagz' => [ 'tagz' , ' >= 9.9.2' ] ,
27
- 'multi_json' => [ 'multi_json' , ' >= 1.0.3' ] ,
28
- 'uuidtools' => [ 'uuidtools' , ' >= 2.1.2' ] ,
29
- 'wrap' => [ 'wrap' , ' >= 1.5.0' ] ,
30
- 'rails_current' => [ 'rails_current' , ' >= 1.8.0' ] ,
31
- 'rails_errors2html' => [ 'rails_errors2html' , ' >= 1.3.0' ] ,
32
- }
33
- end
34
-
35
- def description
36
- "presenter, conducer, api, and better form objects for you rails' pleasure"
37
- end
38
-
39
- def libdir(*args, &block)
40
- @libdir ||= File.expand_path(__FILE__).sub(/\.rb$/,'')
41
- args.empty? ? @libdir : File.join(@libdir, *args)
42
- ensure
43
- if block
44
- begin
45
- $LOAD_PATH.unshift(@libdir)
46
- block.call()
47
- ensure
48
- $LOAD_PATH.shift()
49
- end
50
- end
51
- end
52
-
53
- def load(*libs)
54
- libs = libs.join(' ').scan(/[^\s+]+/)
55
- Dao.libdir{ libs.each{|lib| Kernel.load(lib) } }
56
- end
57
-
58
- extend(Dao)
59
- end
14
+ require_relative 'dao/_lib.rb'
60
15
 
61
16
  # gems
62
17
  #
63
- begin
18
+ begin
64
19
  require 'rubygems'
65
20
  rescue LoadError
66
21
  nil
67
22
  end
68
23
 
69
- if defined?(gem)
70
- Dao.dependencies.each do |lib, dependency|
71
- gem(*dependency)
72
- require(lib)
73
- end
24
+ Dao.dependencies.each do |lib, dependency|
25
+ gem(*dependency) if defined?(gem)
26
+ require(lib)
74
27
  end
75
28
 
29
+ # rails frameworks
30
+ #
76
31
  %w[
77
32
  action_controller
78
- active_resource
79
33
  active_support
34
+ active_model
80
35
  ].each do |framework|
81
36
  begin
82
37
  require "#{ framework }/railtie"
83
38
  rescue LoadError
39
+ begin
40
+ require "#{ framework }"
41
+ rescue LoadError
42
+ raise
43
+ end
84
44
  end
85
45
  end
86
46
 
87
-
47
+ # dao libs
48
+ #
88
49
  Dao.load %w[
89
50
  blankslate.rb
51
+ coerce.rb
52
+ wrap.rb
90
53
  instance_exec.rb
91
54
  extractor.rb
92
55
  exceptions.rb
@@ -97,6 +60,7 @@
97
60
  name.rb
98
61
  status.rb
99
62
  path_map.rb
63
+ errors2html.rb
100
64
  errors.rb
101
65
  messages.rb
102
66
  form.rb
@@ -120,23 +84,3 @@
120
84
  conducer.rb
121
85
  upload.rb
122
86
  ]
123
-
124
-
125
- unless defined?(::UUIDTools::Config)
126
- ::UUIDTools.module_eval do
127
- Config = ::RbConfig # shuts up warnings...
128
- end
129
- end
130
-
131
- # protect against rails' too clever reloading
132
- #
133
- =begin
134
- if defined?(Rails)
135
- unless defined?(unloadable)
136
- require 'active_support'
137
- require 'active_support/dependencies'
138
- end
139
- unloadable(Dao)
140
- end
141
- BEGIN{ Object.send(:remove_const, :Dao) if defined?(Dao) }
142
- =end