dao 5.6.1 → 7.0.0

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