puffer 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/app/cells/puffer/base/additional.html.erb +13 -5
- data/app/helpers/puffer_helper.rb +6 -1
- data/app/views/layouts/puffer.html.erb +5 -3
- data/app/views/puffer/_form.html.erb +1 -1
- data/app/views/puffer/associated/one.js.erb +9 -0
- data/app/views/puffer/edit.html.erb +1 -1
- data/app/views/puffer/index.html.erb +7 -7
- data/app/views/puffer/new.html.erb +1 -1
- data/app/views/puffer/show.html.erb +4 -4
- data/lib/generators/puffer/install/templates/puffer/javascripts/application.js +10 -0
- data/lib/generators/puffer/install/templates/puffer/javascripts/rails-src.js +36 -378
- data/lib/generators/puffer/install/templates/puffer/javascripts/right-autocompleter-src.js +621 -0
- data/lib/generators/puffer/install/templates/puffer/javascripts/right-autocompleter.js +18 -0
- data/lib/generators/puffer/install/templates/puffer/javascripts/right-autocompleter.js.gz +0 -0
- data/lib/generators/puffer/install/templates/puffer/stylesheets/puffer.css +107 -6
- data/lib/puffer/base.rb +4 -3
- data/lib/puffer/controller/actions.rb +4 -70
- data/lib/puffer/controller/dsl.rb +23 -5
- data/lib/puffer/controller/generated.rb +65 -0
- data/lib/puffer/extensions/activerecord.rb +3 -3
- data/lib/puffer/extensions/core.rb +14 -0
- data/lib/puffer/extensions/mapper.rb +20 -0
- data/lib/puffer/fields.rb +11 -2
- data/lib/puffer/fields/field.rb +24 -1
- data/lib/puffer/inputs.rb +1 -3
- data/lib/puffer/inputs/association.rb +27 -1
- data/lib/puffer/inputs/base.rb +12 -4
- data/lib/puffer/inputs/boolean.rb +1 -1
- data/lib/puffer/inputs/date_time.rb +1 -1
- data/lib/puffer/resource.rb +1 -1
- data/lib/puffer/resource/routing.rb +2 -2
- data/lib/puffer/resource/scoping.rb +5 -1
- data/puffer.gemspec +15 -5
- data/spec/dummy/app/controllers/admin/profiles_controller.rb +2 -2
- data/spec/dummy/app/views/admin/users/index.html.erb +3 -1
- data/spec/dummy/config/database.yml +1 -1
- data/spec/dummy/public/puffer/javascripts/application.js +10 -0
- data/spec/dummy/public/puffer/javascripts/rails-src.js +36 -378
- data/spec/dummy/public/puffer/javascripts/right-autocompleter-src.js +621 -0
- data/spec/dummy/public/puffer/javascripts/right-autocompleter.js +18 -0
- data/spec/dummy/public/puffer/javascripts/right-autocompleter.js.gz +0 -0
- data/spec/dummy/public/puffer/stylesheets/puffer.css +107 -6
- data/spec/lib/extensions/core_spec.rb +29 -0
- data/spec/lib/resource/routing_spec.rb +11 -11
- metadata +28 -18
- data/lib/generators/puffer/install/templates/puffer/javascripts/rails.js +0 -14
- data/spec/dummy/public/puffer/javascripts/rails.js +0 -14
@@ -0,0 +1,18 @@
|
|
1
|
+
/**
|
2
|
+
* RightJS-UI: Autocompleter
|
3
|
+
* http://rightjs.org/ui/autocompleter
|
4
|
+
*
|
5
|
+
* Copyright (C) 2010 Nikolay Nemshilov
|
6
|
+
*/
|
7
|
+
var Autocompleter=RightJS.Autocompleter=function(h,c){function l(a,b,d,e){if(c.Fx)if(d===undefined){d=a.options.fxName;if(e===undefined){e={duration:a.options.fxDuration,onFinish:c(a.fire).bind(a,b)};if(b==="hide")e.duration=(c.Fx.Durations[e.duration]||e.duration)/2}}if(!c.Fx||!d)a.fire(b);return a.$super(d,e)}function m(a,b,d){var e=(this.reAnchor||(this.reAnchor=new c.Element("div",{"class":"rui-re-anchor"})).insert(this)).insertTo(a,"after").position(),f=a.dimensions(),i=parseInt(a.getStyle("borderTopWidth")),
|
8
|
+
j=parseInt(a.getStyle("borderLeftWidth")),q=parseInt(a.getStyle("borderRightWidth")),r=parseInt(a.getStyle("borderBottomWidth"));a=f.top-e.y+i;e=f.left-e.x+j;j=f.width-j-q;f=f.height-i-r;this.setStyle("visibility:hidden").show(null);if(b==="right")e+=j-this.size().x;else a+=f;this.moveTo(e,a);if(d)b==="left"||b==="right"?this.setHeight(f):this.setWidth(j);this.setStyle("visibility:visible").hide(null)}var g=c,n=c.$,s=c.$w,t=c.Xhr,o=c.RegExp,u=c.isArray,p=new c.Class(c.Element,{initialize:function(a){this.$super("div",
|
9
|
+
{"class":"rui-spinner"});this.dots=[];for(var b=0;b<(a||4);b++)this.dots.push(new c.Element("div"));this.dots[0].addClass("glowing");this.insert(this.dots);c(this.shift).bind(this).periodical(300)},shift:function(){if(this.visible()){var a=this.dots.pop();this.dots.unshift(a);this.insert(a,"top")}}}),k=new (function(a,b){if(!b){b=a;a="DIV"}var d=new c.Class(c.Element.Wrappers[a]||c.Element,{initialize:function(e,f){this.key=e;var i=[{"class":"rui-"+e}];this instanceof c.Input||this instanceof c.Form||
|
10
|
+
i.unshift(a);this.$super.apply(this,i);if(c.isString(f))f=c.$(f);if(f instanceof c.Element){this._=f._;if("$listeners"in f)f.$listeners=f.$listeners;f={}}this.setOptions(f,this);return c.Wrapper.Cache[c.$uid(this._)]=this},setOptions:function(e,f){f=f||this;c.Options.setOptions.call(this,c.Object.merge(e,eval("("+(f.get("data-"+this.key)||"{}")+")")));return this}});d=new c.Class(d,b);c.Observer.createShortcuts(d.prototype,d.EVENTS||[]);return d})("UL",{include:{show:function(a,b){this.constructor.current=
|
11
|
+
this;return l(this,"show",a,b)},hide:function(a,b){this.constructor.current=null;return l(this,"show",a,b)},showAt:function(a,b,d){this.hide(null).shownAt=a=c.$(a);m.call(this,a,b,d);return this.show()},toggleAt:function(a,b,d){return this.hidden()?this.showAt(a,b,d):this.hide()}},extend:{version:"2.2.0",EVENTS:s("show hide update load select done"),Options:{url:h.location.href,param:"search",method:"get",minLength:1,threshold:200,cache:true,local:null,fxName:"slide",fxDuration:"short",spinner:"native",
|
12
|
+
cssRule:"input[data-autocompleter]"}},initialize:function(a,b){this.input=n(a);this.$super("autocompleter",b).addClass("rui-dd-menu").onMousedown(this.clicked);this.input.autocompleter=this},destroy:function(){delete this.input.autocompleter;return this},prev:function(){return this.pick("prev")},next:function(){return this.pick("next")},done:function(a){if(a=a||this.first("li.current")){a.radioClass("current");this.input.setValue(g(a.html()).stripTags());this.fire("done")}return this.hide()},setOptions:function(a){this.$super(a,
|
13
|
+
this.input);a=this.options;g(a.url).includes("%{search}")||(a.url+=(g(a.url).includes("?")?"&":"?")+a.param+"=%{search}")},pick:function(a){var b=this.children(),d=b.first("hasClass","current"),e=b.indexOf(d);if(a=="prev")d=e<1?b.last():b[e<0?0:e-1];else if(a=="next")d=e<0||e==b.length-1?b.first():b[e+1];return this.fire("select",{item:d.radioClass("current")})},clicked:function(a){this.done(a.stop().find("li"))},keypressed:function(){if(this.input.value().length>=this.options.minLength){this.timeout&&
|
14
|
+
this.timeout.cancel();this.timeout=g(this.trigger).bind(this).delay(this.options.threshold)}else return this.hide()},trigger:function(){this.timeout=null;this.cache=this.cache||{};var a=this.input.value(),b=this.options;if(a.length<b.minLength)return this.hide();if(this.cache[a])this.suggest(this.cache[a],a);else if(u(b.local))this.suggest(this.findLocal(a),a);else this.request=t.load(b.url.replace("%{search}",encodeURIComponent(a)),{method:b.method,spinner:this.getSpinner(),onComplete:g(function(d){this.fire("load").suggest(d.text,
|
15
|
+
a)}).bind(this)})},suggest:function(a,b){if(this.options.cache)this.cache[b]=a;if(g(a).blank())this.hide();else{this.update(a.replace(/<ul[^>]*>|<\/ul>/im,""));this.fire("update");if(!this._connected||this.hidden()){this.showAt(this.input,"bottom","resize");this._connected=true}}return this},findLocal:function(a){var b=new o("("+o.escape(a)+")","ig");return g(this.options.local).map(function(d){if(d.match(b))return"<li>"+d.replace(b,"<strong>$1</strong>")+"</li>"}).compact().join("")},getSpinner:function(){var a=
|
16
|
+
this.options,b=a.spinner;if(b=="native"){b=a.spinner=(new p(3)).insertTo(this);b.addClass("rui-autocompleter-spinner")}b instanceof p&&m.call(b,this.input,"right","resize");return b}});n(h).on({focus:function(a){if((a=a.target)&&a instanceof c.Element&&(a.autocompleter||a.match(k.Options.cssRule)))a.autocompleter||new k(a)},blur:function(a){(a=a.target?a.target.autocompleter:null)&&a.visible()&&a.hide()},keydown:function(a){var b=a.target?a.target.autocompleter:null;if(b&&b.visible()){var d={27:"hide",
|
17
|
+
38:"prev",40:"next",13:"done"}[a.keyCode];if(d){a.stop();b[d]()}}},keyup:function(a){var b=a.target?a.target.autocompleter:null;b&&!g([9,27,37,38,39,40,13]).include(a.keyCode)&&b.keypressed(a)}});(function(){var a=h.createElement("style"),b=h.createTextNode(" *.rui-dd-menu, *.rui-dd-menu li{margin:0;padding:0;border:none;background:none;list-style:none;font-weight:normal;float:none} *.rui-dd-menu{display:none;position:absolute;z-index:9999;background:white;border:1px solid #BBB;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;box-shadow:#DDD .2em .2em .4em;-moz-box-shadow:#DDD .2em .2em .4em;-webkit-box-shadow:#DDD .2em .2em .4em} *.rui-dd-menu li{padding:.2em .4em;border-top:none;border-bottom:none;cursor:pointer} *.rui-dd-menu li.current{background:#DDD} *.rui-dd-menu li:hover{background:#EEE}dl.rui-dd-menu dt{padding:.3em .5em;cursor:default;font-weight:bold;font-style:italic;color:#444;background:#EEE}dl.rui-dd-menu dd li{padding-left:1.5em}div.rui-spinner,div.rui-spinner div{margin:0;padding:0;border:none;background:none;list-style:none;font-weight:normal;float:none;display:inline-block; *display:inline; *zoom:1;border-radius:.12em;-moz-border-radius:.12em;-webkit-border-radius:.12em}div.rui-spinner{text-align:center;white-space:nowrap;background:#EEE;border:1px solid #DDD;height:1.2em;padding:0 .2em}div.rui-spinner div{width:.4em;height:70%;background:#BBB;margin-left:1px}div.rui-spinner div:first-child{margin-left:0}div.rui-spinner div.glowing{background:#777}div.rui-re-anchor{margin:0;padding:0;background:none;border:none;float:none;display:inline;position:absolute;z-index:9999}.rui-autocompleter{border-top-color:#DDD !important;border-top-left-radius:0 !important;border-top-right-radius:0 !important;-moz-border-radius-topleft:0 !important;-moz-border-radius-topright:0 !important;-webkit-border-top-left-radius:0 !important;-webkit-border-top-right-radius:0 !important}.rui-autocompleter-spinner{border:none !important;background:none !important;position:absolute;z-index:9999}.rui-autocompleter-spinner div{margin-top:.2em !important; *margin-top:0.1em !important}");
|
18
|
+
a.type="text/css";if(a.styleSheet)a.styleSheet.cssText=b.nodeValue;else a.appendChild(b);h.getElementsByTagName("head")[0].appendChild(a)})();return k}(document,RightJS);
|
Binary file
|
@@ -88,7 +88,7 @@ h1
|
|
88
88
|
*display: inline;
|
89
89
|
zoom: 1;
|
90
90
|
color: #ddd;
|
91
|
-
padding:
|
91
|
+
padding: 7px 12px;
|
92
92
|
font-size: 11pt;
|
93
93
|
text-decoration: none;
|
94
94
|
text-shadow: #304759 -1px -1px 0;
|
@@ -120,6 +120,16 @@ h1
|
|
120
120
|
border-bottom-right-radius: 3px;
|
121
121
|
}
|
122
122
|
|
123
|
+
.sidebar .navigation li .additional dt
|
124
|
+
{
|
125
|
+
margin-bottom: 2px;
|
126
|
+
}
|
127
|
+
|
128
|
+
.sidebar .navigation li .additional dd
|
129
|
+
{
|
130
|
+
margin-bottom: 8px;
|
131
|
+
}
|
132
|
+
|
123
133
|
.columns
|
124
134
|
{
|
125
135
|
width: 100%;
|
@@ -170,7 +180,7 @@ h1
|
|
170
180
|
border-top-left-radius: 5px;
|
171
181
|
border-bottom-left-radius: 5px;
|
172
182
|
background: #fff;
|
173
|
-
padding:
|
183
|
+
padding: 30px;
|
174
184
|
}
|
175
185
|
|
176
186
|
.list_table
|
@@ -186,6 +196,11 @@ h1
|
|
186
196
|
-webkit-border-radius: 5px;
|
187
197
|
}
|
188
198
|
|
199
|
+
.list_table *
|
200
|
+
{
|
201
|
+
font-size: 8pt;
|
202
|
+
}
|
203
|
+
|
189
204
|
.list_table tr
|
190
205
|
{
|
191
206
|
vertical-align: top;
|
@@ -258,6 +273,40 @@ h1
|
|
258
273
|
background: #f4f4f4;
|
259
274
|
}
|
260
275
|
|
276
|
+
label, input, textarea
|
277
|
+
{
|
278
|
+
font-family: Helvetica, Arial, sans-serif;
|
279
|
+
}
|
280
|
+
|
281
|
+
input[type=text], input[type=password], textarea
|
282
|
+
{
|
283
|
+
border: #ccc solid 1px;
|
284
|
+
font-size: 11pt;
|
285
|
+
padding: 3px 0;
|
286
|
+
border-radius: 3px;
|
287
|
+
}
|
288
|
+
|
289
|
+
input[type=text]:focus, input[type=password]:focus, textarea:focus
|
290
|
+
{
|
291
|
+
border: #536C80 solid 1px;
|
292
|
+
}
|
293
|
+
|
294
|
+
input[type=submit]
|
295
|
+
{
|
296
|
+
border: 0;
|
297
|
+
border-radius: 3px;
|
298
|
+
background: #536C80;
|
299
|
+
color: #ddd;
|
300
|
+
text-shadow: -1px -1px 0 #304759;
|
301
|
+
padding: 3px 10px;
|
302
|
+
font-size: 11pt;
|
303
|
+
}
|
304
|
+
|
305
|
+
#search
|
306
|
+
{
|
307
|
+
width: 120px;
|
308
|
+
}
|
309
|
+
|
261
310
|
.form
|
262
311
|
{
|
263
312
|
margin-bottom: 30px;
|
@@ -269,21 +318,73 @@ h1
|
|
269
318
|
margin-bottom: 8px;
|
270
319
|
}
|
271
320
|
|
321
|
+
.form li .label
|
322
|
+
{
|
323
|
+
margin-bottom: 3px;
|
324
|
+
}
|
325
|
+
|
326
|
+
.form li .label *
|
327
|
+
{
|
328
|
+
display: inline;
|
329
|
+
}
|
330
|
+
|
272
331
|
.form li label
|
273
332
|
{
|
274
|
-
|
275
|
-
font-size: 11pt;
|
333
|
+
font-size: 10pt;
|
276
334
|
font-weight: bold;
|
277
335
|
}
|
278
336
|
|
279
337
|
.form li input[type=text], .form li input[type=password], .form li textarea
|
280
338
|
{
|
281
|
-
border: #ccc solid 1px;
|
282
339
|
width: 100%;
|
283
|
-
font-size: 12pt;
|
284
340
|
}
|
285
341
|
|
286
342
|
.form li textarea
|
287
343
|
{
|
288
344
|
height: 60px;
|
289
345
|
}
|
346
|
+
|
347
|
+
.field_error
|
348
|
+
{
|
349
|
+
color: #C83E3E;
|
350
|
+
}
|
351
|
+
|
352
|
+
.association
|
353
|
+
{
|
354
|
+
position: relative;
|
355
|
+
}
|
356
|
+
|
357
|
+
.association input[disabled]
|
358
|
+
{
|
359
|
+
text-indent: 25px;
|
360
|
+
}
|
361
|
+
|
362
|
+
.association .association_clear
|
363
|
+
{
|
364
|
+
position: absolute;
|
365
|
+
top: 4px;
|
366
|
+
left: 9px;
|
367
|
+
cursor: pointer;
|
368
|
+
display: none;
|
369
|
+
}
|
370
|
+
|
371
|
+
.association .association_clear:hover
|
372
|
+
{
|
373
|
+
color: #b00;
|
374
|
+
text-shadow: 1px 1px 2px #555;
|
375
|
+
}
|
376
|
+
|
377
|
+
.association input[disabled] ~ .association_clear
|
378
|
+
{
|
379
|
+
display: block;
|
380
|
+
}
|
381
|
+
|
382
|
+
.association .rui-autocompleter li .description
|
383
|
+
{
|
384
|
+
display: none;
|
385
|
+
}
|
386
|
+
|
387
|
+
.association .rui-autocompleter li:hover .description
|
388
|
+
{
|
389
|
+
display: block;
|
390
|
+
}
|
data/lib/puffer/base.rb
CHANGED
@@ -6,6 +6,7 @@ module Puffer
|
|
6
6
|
include Puffer::Controller::Helpers
|
7
7
|
include Puffer::Controller::Dsl
|
8
8
|
include Puffer::Controller::Config
|
9
|
+
include Puffer::Controller::Generated
|
9
10
|
|
10
11
|
respond_to :html, :js
|
11
12
|
|
@@ -28,19 +29,19 @@ module Puffer
|
|
28
29
|
def create
|
29
30
|
@record = resource.new_member
|
30
31
|
@record.save
|
31
|
-
respond_with @record, :location => resource.
|
32
|
+
respond_with @record, :location => resource.collection_path
|
32
33
|
end
|
33
34
|
|
34
35
|
def update
|
35
36
|
@record = resource.member
|
36
37
|
@record.update_attributes resource.attributes
|
37
|
-
respond_with @record, :location => resource.
|
38
|
+
respond_with @record, :location => resource.collection_path
|
38
39
|
end
|
39
40
|
|
40
41
|
def destroy
|
41
42
|
@record = resource.member
|
42
43
|
@record.destroy
|
43
|
-
redirect_to (request.referrer || resource.
|
44
|
+
redirect_to (request.referrer || resource.collection_path)
|
44
45
|
end
|
45
46
|
|
46
47
|
end
|
@@ -1,79 +1,13 @@
|
|
1
1
|
module Puffer
|
2
2
|
module Controller
|
3
|
-
|
3
|
+
class Actions < Array
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
%w(match get post put delete).each do |method|
|
6
|
+
define_method method do |*args|
|
7
|
+
push args.unshift(method)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
module ClassMethods
|
12
|
-
|
13
|
-
def generate_association_actions field
|
14
|
-
field.collection? ? generate_collection_association_actions(field) : generate_single_association_actions(field)
|
15
|
-
end
|
16
|
-
|
17
|
-
def generate_single_association_actions field
|
18
|
-
define_method "associated_#{field}_choosing" do
|
19
|
-
@record = model.find params[:id]
|
20
|
-
@records = field.association.klass.scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
21
|
-
@field = field
|
22
|
-
render 'puffer/associated/one'
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def generate_collection_association_actions field
|
27
|
-
define_method "associated_#{field}" do
|
28
|
-
@record = model.find params[:id]
|
29
|
-
@records = field.association.klass.scoped(:conditions => {:id => params[:ids]}).scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
30
|
-
@field = field
|
31
|
-
render 'puffer/associated/many'
|
32
|
-
end
|
33
|
-
|
34
|
-
define_method "associated_#{field}_choosing" do
|
35
|
-
@record = model.find params[:id]
|
36
|
-
@records = field.association.klass.scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
37
|
-
@choosen = field.association.klass.scoped(:conditions => {:id => params[:ids]}).scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
38
|
-
@field = field
|
39
|
-
render 'puffer/associated/many'
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def generate_change_actions field
|
44
|
-
define_method "toggle_#{field}" do
|
45
|
-
@record = model.find params[:id]
|
46
|
-
@field = field
|
47
|
-
@record.toggle! field.name.to_sym
|
48
|
-
render 'puffer/toggle'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def route_member_actions
|
55
|
-
unless @route_member_actions
|
56
|
-
@route_member_actions = {}
|
57
|
-
actions.each do |action|
|
58
|
-
@route_member_actions.merge!(action => :get)
|
59
|
-
end
|
60
|
-
[:form_fields, :update_fields, :create_fields].each do |fields|
|
61
|
-
fields = send fields
|
62
|
-
fields.each do |field|
|
63
|
-
if field.association?
|
64
|
-
field.collection? ? @route_member_actions.merge!("associated_#{field}" => :get, "associated_#{field}_choosing" => :get) : @route_member_actions.merge!("associated_#{field}_choosing" => :get)
|
65
|
-
end
|
66
|
-
end if fields
|
67
|
-
end
|
68
|
-
index_fields.each do |field|
|
69
|
-
@route_member_actions.merge!("toggle_#{field}" => :post) if field.toggable?
|
70
|
-
end if index_fields
|
71
|
-
end
|
72
|
-
@route_member_actions
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
11
|
end
|
78
12
|
end
|
79
13
|
end
|
@@ -10,26 +10,44 @@ module Puffer
|
|
10
10
|
|
11
11
|
%w(index show form create update).each do |action|
|
12
12
|
class_attribute "_#{action}_fields"
|
13
|
-
send "_#{action}_fields=", Puffer::Fields.new unless send("_#{action}_fields")
|
13
|
+
send "_#{action}_fields=", Puffer::Fields.new unless send("_#{action}_fields?")
|
14
14
|
helper_method "#{action}_fields"
|
15
15
|
end
|
16
|
+
|
17
|
+
class_attribute :_members
|
18
|
+
self._members = Puffer::Controller::Actions.new
|
19
|
+
class_attribute :_collections
|
20
|
+
self._collections = Puffer::Controller::Actions.new
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
19
24
|
module ClassMethods
|
20
25
|
|
26
|
+
def inherited klass
|
27
|
+
klass._members = _members.dup
|
28
|
+
klass._collections = _collections.dup
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def member &block
|
33
|
+
block.bind(_members).call if block_given?
|
34
|
+
end
|
35
|
+
|
36
|
+
def collection &block
|
37
|
+
block.bind(_collections).call if block_given?
|
38
|
+
end
|
39
|
+
|
21
40
|
%w(index show form create update).each do |action|
|
22
41
|
define_method action do |&block|
|
23
|
-
@_fields = send
|
24
|
-
@_fields.clear
|
42
|
+
@_fields = send("_#{action}_fields=", Puffer::Fields.new)
|
25
43
|
block.call if block
|
26
|
-
|
44
|
+
remove_instance_variable :@_fields
|
27
45
|
end
|
28
46
|
end
|
29
47
|
|
30
48
|
def field name, options = {}
|
31
49
|
field = @_fields.field(model, name, options) if @_fields
|
32
|
-
|
50
|
+
generate_association_actions field if field.reflection
|
33
51
|
#generate_change_actions field if field.toggable?
|
34
52
|
end
|
35
53
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Puffer
|
2
|
+
module Controller
|
3
|
+
module Generated
|
4
|
+
|
5
|
+
def self.included base
|
6
|
+
base.class_eval do
|
7
|
+
extend ClassMethods
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def generate_association_actions field
|
14
|
+
field.collection? ? generate_collection_association_actions(field) : generate_single_association_actions(field)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_single_association_actions field
|
18
|
+
define_method "associated_#{field}_choosing" do
|
19
|
+
@field = field
|
20
|
+
@record = resource.member if params[:id]
|
21
|
+
@records = field.reflection.klass.includes(field.association_fields.includes).joins(field.association_fields.includes).where(field.association_fields.searches(params[:search])).limit(100).all
|
22
|
+
render 'puffer/associated/one'
|
23
|
+
end
|
24
|
+
|
25
|
+
collection do
|
26
|
+
get "associated_#{field}_choosing"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_collection_association_actions field
|
31
|
+
define_method "associated_#{field}" do
|
32
|
+
@record = resource.member
|
33
|
+
@records = field.association.klass.scoped(:conditions => {:id => params[:ids]}).scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
34
|
+
@field = field
|
35
|
+
render 'puffer/associated/many'
|
36
|
+
end
|
37
|
+
|
38
|
+
define_method "associated_#{field}_choosing" do
|
39
|
+
@record = resource.member
|
40
|
+
@records = field.association.klass.scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
41
|
+
@choosen = field.association.klass.scoped(:conditions => {:id => params[:ids]}).scoped(:conditions => search_query(field.association_fields)).paginate(:page => params[:page], :include => includes(field.association_fields))
|
42
|
+
@field = field
|
43
|
+
render 'puffer/associated/many'
|
44
|
+
end
|
45
|
+
|
46
|
+
collection do
|
47
|
+
get "associated_#{field}"
|
48
|
+
get "associated_#{field}_choosing"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_change_actions field
|
53
|
+
define_method "toggle_#{field}" do
|
54
|
+
@record = model.find params[:id]
|
55
|
+
@field = field
|
56
|
+
@record.toggle! field.name.to_sym
|
57
|
+
render 'puffer/toggle'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -8,11 +8,11 @@ module Puffer
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def to_title
|
11
|
-
send
|
11
|
+
send title_method
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
self.class.column_names[1].to_sym
|
14
|
+
def title_method
|
15
|
+
self.class.column_names.detect {|c| c =~ /name|title/} || self.class.column_names[1].to_sym
|
16
16
|
end
|
17
17
|
|
18
18
|
end
|
@@ -21,11 +21,25 @@ module Puffer
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
module Array
|
25
|
+
def to_includes
|
26
|
+
map do |field|
|
27
|
+
sections = field.split('.').map(&:to_sym)
|
28
|
+
hash = sections.pop
|
29
|
+
sections.reverse_each do |section|
|
30
|
+
hash = {section => hash}
|
31
|
+
end
|
32
|
+
hash
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
24
37
|
end
|
25
38
|
end
|
26
39
|
|
27
40
|
String.send :include, Puffer::Extensions::String
|
28
41
|
Symbol.send :include, Puffer::Extensions::Symbol
|
42
|
+
Array.send :include, Puffer::Extensions::Array
|
29
43
|
|
30
44
|
Kernel.class_eval do
|
31
45
|
def swallow_nil
|