Class: Nitro::Scaffolding::ScaffoldCompiler

Inherits:
Object
  • Object
show all
Defined in:
lib/nitro/scaffolding.rb

Overview

– Compiles the scaffolding code. ++

Instance Method Summary collapse

Constructor Details

#initialize(controller, klass, options) ⇒ ScaffoldCompiler

Returns a new instance of ScaffoldCompiler.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/nitro/scaffolding.rb', line 53

def initialize(controller, klass, options)
  @controller = controller
  @klass = klass
  @options = options      
  @oid = options[:oid] || options[:pk]
  @name = options[:name]
  @plural = options[:plural_name]
  @suffix = options[:suffix]
  @compiler = Compiler.new(@controller)

  @base = options[:base] || options[:mount] || options[:at]
  if @base == true
    @base = @plural.dup 
  elsif @base == :ROOT
    @base = nil
  end            
  @base__ = "#{@base}__" if @base
end

Instance Method Details

#define_class_method(meth, code) ⇒ Object

– A helper that defines a class method. ++



76
77
78
79
80
81
82
83
84
# File 'lib/nitro/scaffolding.rb', line 76

def define_class_method(meth, code)
  unless @klass.instance_methods.include?(meth.to_s) 
    @klass.module_eval %{
      def #{meth}
        #{code}
      end
    } 
  end
end

#define_controller_action(definition, code, template = nil) ⇒ Object

– A helper that defines a controller action. ++



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/nitro/scaffolding.rb', line 90

def define_controller_action(definition, code, template = nil)
  sym, args = definition.to_s.split(/\(|\)/)
  
  # Access Namespace::Klass.action as namespace/klass/action.
  
  sym.gsub!(/::/, '__')
  
  if sym == 'index'
    action = "#{@base__}index"
  else
    action = "#@base__#{sym}#@suffix"
  end

  unless @controller.action?(action)
    @controller.module_eval %{
      def #{action}(#{args})
        @klass = #{@klass}
        #{code}
      end
    }
  end

  unless @compiler.template?(action)

    # Use the standard scaffold template.
    path = File.join(Scaffolding.template_root, "#{template || sym}.xhtml")

    if File.exist?(path) and source = File.read(path)
      # Interpolate the source.
      source.gsub!(/%base%/, @base.to_s)
      source.gsub!(/%klass%/, @klass.to_s)
      source.gsub!(/%name%/, @name)
      source.gsub!(/%plural%/, @plural)
      
      # Transform the source.
      source = @compiler.transform_template(action, source)

      @controller.module_eval %{
        def #{action}_template
          #{source}
        end
      }
    end
  end
end

#scaffoldObject

Scaffold the class and the controller.



138
139
140
141
# File 'lib/nitro/scaffolding.rb', line 138

def scaffold
  scaffold_class
  scaffold_controller
end

#scaffold_classObject

Scaffold the class.



145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/nitro/scaffolding.rb', line 145

def scaffold_class      
  define_class_method :scaffold_base, %{
    "#{@controller.mount_path}/#@base"
  }          
  
  define_class_method :to_href, %{
    "#{@controller.mount_path}/#@base/view/\#@#{@oid}"
  }    

  define_class_method :to_edit_href, %{
    "#{@controller.mount_path}/#@base/edit/\#@#{@oid}"
  }    
end

#scaffold_controllerObject

Scaffold the controller.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/nitro/scaffolding.rb', line 161

def scaffold_controller      
  define_controller_action 'index', %{
    #{Aspects.gen_advice_code(:scaffold_index, @controller.advices, :pre)}
    @list, @pager = paginate(@klass, :per_page => Scaffolding.per_page)
  }

  define_controller_action 'list', %{
    #{Aspects.gen_advice_code(:scaffold_list, @controller.advices, :pre)}
    @list, @pager = paginate(@klass, :per_page => Scaffolding.per_page)
  }
    
  define_controller_action 'view(oid)', %{
    #{Aspects.gen_advice_code(:scaffold_view, @controller.advices, :pre)}
    @obj = @klass[oid]
  }

  define_controller_action 'new(all = false)', %{
    #{Aspects.gen_advice_code(:scaffold_new, @controller.advices, :pre)}
    @obj = @klass.new
    @all = all
  }

  define_controller_action 'edit(oid = nil, all = false)', %{
    #{Aspects.gen_advice_code(:scaffold_edit, @controller.advices, :pre)}
    @obj = @klass[oid]
    @all = all
  }

  # FIXME: investigate save, improve.
  
  define_controller_action 'save', %{
    if oid = request.fetch('#@oid', nil)
      oid = oid.to_s # fix StringIO (post).
      obj = request.fill(@klass[oid], :assign_relations => true, :force_boolean => true, :preprocess => true)
    else
      obj = request.fill(@klass.create, :assign_relations => true, :preprocess => true)
    end
    #{Aspects.gen_advice_code(:scaffold_save, @controller.advices, :pre)}
    unless obj.valid?
      flash[:ERRORS] = obj.errors
      redirect_to_referer
    end
    obj.save
    oid = obj.pk
    #{Aspects.gen_advice_code(:scaffold_save, @controller.advices, :post)}
    redirect '#{action_path(:list)}'
  }

  define_controller_action 'search(query)', %{
    #{Aspects.gen_advice_code(:scaffold_search, @controller.advices, :pre)}
    @query = query
    if @klass.respond_to? :search
      @list = #@klass.search(query)
    end
    #{Aspects.gen_advice_code(:scaffold_search, @controller.advices, :post)}
  }

  define_controller_action 'advanced_search', %{
    #{Aspects.gen_advice_code(:scaffold_search, @controller.advices, :pre)}
    if request.post?
      @list = #@klass.query_by_example(request.params)
    end
    #{Aspects.gen_advice_code(:scaffold_advanced_search, @controller.advices, :post)}
  }

  define_controller_action 'delete(oid)', %{
    #{Aspects.gen_advice_code(:scaffold_delete, @controller.advices, :pre)}
    @klass.delete(oid)
    #{Aspects.gen_advice_code(:scaffold_delete, @controller.advices, :post)}
    redirect_to_referer
  }            
  
  # Actions for the relations
  
  for rel in @klass.relations        
    define_controller_action "remove_#{rel.target_singular_name}(oid, rid)", %{
      obj = @klass[oid]
      #{Aspects.gen_advice_code(:scaffold_remove_relation, @controller.advices, :pre)}
      rob = #{rel.target_class}[rid]
      obj.#{rel.name}.remove(rob)
      #{::Aspects.gen_advice_code(:scaffold_remove_relation, @controller.advices, :post)}
      redirect_to_referer
    }
    define_controller_action "delete_#{rel.target_singular_name}(oid, rid)", %{
      #{Aspects.gen_advice_code(:scaffold_delete_relation, @controller.advices, :pre)}
      obj = @klass[oid]
      rob = #{rel.target_class}[rid]
      obj.#{rel.name}.delete(rob)
      #{Aspects.gen_advice_code(:scaffold_delete_relation, @controller.advices, :post)}
      redirect_to_referer
    }
  end        
end