scaffolding_extensions 1.3.12 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +2 -7
- data/doc/datamapper.txt +20 -0
- data/lib/scaffolding_extensions/model/datamapper.rb +300 -0
- data/lib/scaffolding_extensions.rb +3 -0
- metadata +5 -2
data/README
CHANGED
@@ -29,6 +29,7 @@ Scaffolding Extensions currently supports:
|
|
29
29
|
* Object Relational Mappers
|
30
30
|
* ActiveRecord 2.3.5
|
31
31
|
* Sequel 3.8.0
|
32
|
+
* DataMapper 0.10.2 (see doc/datamapper.txt for details)
|
32
33
|
* Javascript Libaries (used for Ajax/Autocompleting)
|
33
34
|
* Prototype 1.6.0.3
|
34
35
|
* JQuery 1.2.3
|
@@ -37,17 +38,11 @@ Support for other web frameworks and ORMs can be added, see the
|
|
37
38
|
controller_spec.txt and model_spec.txt files for the methods that need to be
|
38
39
|
defined.
|
39
40
|
|
40
|
-
The current version of Scaffolding Extensions is quite different from older
|
41
|
-
versions (svn revision 89 and previous). Older versions of Rails should be
|
42
|
-
able to use an older version of the plugin, which won't be discussed further as
|
43
|
-
it is substantially different from the current version (see the conversion.txt
|
44
|
-
file for details).
|
45
|
-
|
46
41
|
You can get Scaffolding Extensions via git or as a gem:
|
47
42
|
|
48
43
|
* git: git://github.com/jeremyevans/scaffolding_extensions.git
|
49
44
|
* gem: sudo gem install scaffolding_extensions
|
50
|
-
* demo: http://
|
45
|
+
* demo: http://se-demo.heroku.com
|
51
46
|
* github: http://github.com/jeremyevans/scaffolding_extensions
|
52
47
|
* RDoc: http://scaffolding-ext.rubyforge.org
|
53
48
|
* Bug Tracker: http://rubyforge.org/tracker/?atid=22169&group_id=5726&func=browse
|
data/doc/datamapper.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The DataMapper module has some quirks, mainly:
|
2
|
+
|
3
|
+
1. For models that have the "storage_name" explicitly defined,
|
4
|
+
the "has n, :through => Resource" relation doesn't work well.
|
5
|
+
Don't use models, that have non-standard table names, or
|
6
|
+
create the habtm resource by hand (check the test application)
|
7
|
+
|
8
|
+
2. Because DataMapper uses a module instead of a superclass, you have
|
9
|
+
to add the appropriate scaffolding_extensions modules by hand.
|
10
|
+
The simplest way is to use the `add_scaffolding_methods` method in
|
11
|
+
your controller, or initialization script:
|
12
|
+
|
13
|
+
class Dm < Merb::Controller
|
14
|
+
add_scaffolding_methods [DmOfficer, DmMeeting, DmEmployee, DmGroup, DmPosition]
|
15
|
+
scaffold DmOfficer
|
16
|
+
scaffold DmMeeting
|
17
|
+
scaffold_all_models :only =>[DmEmployee, DmGroup, DmPosition]
|
18
|
+
end
|
19
|
+
|
20
|
+
You need dm-core, dm-validations, and do_sqlite3 in order to run the test_suite for scaffolding_extensions with datamapper.
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
ScaffoldingExtensions::MODEL_SUPERCLASSES << DataMapper::Resource
|
4
|
+
|
5
|
+
def get_key_array_safe(key)
|
6
|
+
if key.is_a?(Array) then
|
7
|
+
if key.length==1
|
8
|
+
key.first
|
9
|
+
else
|
10
|
+
key
|
11
|
+
end
|
12
|
+
else
|
13
|
+
key
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_ordering_options(ordopts)
|
18
|
+
result = []
|
19
|
+
if ordopts then
|
20
|
+
ordering = ordopts.dup
|
21
|
+
else
|
22
|
+
return nil
|
23
|
+
end
|
24
|
+
ordering = ordering.split(',') unless ordering.is_a?(Array)
|
25
|
+
ordering.each do |ord|
|
26
|
+
asc = :asc
|
27
|
+
if ord.upcase =~ /DESC/
|
28
|
+
asc = :desc
|
29
|
+
end
|
30
|
+
ord.gsub!(/[Dd][Ee][Ss][Cc]|[Aa][Ss][Cc]/,"")
|
31
|
+
ord.strip!
|
32
|
+
if ord =~ /(\w+)\.(\w+)/
|
33
|
+
tablename = $1
|
34
|
+
propertyname = $2
|
35
|
+
#TODO handling of associated orderings
|
36
|
+
#optionshash[:order] << DataMapper::Query::Direction.new(eval("#{tablename.downcase.gsub(/\b[a-z]/) { |a| a.upcase }.gsub(/\s/, "")
|
37
|
+
#}.properties[:#{propertyname.downcase}]"),asc)
|
38
|
+
result << eval(":#{propertyname}.#{asc.to_s}")
|
39
|
+
elsif ord =~ /(\w+)/
|
40
|
+
propertyname = $1
|
41
|
+
result << eval(":#{propertyname}.#{asc.to_s}")
|
42
|
+
else
|
43
|
+
# TODO Warning message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
# Instance methods added to DataMapper::Resource to allow it to work with Scaffolding Extensions.
|
50
|
+
module ScaffoldingExtensions::DataMapper
|
51
|
+
# Get value for given attribute
|
52
|
+
def scaffold_attribute_value(field)
|
53
|
+
self[field]
|
54
|
+
end
|
55
|
+
|
56
|
+
# the value of the primary key for this object
|
57
|
+
def scaffold_id
|
58
|
+
get_key_array_safe(self.key)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Class methods added to DataMapper::Resource to allow it to work with Scaffolding Extensions.
|
63
|
+
module ScaffoldingExtensions::MetaDataMapper
|
64
|
+
SCAFFOLD_OPTIONS = ::ScaffoldingExtensions::MetaModel::SCAFFOLD_OPTIONS
|
65
|
+
|
66
|
+
# Add the associated object to the object's association
|
67
|
+
def scaffold_add_associated_object(association, object, associated_object)
|
68
|
+
ap = object.send(association)
|
69
|
+
ap << associated_object unless ap.include?(associated_object)
|
70
|
+
object.save
|
71
|
+
end
|
72
|
+
|
73
|
+
# Array of all association reflections for this model
|
74
|
+
# only shows the associations that are scaffolding_enabled
|
75
|
+
def scaffold_all_associations
|
76
|
+
relationships.values.select { |v|
|
77
|
+
v.send(:target_model).respond_to?(:scaffold_name)
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
# The class that this model is associated with via the association
|
82
|
+
def scaffold_associated_class(association)
|
83
|
+
relationships[association].target_model
|
84
|
+
end
|
85
|
+
|
86
|
+
# The association reflection for this association
|
87
|
+
def scaffold_association(association)
|
88
|
+
relationships[association]
|
89
|
+
end
|
90
|
+
|
91
|
+
# The type of association, either :new for :one_to_many (as you can create new objects
|
92
|
+
# associated with the current object), :edit for :many_to_many (since you
|
93
|
+
# can edit the list of associated objects), or :one for :many_to_one.
|
94
|
+
def scaffold_association_type(association)
|
95
|
+
if relationships[association].class == DataMapper::Associations::OneToMany::Relationship
|
96
|
+
:new
|
97
|
+
elsif relationships[association].class == DataMapper::Associations::ManyToMany::Relationship
|
98
|
+
:edit
|
99
|
+
else
|
100
|
+
:one
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# List of symbols for associations to display on the scaffolded edit page. Defaults to
|
105
|
+
# all associations for which the scaffolding is enabled. Can be set with an instance variable.
|
106
|
+
def scaffold_associations
|
107
|
+
@scaffold_associations ||= relationships.keys.select { |v|
|
108
|
+
relationships[v].send(:target_model).respond_to?(:scaffold_name)
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
# Destroys the object
|
113
|
+
def scaffold_destroy(object)
|
114
|
+
object.destroy
|
115
|
+
end
|
116
|
+
|
117
|
+
# The error to raise, should match other errors raised by the underlying library.
|
118
|
+
def scaffold_error_raised
|
119
|
+
DataMapper::ObjectNotFoundError
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns the list of fields to display on the scaffolded forms. Defaults
|
123
|
+
# to displaying all columns with the exception of the primary key column.
|
124
|
+
# Also includes :many_to_one associations, replacing
|
125
|
+
# the foriegn keys with the association itself. Can be set with an instance variable.
|
126
|
+
def scaffold_fields(action = :default)
|
127
|
+
return @scaffold_fields if @scaffold_fields
|
128
|
+
fields = (properties.map {|a| a.name}) - [scaffold_primary_key]
|
129
|
+
scaffold_all_associations.each do |reflection|
|
130
|
+
next unless reflection.class == DataMapper::Associations::ManyToOne::Relationship
|
131
|
+
fields.delete(get_key_array_safe(reflection.send(:child_key)).name)
|
132
|
+
fields.push(reflection.name)
|
133
|
+
end
|
134
|
+
@scaffold_fields = fields.sort_by{|f| f.to_s}
|
135
|
+
end
|
136
|
+
|
137
|
+
# The foreign key for the given reflection
|
138
|
+
def scaffold_foreign_key(reflection)
|
139
|
+
get_key_array_safe(reflection.child_key).name
|
140
|
+
end
|
141
|
+
|
142
|
+
# Retrieve a single model object given an id
|
143
|
+
def scaffold_get_object(id)
|
144
|
+
self.get(id) || (raise scaffold_error_raised)
|
145
|
+
end
|
146
|
+
|
147
|
+
# All objects that are currently associated with the given object. This method does not
|
148
|
+
# check that the returned associated objects meet the associated class's scaffold_session_value
|
149
|
+
# constraint, as it is assumed that all objects currently assocated with the given object
|
150
|
+
# have already met the criteria. If that is not the case, you should override this method.
|
151
|
+
def scaffold_associated_objects(association, object, options)
|
152
|
+
object.send(association,:order => get_ordering_options(scaffold_select_order_association(association)))
|
153
|
+
end
|
154
|
+
|
155
|
+
# Retrieve multiple objects given a hash of options
|
156
|
+
def scaffold_get_objects(options)
|
157
|
+
optionshash = {}
|
158
|
+
data = self.all
|
159
|
+
if options[:conditions]
|
160
|
+
conditions = options[:conditions]
|
161
|
+
if conditions && Array === conditions && conditions.length > 0
|
162
|
+
if String === conditions[0]
|
163
|
+
data = data.all(:conditions => conditions)
|
164
|
+
else
|
165
|
+
conditions.each do |cond|
|
166
|
+
next if cond.nil?
|
167
|
+
data = case cond
|
168
|
+
when Hash, String then data.all(:conditions => [cond.gsub("NULL","?"),nil])
|
169
|
+
when Array then
|
170
|
+
if cond.length==1
|
171
|
+
data.all(:conditions => [cond[0].gsub("NULL","?"),nil])
|
172
|
+
else
|
173
|
+
data.all(:conditions => cond)
|
174
|
+
end
|
175
|
+
when Proc then data.all(&cond)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
slice = nil
|
182
|
+
if options[:limit]
|
183
|
+
startpos = options[:offset] || 0
|
184
|
+
endpos = options[:limit]
|
185
|
+
slice = [startpos,endpos]
|
186
|
+
end
|
187
|
+
# TODO includes break SQL generation
|
188
|
+
# optionshash[:links] = options[:include] if options[:include]
|
189
|
+
# optionshash[:links] = [optionshash[:links]] unless optionshash[:links].is_a?(Array)
|
190
|
+
if options[:order] then
|
191
|
+
optionshash[:order] = get_ordering_options(options[:order])
|
192
|
+
end
|
193
|
+
if slice then
|
194
|
+
q = data.all(optionshash).slice(*slice)
|
195
|
+
else
|
196
|
+
q = data.all(optionshash)
|
197
|
+
end
|
198
|
+
#p repository.adapter.send("select_statement",q.query)
|
199
|
+
q.to_a
|
200
|
+
end
|
201
|
+
|
202
|
+
# Return the class, left foreign key, right foreign key, and join table for this habtm association
|
203
|
+
def scaffold_habtm_reflection_options(association)
|
204
|
+
habtm = relationships[association]
|
205
|
+
[
|
206
|
+
habtm.target_model,
|
207
|
+
get_key_array_safe(habtm.through.child_key).name,
|
208
|
+
get_key_array_safe(habtm.via.child_key).name,
|
209
|
+
habtm.send(:through_model).storage_name
|
210
|
+
]
|
211
|
+
end
|
212
|
+
|
213
|
+
# Returns a hash of values to be used as url parameters on the link to create a new
|
214
|
+
# :has_many associated object. Defaults to setting the foreign key field to the
|
215
|
+
# record's primary key.
|
216
|
+
def scaffold_new_associated_object_values(association, record)
|
217
|
+
{scaffold_foreign_key(scaffold_association(association))=>record.scaffold_id}
|
218
|
+
end
|
219
|
+
|
220
|
+
# The primary key for the given table
|
221
|
+
def scaffold_primary_key
|
222
|
+
get_key_array_safe(key).name
|
223
|
+
end
|
224
|
+
|
225
|
+
# Saves the object.
|
226
|
+
def scaffold_save(action, object)
|
227
|
+
object.save
|
228
|
+
end
|
229
|
+
|
230
|
+
# The column type for the given table column, or nil if it isn't a table column
|
231
|
+
def scaffold_table_column_type(column)
|
232
|
+
column = self.properties[column]
|
233
|
+
if column then
|
234
|
+
if column.type == DataMapper::Types::Text
|
235
|
+
:text
|
236
|
+
else
|
237
|
+
column.type.to_s.split("::").last.downcase.intern
|
238
|
+
end
|
239
|
+
else
|
240
|
+
nil
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# The name of the underlying table
|
245
|
+
def scaffold_table_name
|
246
|
+
storage_name
|
247
|
+
end
|
248
|
+
|
249
|
+
private
|
250
|
+
# Updates associated records for a given reflection and from record to point to the
|
251
|
+
# to record
|
252
|
+
def scaffold_reflection_merge(reflection, from, to)
|
253
|
+
if reflection.class == DataMapper::Associations::OneToMany::Relationship
|
254
|
+
foreign_key = get_key_array_safe(reflection.target_key).name
|
255
|
+
p reflection
|
256
|
+
p reflection.target_model
|
257
|
+
table = reflection.target_model
|
258
|
+
elsif reflection.class == DataMapper::Associations::ManyToMany::Relationship
|
259
|
+
foreign_key = get_key_array_safe(reflection.through.child_key).name
|
260
|
+
p reflection
|
261
|
+
table = reflection.send(:through_model)
|
262
|
+
p table
|
263
|
+
else
|
264
|
+
return
|
265
|
+
end
|
266
|
+
table.all(foreign_key => from).update(foreign_key => to)
|
267
|
+
end
|
268
|
+
|
269
|
+
# Remove the associated object from object's association
|
270
|
+
def scaffold_remove_associated_object(association, object, associated_object)
|
271
|
+
object.send(association).delete(associated_object)
|
272
|
+
object.save
|
273
|
+
end
|
274
|
+
|
275
|
+
# Set the object's attributes with the given attributes
|
276
|
+
def scaffold_set_attributes(object, attributes)
|
277
|
+
attributes.each do |k,v|
|
278
|
+
v = nil if v.empty? and (scaffold_table_column_type(k) == :boolean or scaffold_table_column_type(k) == :integer)
|
279
|
+
object.send("#{k}=", v)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
|
285
|
+
def add_scaffolding_methods(classes)
|
286
|
+
unless classes.is_a?(Array)
|
287
|
+
classes = [classes]
|
288
|
+
end
|
289
|
+
classes.each do |cl|
|
290
|
+
cl.class_eval <<-ECLASS
|
291
|
+
SCAFFOLD_OPTIONS = ::ScaffoldingExtensions::MetaModel::SCAFFOLD_OPTIONS
|
292
|
+
include ScaffoldingExtensions::Model
|
293
|
+
include ScaffoldingExtensions::DataMapper
|
294
|
+
extend ScaffoldingExtensions::MetaModel
|
295
|
+
extend ScaffoldingExtensions::MetaDataMapper
|
296
|
+
extend ScaffoldingExtensions::Overridable
|
297
|
+
ECLASS
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
@@ -94,6 +94,9 @@ require 'scaffolding_extensions/controller/sinatra' if defined? Sinatra
|
|
94
94
|
require 'scaffolding_extensions/controller/merb' if defined? Merb
|
95
95
|
|
96
96
|
require 'scaffolding_extensions/model/active_record' if defined? ActiveRecord::Base
|
97
|
+
if defined? DataMapper::Resource
|
98
|
+
require 'scaffolding_extensions/model/datamapper'
|
99
|
+
end
|
97
100
|
if defined? Sequel::Model
|
98
101
|
require('sequel/extensions/inflector') unless [:singularize, :pluralize, :camelize, :underscore, :constantize].all?{|meth| "".respond_to?(meth)}
|
99
102
|
require 'scaffolding_extensions/model/sequel'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scaffolding_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-03-08 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -26,6 +26,7 @@ files:
|
|
26
26
|
- README
|
27
27
|
- lib/scaffolding_extensions/model/active_record.rb
|
28
28
|
- lib/scaffolding_extensions/model/sequel.rb
|
29
|
+
- lib/scaffolding_extensions/model/datamapper.rb
|
29
30
|
- lib/scaffolding_extensions/controller/action_controller.rb
|
30
31
|
- lib/scaffolding_extensions/controller/camping.rb
|
31
32
|
- lib/scaffolding_extensions/controller/ramaze.rb
|
@@ -50,6 +51,7 @@ files:
|
|
50
51
|
- doc/sinatra.txt
|
51
52
|
- doc/testing.txt
|
52
53
|
- doc/advanced.txt
|
54
|
+
- doc/datamapper.txt
|
53
55
|
- contrib/scaffold_associations_tree/README
|
54
56
|
- contrib/scaffold_associations_tree/bullet.gif
|
55
57
|
- contrib/scaffold_associations_tree/minus.gif
|
@@ -94,6 +96,7 @@ rdoc_options:
|
|
94
96
|
- doc/sinatra.txt
|
95
97
|
- doc/testing.txt
|
96
98
|
- doc/advanced.txt
|
99
|
+
- doc/datamapper.txt
|
97
100
|
require_paths:
|
98
101
|
- lib
|
99
102
|
required_ruby_version: !ruby/object:Gem::Requirement
|