scaffolding_extensions 1.3.12 → 1.4.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.
- 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
|