extjs-mvc 0.2.7 → 0.2.8
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.rdoc +32 -28
- data/VERSION +1 -1
- data/lib/extjs-mvc.rb +6 -0
- data/lib/model/active_record.rb +2 -2
- data/lib/model/base.rb +22 -11
- data/lib/model/mongo_mapper.rb +8 -8
- data/lib/test/macros.rb +20 -0
- data/test/active_record_test.rb +0 -0
- data/test/data_mapper_test.rb +0 -0
- data/test/database.yml +3 -0
- data/test/debug.log +2579 -0
- data/test/model_test.rb +108 -12
- data/test/mongo_mapper.rb +0 -0
- data/test/test_helper.rb +111 -0
- metadata +8 -2
data/README.rdoc
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
= mvc
|
2
2
|
|
3
|
-
|
4
3
|
A collection of helpers, MVC mixins and PORs (plain-old-ruby-object) to assist with auto-generating ExtJS Stores (Ext.data.Store) including its associated DataReader (Ext.data.JsonReader, Ext.data.XmlReader) and DataWriter (Ext.data.JsonWriter, Ext.data.XmlWriter). Also contains a helper for rendering javascript component definitions via partials.
|
5
4
|
|
5
|
+
See tutorial http://www.extjs.com/blog/2009/09/30/ext-js-on-rails-a-comprehensivetutorial/
|
6
6
|
|
7
7
|
===Installation
|
8
8
|
% sudo gem install gemcutter
|
9
9
|
% gem tumble (only have to do this once, adds gemcutter as primary gem-source)
|
10
|
-
|
10
|
+
% sudo gem install extjs-mvc
|
11
11
|
|
12
|
-
<
|
12
|
+
<b>Rails Installation:</b>
|
13
13
|
In <tt>environment.rb</tt>,
|
14
14
|
|
15
15
|
Rails::Initializer.run do |config|
|
16
16
|
config.gem "extjs-mvc"
|
17
17
|
end
|
18
18
|
|
19
|
-
<
|
19
|
+
<b>Merb installation:</b>
|
20
20
|
In <tt>config/dependencies.rb</tt>, Add extjs-mvc as a new dependency
|
21
21
|
|
22
22
|
dependency "extjs-mvc"
|
@@ -27,22 +27,23 @@ extjs-mvc contains Model mixin named <tt>ExtJS::Model</tt> which works for <b>th
|
|
27
27
|
Simply include the mixin into your model. Use the class-method <tt>extjs_fields</tt> to specify those
|
28
28
|
fields with will be used to render the <tt>Ext.data.Record.create</tt> field-def'n.
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
extjs_fields :exclude => [:password, :password_confirmation]
|
34
|
-
# OR
|
35
|
-
extjs_fields :name, :description
|
36
|
-
# OR define a column as a Hash
|
37
|
-
extjs_fields :description, :name => {"sortDir" => "ASC"}, :created_at => {"dateFormat" => "c"}
|
38
|
-
#
|
39
|
-
extjs_fields :name, :description, :parent => [:name, :date]
|
40
|
-
# this would configure associated columns with names like:
|
41
|
-
[...{name: "parent_name", mapping: "parent.name"}, {name: "parent_date", mapping: "parent.date"}...]
|
42
|
-
end
|
30
|
+
class User < ActiveRecord::Base
|
31
|
+
include ExtJS::Model
|
43
32
|
|
44
|
-
|
45
|
-
|
33
|
+
extjs_fields :exclude => [:password, :password_confirmation]
|
34
|
+
|
35
|
+
# OR
|
36
|
+
extjs_fields :name, :description
|
37
|
+
|
38
|
+
# OR define a column as a Hash
|
39
|
+
extjs_fields :description, :name => {"sortDir" => "ASC"}, :created_at => {"dateFormat" => "c"}
|
40
|
+
|
41
|
+
# OR render associations, association-fields will have their "mapping" property set automatically
|
42
|
+
extjs_fields :name, :description, :company => [:name, :description]
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
After including the model mixin <tt>ExtJS::Model</tt>, try typing the following in <tt>irb</tt> console:
|
46
47
|
>> User.extjs_record
|
47
48
|
=> { "idProperty"=>"id", "fields"=>[
|
48
49
|
{:type=>:int, :allowBlank=>true, :name=>"id"},
|
@@ -51,8 +52,10 @@ In <tt>irb</tt> console:
|
|
51
52
|
{:type=>:string, :allowBlank=>false, :name=>"email"}
|
52
53
|
]}
|
53
54
|
|
55
|
+
An auto-generated <tt>Ext.data.JsonReader</tt> configuration!
|
56
|
+
|
54
57
|
=== An ActionController mixin: ExtJS::Controller
|
55
|
-
The <tt>extjs-mvc</tt> Gem includes a framework agnostic Controller mixin which works with both Rails and Merb.
|
58
|
+
The <tt>extjs-mvc</tt> Gem includes a framework agnostic Controller mixin which works with both Rails and Merb. Include this mixin into any controller which will need to generate an <tt>Ext.data.Store</tt>.
|
56
59
|
<b>usage:</b>
|
57
60
|
|
58
61
|
class UsersController < ActionController::Base
|
@@ -71,13 +74,13 @@ The <tt>extjs-mvc</tt> Gem includes a framework agnostic Controller mixin which
|
|
71
74
|
Now render Ext components using helper method <tt>extjs_component</tt>
|
72
75
|
|
73
76
|
@viewport = extjs_component(
|
74
|
-
"xtype"
|
75
|
-
"frame"
|
76
|
-
"layout"
|
77
|
-
@viewport.add("xtype"
|
78
|
-
@viewport.add(:partial
|
79
|
-
@viewport.add(:partial
|
80
|
-
@viewport.add("xtype"
|
77
|
+
"xtype" => "viewport",
|
78
|
+
"frame" => true,
|
79
|
+
"layout" => "border")
|
80
|
+
@viewport.add("xtype" => "panel", "contentEl" => "hd", "region" => "north", "height" => 30)
|
81
|
+
@viewport.add(:partial => "/users/grid", "itemId" => "users-grid", "region" => "west")
|
82
|
+
@viewport.add(:partial => "/tasks/grid", "itemId" => "tasks-grid", "region" => "center")
|
83
|
+
@viewport.add("xtype" => "panel", "contentEl" => "ft", "region" => "south", "height" => 20)
|
81
84
|
|
82
85
|
Note how it can also render partials. Partials will be invoked with a local-variable named "container", a reference to the
|
83
86
|
parent Ext::Component instance which added the partial. If no "container" is specified, it would be expected that your partial
|
@@ -93,12 +96,13 @@ Renders an Ext.data.Store with helper method <tt>extjs_store</tt>
|
|
93
96
|
helper ExtJS::Helpers::Store
|
94
97
|
end
|
95
98
|
|
99
|
+
Now render a store in an erb template:
|
96
100
|
|
97
101
|
@store = extjs_store(
|
98
102
|
:controller => "users",
|
99
103
|
:proxy => "http" # <-- default
|
100
104
|
:format => "json" # <-- default
|
101
|
-
:model => "user", # <-- default: controller_name.singularize
|
105
|
+
:model => "user", # <-- default: controller_name.singularize
|
102
106
|
:writer => {:encode => false},
|
103
107
|
:config => { # <-- standard Ext.data.Store config-params
|
104
108
|
"autoLoad" => true
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.8
|
data/lib/extjs-mvc.rb
CHANGED
data/lib/model/active_record.rb
CHANGED
@@ -34,7 +34,7 @@ module ExtJS
|
|
34
34
|
def extjs_type(col)
|
35
35
|
type = col.type
|
36
36
|
case type
|
37
|
-
when :datetime
|
37
|
+
when :datetime, :date, :time, :timestamp
|
38
38
|
type = :date
|
39
39
|
when :text
|
40
40
|
type = :string
|
@@ -55,7 +55,7 @@ module ExtJS
|
|
55
55
|
@extjs_associations = {}
|
56
56
|
self.reflections.keys.each do |key|
|
57
57
|
assn = self.reflections[key]
|
58
|
-
type = (assn.macro === :has_many) ? :many : assn.macro
|
58
|
+
type = (assn.macro === :has_many || assn.macro === :has_and_belongs_to_many) ? :many : assn.macro
|
59
59
|
@extjs_associations[key.to_sym] = {
|
60
60
|
:name => key,
|
61
61
|
:type => type,
|
data/lib/model/base.rb
CHANGED
@@ -30,20 +30,24 @@ module ExtJS
|
|
30
30
|
# @params {Mixed} params A list of fields to use instead of this Class's extjs_record_fields
|
31
31
|
#
|
32
32
|
def to_record(*params)
|
33
|
+
if self.class.extjs_record_fields.empty?
|
34
|
+
self.class.extjs_fields(*self.class.extjs_column_names)
|
35
|
+
end
|
33
36
|
|
34
37
|
fields = (params.empty?) ? self.class.extjs_record_fields : self.class.process_fields(*params)
|
35
38
|
assns = self.class.extjs_associations
|
36
39
|
pk = self.class.extjs_primary_key
|
37
40
|
|
38
41
|
# build the initial field data-hash
|
39
|
-
data = {pk => self.send(pk)}
|
42
|
+
data = {pk.to_s => self.send(pk)}
|
40
43
|
|
41
44
|
fields.each do |field|
|
42
45
|
if refl = assns[field[:name]] || assns[field[:name].to_sym]
|
43
46
|
if refl[:type] === :belongs_to
|
44
47
|
assn = self.send(field[:name])
|
48
|
+
|
45
49
|
if assn.respond_to?(:to_record)
|
46
|
-
data[field[:name]] = assn.
|
50
|
+
data[field[:name]] = assn.to_record field[:fields]
|
47
51
|
elsif (field[:fields])
|
48
52
|
data[field[:name]] = {}
|
49
53
|
field[:fields].each do |property|
|
@@ -52,6 +56,8 @@ module ExtJS
|
|
52
56
|
else
|
53
57
|
data[field[:name]] = {} # belongs_to assn that doesn't respond to to_record and no fields list
|
54
58
|
end
|
59
|
+
# Append associations foreign_key to data
|
60
|
+
data[refl[:foreign_key].to_s] = self.send(refl[:foreign_key])
|
55
61
|
elsif refl[:type] === :many
|
56
62
|
data[field[:name]] = self.send(field[:name]).collect {|r| r.to_record} #CAREFUL!!!!!!!!!!!!1
|
57
63
|
end
|
@@ -91,13 +97,13 @@ module ExtJS
|
|
91
97
|
elsif assn = associations[field[:name]] || associations[field[:name].to_sym]
|
92
98
|
assn_fields = field.delete(:fields) || nil
|
93
99
|
if assn[:class].respond_to?(:extjs_record) # <-- exec extjs_record on assn Model.
|
94
|
-
record = assn[:class].
|
100
|
+
record = assn[:class].extjs_record(assn_fields)
|
95
101
|
rs.concat(record["fields"].collect {|assn_field|
|
96
|
-
extjs_field(assn_field, :mapping => field[:name])
|
102
|
+
extjs_field(assn_field, :mapping => field[:name], "allowBlank" => true) # <-- allowBlank on associated data?
|
97
103
|
})
|
98
104
|
elsif assn_fields # <-- :parent => [:id, :name]
|
99
105
|
rs.concat(assn_fields.collect {|assn_field|
|
100
|
-
extjs_field(assn_field, :mapping => field[:name])
|
106
|
+
extjs_field(assn_field, :mapping => field[:name], "allowBlank" => true)
|
101
107
|
})
|
102
108
|
else
|
103
109
|
rs << extjs_field(field)
|
@@ -144,9 +150,9 @@ module ExtJS
|
|
144
150
|
# This is to handle the case where extjs_record and to_record are called recursively, in which case
|
145
151
|
# these fields have already been processed.
|
146
152
|
#
|
147
|
-
if params.length === 1 && params.first.kind_of?(Array) && !params.first.empty?
|
148
|
-
|
149
|
-
end
|
153
|
+
#if params.length === 1 && params.first.kind_of?(Array) && !params.first.empty?
|
154
|
+
# return params.first
|
155
|
+
#end
|
150
156
|
|
151
157
|
fields = []
|
152
158
|
if !options.keys.empty?
|
@@ -172,9 +178,14 @@ module ExtJS
|
|
172
178
|
end
|
173
179
|
|
174
180
|
unless params.empty?
|
175
|
-
|
176
|
-
|
177
|
-
|
181
|
+
params = params.first if params.length == 1 && params.first.kind_of?(Array) && !params.first.empty?
|
182
|
+
params.each do |f|
|
183
|
+
if f.kind_of?(Hash)
|
184
|
+
fields << f
|
185
|
+
else
|
186
|
+
fields << {:name => f.to_s}
|
187
|
+
end
|
188
|
+
end
|
178
189
|
end
|
179
190
|
fields
|
180
191
|
end
|
data/lib/model/mongo_mapper.rb
CHANGED
@@ -7,25 +7,25 @@ module ExtJS
|
|
7
7
|
# ClassMethods
|
8
8
|
#
|
9
9
|
module ClassMethods
|
10
|
-
|
10
|
+
|
11
11
|
def extjs_primary_key
|
12
12
|
:_id
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def extjs_column_names
|
16
16
|
self.column_names
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def extjs_columns_hash
|
20
20
|
self.keys
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def extjs_associations
|
24
24
|
if @extjs_associations.nil?
|
25
25
|
@extjs_associations = {}
|
26
26
|
self.associations.keys.each do |key|
|
27
27
|
@extjs_associations[key.to_sym] = {
|
28
|
-
:name => key,
|
28
|
+
:name => key,
|
29
29
|
:type => self.associations[key].type,
|
30
30
|
:class => self.associations[key].class_name.constantize,
|
31
31
|
:foreign_key => self.associations[key].foreign_key
|
@@ -34,7 +34,7 @@ module ExtJS
|
|
34
34
|
end
|
35
35
|
@extjs_associations
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def extjs_type(col)
|
39
39
|
type = col.type.to_s
|
40
40
|
case type
|
@@ -50,9 +50,9 @@ module ExtJS
|
|
50
50
|
type = "auto"
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
def extjs_allow_blank(col)
|
55
|
-
(col.name
|
55
|
+
(col.name == '_id') || (col.options[:required] != true)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
data/lib/test/macros.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module ExtJS
|
2
|
+
module TestMacros
|
3
|
+
##
|
4
|
+
# Asserts that the passed list of fields are specified in the extjs_fields call
|
5
|
+
# in the model class.
|
6
|
+
# @fields {Symbols} fields A list of fields
|
7
|
+
#
|
8
|
+
def should_have_extjs_fields *fields
|
9
|
+
klass = model_class
|
10
|
+
should "have the correct extjs_fields" do
|
11
|
+
fields.each do |field|
|
12
|
+
found_record = klass.extjs_record_fields.find do|record_field|
|
13
|
+
record_field[:name] == field.to_s
|
14
|
+
end
|
15
|
+
assert_not_nil found_record, "extjs field #{field} isn't listed in the #{klass.name} model"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
File without changes
|
File without changes
|
data/test/database.yml
ADDED