dao 5.6.1 → 7.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aa44a9f2c9e686fe6b08cd45e8b0517d8d03e336
4
+ data.tar.gz: 2c0e7da32f04b45de57f87b961e6cf4fa4e65ab6
5
+ SHA512:
6
+ metadata.gz: d20cdbe9a84bb0123364518b0f4dbad1520abc527f5422c15503454cdf6cbcf57ed24d8ddf87d9ac48e26ce1b695c823315562dafa6a3a573940448e49d66d74
7
+ data.tar.gz: a135cbbab52a6ac7f8632d77865a93bc4e38bac98526f4695ca55c1ab4e5c53212cf1598d0cc9caa61a90df538b313e8f2cae839ecb3ccb0fcc87ea02c11fc61
@@ -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
@@ -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)
@@ -62,8 +62,8 @@ end
62
62
 
63
63
  task :gemspec do
64
64
  ignore_extensions = ['git', 'svn', 'tmp', /sw./, 'bak', 'gem']
65
- ignore_directories = ['pkg', 'notes']
66
- ignore_files = ['test/log', 'a.rb']
65
+ ignore_directories = ['pkg']
66
+ ignore_files = ['test/log']
67
67
 
68
68
  shiteless =
69
69
  lambda do |list|
@@ -73,9 +73,9 @@ task :gemspec do
73
73
  ignore_extensions.any?{|ext| ext === extension}
74
74
  end
75
75
  list.delete_if do |entry|
76
- #next unless test(?d, entry)
77
- path = File.expand_path(entry)
78
- ignore_directories.any?{|dir| path =~ /^#{ Regexp.escape(File.expand_path(dir)) }/}
76
+ next unless test(?d, entry)
77
+ dirname = File.expand_path(entry)
78
+ ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
79
79
  end
80
80
  list.delete_if do |entry|
81
81
  next unless test(?f, entry)
@@ -3,21 +3,20 @@
3
3
 
4
4
  Gem::Specification::new do |spec|
5
5
  spec.name = "dao"
6
- spec.version = "5.6.1"
6
+ spec.version = "7.0.0"
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"
9
+ spec.description = "presenter, conductor, api, and better form objects for you rails' pleasure"
10
10
  spec.license = "same as ruby's"
11
11
 
12
12
  spec.files =
13
- ["Gemfile",
14
- "Gemfile.lock",
15
- "README",
13
+ ["README.md",
16
14
  "Rakefile",
17
15
  "dao.gemspec",
18
16
  "lib",
19
17
  "lib/dao",
20
18
  "lib/dao.rb",
19
+ "lib/dao/_lib.rb",
21
20
  "lib/dao/active_record.rb",
22
21
  "lib/dao/api",
23
22
  "lib/dao/api.rb",
@@ -42,6 +41,7 @@ Gem::Specification::new do |spec|
42
41
  "lib/dao/endpoint.rb",
43
42
  "lib/dao/engine.rb",
44
43
  "lib/dao/errors.rb",
44
+ "lib/dao/errors2html.rb",
45
45
  "lib/dao/exceptions.rb",
46
46
  "lib/dao/extractor.rb",
47
47
  "lib/dao/form.rb",
@@ -85,6 +85,14 @@ Gem::Specification::new do |spec|
85
85
  "lib/dao/validations/common.rb",
86
86
  "lib/dao/validations/instance.rb",
87
87
  "lib/dao/validations/validator.rb",
88
+ "notes",
89
+ "notes/ara.txt",
90
+ "public",
91
+ "public/system",
92
+ "public/system/uploads",
93
+ "tasks",
94
+ "tasks/default.rake",
95
+ "tasks/this.rb",
88
96
  "test",
89
97
  "test/active_model_conducer_lint_test.rb",
90
98
  "test/api_test.rb",
@@ -93,10 +101,11 @@ Gem::Specification::new do |spec|
93
101
  "test/data/han-solo.jpg",
94
102
  "test/errors_test.rb",
95
103
  "test/form_test.rb",
96
- "test/helper.rb",
97
104
  "test/leak.rb",
105
+ "test/rake_rerun_reporter.rb",
98
106
  "test/support_test.rb",
99
- "test/testing.rb",
107
+ "test/test_helper.rb",
108
+ "test/util.rb",
100
109
  "test/validations_test.rb"]
101
110
 
102
111
  spec.executables = []
@@ -106,25 +115,23 @@ Gem::Specification::new do |spec|
106
115
  spec.test_files = nil
107
116
 
108
117
 
109
- spec.add_dependency(*["rails", " ~> 3.1"])
118
+ spec.add_dependency(*["rails", " ~> 5.2"])
110
119
 
111
- spec.add_dependency(*["map", " >= 6.0.0"])
120
+ spec.add_dependency(*["map", " ~> 6.0"])
112
121
 
113
- spec.add_dependency(*["fattr", " >= 2.2"])
122
+ spec.add_dependency(*["fattr", " ~> 2.2"])
114
123
 
115
- spec.add_dependency(*["coerce", " >= 0.0.3"])
124
+ spec.add_dependency(*["coerce", " ~> 0.0"])
116
125
 
117
- spec.add_dependency(*["tagz", " >= 9.9.2"])
126
+ spec.add_dependency(*["tagz", " ~> 9.9"])
118
127
 
119
- spec.add_dependency(*["multi_json", " >= 1.0.3"])
128
+ spec.add_dependency(*["multi_json", " ~> 1.0"])
120
129
 
121
- spec.add_dependency(*["uuidtools", " >= 2.1.2"])
130
+ spec.add_dependency(*["uuidtools", " ~> 2.1"])
122
131
 
123
- spec.add_dependency(*["wrap", " >= 1.5.0"])
132
+ spec.add_dependency(*["wrap", " ~> 1.5"])
124
133
 
125
- spec.add_dependency(*["rails_current", " >= 1.8.0"])
126
-
127
- spec.add_dependency(*["rails_errors2html", " >= 1.3.0"])
134
+ spec.add_dependency(*["rails_current", " ~> 2.0"])
128
135
 
129
136
 
130
137
  spec.extensions.push(*[])
data/lib/dao.rb CHANGED
@@ -10,81 +10,37 @@
10
10
 
11
11
  # dao libs
12
12
  #
13
- module Dao
14
- Version = '5.6.1' unless defined?(Version)
13
+ require "map"
14
+ require "fattr"
15
+ require "coerce"
16
+ require "tagz"
17
+ require "multi_json"
18
+ require "uuidtools"
19
+ require "wrap"
20
+ require "rails_current"
15
21
 
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
60
-
61
- # gems
62
22
  #
63
- begin
64
- require 'rubygems'
65
- rescue LoadError
66
- nil
67
- end
68
-
69
- if defined?(gem)
70
- Dao.dependencies.each do |lib, dependency|
71
- gem(*dependency)
72
- require(lib)
73
- end
74
- end
23
+ require_relative 'dao/_lib.rb'
75
24
 
25
+ #
76
26
  %w[
77
27
  action_controller
78
- active_resource
79
28
  active_support
29
+ active_model
80
30
  ].each do |framework|
81
31
  begin
82
32
  require "#{ framework }/railtie"
83
33
  rescue LoadError
34
+ begin
35
+ require "#{ framework }"
36
+ rescue LoadError
37
+ raise
38
+ end
84
39
  end
85
40
  end
86
41
 
87
42
 
43
+ #
88
44
  Dao.load %w[
89
45
  blankslate.rb
90
46
  instance_exec.rb
@@ -97,6 +53,7 @@
97
53
  name.rb
98
54
  status.rb
99
55
  path_map.rb
56
+ errors2html.rb
100
57
  errors.rb
101
58
  messages.rb
102
59
  form.rb
@@ -127,16 +84,3 @@
127
84
  Config = ::RbConfig # shuts up warnings...
128
85
  end
129
86
  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