class RailsBuilder
Public Class Methods
new(s=nil, journal: false)
click to toggle source
# File lib/railsbuilder.rb, line 18 def initialize(s=nil, journal: false) @config = RXFHelper.read(s)[0].gsub(/^(\s{,5})#/,'\1;') if s @tmp_path = @journal = journal == true ? Dir.tmpdir : journal if journal patterns = [ [:root, 'app_path: :app_path', :app_path], [:root, 'app: :app', :app], [:root, 'root: :root', :root], [:root, 'resources: :resources', :resources], [:root, ':resource', :resource], [:resource, 'model', :model], [:model, ':class_name', :model_class], [:model_class, /^(?<name>\w+):\s*(?<type>string|text|decimal)\s*,?(?<options>.*)/, :class_attribute], [:resource, /(?:controller \+ views|actionpack:)/, :resource_cv], [:resource_cv, /(\w+)(?:\s+([av]{1,2}))?/, :resource_cv_av], [:resource_cv_av, /(markdown):\s*(.*)/, :renderer], [:renderer, /.*/, :render_block], [:all, /^\s*;/, :comment] ] xml = parse(patterns, @config) @doc = Rexle.new xml @parent_path = Dir.pwd @notifications = [] end
Public Instance Methods
build(auto: false, desc: nil)
click to toggle source
# File lib/railsbuilder.rb, line 49 def build(auto: false, desc: nil) doc = @doc.root @auto_override = auto @app = app = doc.element('app/@app') return unless app unless File.exists? app then command = 'rails new ' + app puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to build a new app? (Y/n)' shell command trigger = "config: new app entry found which doesn't yet " \ + "exist as a file directory" activity = "new Rails app created" @notifications << [trigger,activity] else end @app_path = app_path = doc.element('app_path/@app_path') || File.join(@parent_path, app) puts 'changing directory to ' + app_path.inspect Dir.chdir app_path # select the :resource records root = doc.element('root/@root') routes = File.join('config','routes.rb') if root then # check if the config/routes.rb file needs updated buffer = File.read routes regex = / #( root 'welcome#index')/ if buffer[regex] or not buffer[/root '#{root}'/] then puts ':: updating ' + routes File.write routes, buffer.sub(regex, " root '" + root + "'") trigger = "config: new root added or changed" activity = "file: config/routes.rb modified" data = /^\s*root\s+'#{root}'/ @notifications << [trigger, activity, data] end end resources = doc.element('resources/@resources') if resources then buffer = File.read routes if not buffer[/\n\s*resources :#{resources}/] then puts ':: updating ' + routes File.write routes, buffer.sub(/\n resources :\w+/,'')\ .sub(/ # resources :products/) \ {|x| x + "\n resources :#{resources}"} trigger = "config: resources entry has been changed" activity = "file: config/routes.rb modified" data = /resources\s+:#{resources}/ @notifications << [trigger, activity, data] end end doc.xpath('resource').each do |node| resource = node.attributes[:resource] next unless resource controller = resource + '_controller.rb' controller_file = File.join('app','controllers', controller) node.elements.each do |child| case child.name.to_sym when :model # if there is no controller entry then apply the scaffold command if resource != '*' then # does the controller exitst? unless File.exists? controller_file then command = "rails g controller %s" % resource puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to generate a controller? (Y/n)' shell command trigger = "config: model found for a controller which " + "doesn't yet exist" activity = "file: created app/controllers/posts_controller.rb" @notifications << [trigger, activity] end # if the model fields are defined let's generate the model model = child.element('model_class') next unless model class_name = model.attributes[:class_name] next unless class_name #attributes = model.xpath('.').map {|x| x.attributes.values} attributes = model.xpath('.').map {|x| field_attributes x} next if attributes.empty? s = class_name + ' ' + attributes\ .map{|h| "%s:%s" % [h[:name], h[:type].to_s]}.join(' ') command = "rails generate model %s" % s puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to generate a model? (Y/n)' r = shell command next if r == :abort trigger = "config: a new model with associated entries has "\ + "been found" activity = "file: created app/models/#{class_name.downcase}.rb" @notifications << [trigger, activity] elsif not File.exists? controller_file then model = child.element('model_class') next unless model class_name = model.attributes[:class_name] next unless class_name attributes = model.xpath('.').map {|x| field_attributes x} next if attributes.empty? s = class_name + ' ' + attributes\ .map{|h| "%s:%s" % [h[:name], h[:type].to_s]}.join(' ') command = "rails generate scaffold %s" % s puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to generate a scaffold? (Y/n)' shell command trigger = "config: model found for a resouce called *" activity = "file: created app/controllers/posts_controller.rb" @notifications << [trigger, activity] # check to see if the class attributes contains options attributes_contain_options = attributes\ .select {|x| x[:options]} if attributes_contain_options then Dir.chdir File.join(app_path,%w(db migrate)) filename = Dir.glob('*.rb').first s = File.read filename attributes_contain_options.each do |x| options = x[:options].map {|y| y.join(': ')}.join(', ') s.sub!(/t\.#{x[:type].to_s}\s+:#{x[:name]}/,'\0, ' + options) end File.write filename, s Dir.chdir app_path end end # -- next command --------------------- command = "rake db:migrate" puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to commit this '\ + 'database operation? (Y/n)' shell command trigger = "... continuation from previous trigger" activity = "database: created" @notifications << [trigger, activity] when :resource_cv # fetch the action name action = child.element 'resource_cv_av/@captures0' if action then page = action + '.html.erb' view_file = File.join('app','views', resource, page) # if the controller exists don't try to generate the view, # instead add the entry to the controller file and # create the view file if File.exists? controller_file then buffer = File.read controller_file regex = /class \w+Controller < ApplicationController/ unless File.exists? view_file then File.write view_file, '' puts ':: created ' + page trigger = "config: the 1st action has been "\ + "created in the controller" activity = "file: created " + view_file @notifications << [trigger, activity] end child.elements.each do |av| action = av.attributes[:captures0] next unless action page = action + '.html.erb' unless buffer[/\bdef #{action}/] then buffer.sub!(regex) {|x| x + "\n def #{action}\n end\n" } File.write controller_file, buffer puts ':: updated ' + controller trigger = "config: an action has been "\ + "created in the controller + views section" activity = "file: updated " + controller_file data = /def #{action}/ @notifications << [trigger, activity, data] end av_type = av.attributes[:captures1] next unless av_type if av_type[/v/] then page = action + '.html.erb' view_file = File.join('app','views', resource, page) unless File.exists? view_file then File.write view_file, '' puts ':: created ' + page trigger = "config: an action has been "\ + "created in the controller + views section" activity = "file: updated " + controller_file data = /def #{action}/ @notifications << [trigger, activity, data] end # does it contain a renderer? e.g. markdown renderer = av.element 'renderer' next unless renderer type, text = renderer.attributes.values # open the related page and add the content if it # doesn't already exist render_block = renderer.text('render_block') raw_text = if text and render_block then text + "\n" + render_block elsif text then text elsif render_block then render_block end if type == 'markdown' and raw_text then html = RDiscount.new(raw_text).to_html buffer = File.read view_file unless buffer[/#{html}/] then File.write view_file, html + "\n" + buffer puts ':: updated ' + view_file trigger = "config: a rendering block has been "\ + "created or modified for an action" activity = "file: updated " + view_file data = /#{html}/ @notifications << [trigger, activity, data] end end end end else unless File.exists? view_file then actions = child.xpath('resource_cv_av') do |x| x.attributes[:captures0] end.join(' ') command = "rails generate controller %s %s" % [resource, actions] puts ":: preparing to execute shell command: `#{command}`" puts 'Are you sure you want to generate a ' \ + 'controller action? (Y/n)' shell command trigger = "config: a new action has been "\ + "created in the controller + views section for a "\ + "resource which doesn't have a model and the "\ + "controller file doesn't yet exist." activity = "file: created " + controller_file @notifications << [trigger, activity] end end end end # /case when end # / child iterator end snapshot(desc) if @journal and @notifications.any? Dir.chdir @parent_path @notifications.to_yaml end
notifications()
click to toggle source
# File lib/railsbuilder.rb, line 388 def notifications @notifications.to_yaml end
restore(level=-2)
click to toggle source
# File lib/railsbuilder.rb, line 392 def restore(level=-2) base = File.join(@tmp_path, 'railsbuilder', @app) dx = Dynarex.new File.join(base, 'dynarexdaily.xml') a = dx.all return 'no restore points available' if a.length < 1 level = 0 if a.length < 2 record = a[level] path = a[level].desc[/^[^;]+/] FileUtils.rm_rf @app_path FileUtils.copy_entry File.join(base, path), @app_path, preserve=true a.last.delete dx.save path + ' app restored' end
save(filepath=@parent_path)
click to toggle source
# File lib/railsbuilder.rb, line 411 def save(filepath=@parent_path) File.write File.join(filepath, "#{@app}.cfg"), @config end
to_doc()
click to toggle source
# File lib/railsbuilder.rb, line 415 def to_doc() @doc end
Private Instance Methods
field_attributes(e)
click to toggle source
# File lib/railsbuilder.rb, line 422 def field_attributes(e) h = { name: e.attributes[:name], type: e.attributes[:type].to_sym, } raw_opt = e.attributes[:options] if raw_opt.length > 0 then h[:options] = raw_opt.split(/\s*,?\s*\b(?=\w+:)/)[1..-1]\ .map {|x| x.split(':',2).map(&:lstrip)} end h end
parse(patterns, s=nil)
click to toggle source
# File lib/railsbuilder.rb, line 436 def parse(patterns, s=nil) if s.nil? then # is there a directory called site1? dir = 'site1' while File.exists? dir do i = dir.slice!(/\d+$/).to_i; dir += (i+=1).to_s end s =<<EOF # # railsbuilder configuration file # app: #{dir} # resources: posts EOF end @config = s LineParser.new(patterns, s).to_xml end
shell(command)
click to toggle source
# File lib/railsbuilder.rb, line 464 def shell(command) return system command if @auto_override if $stdin.getch[/y|\r/i]then IO.popen(command).each_line {|x| print "", x} else puts 'Abort' :abort end end
snapshot(desc=nil)
click to toggle source
# File lib/railsbuilder.rb, line 476 def snapshot(desc=nil) d = Time.now.strftime("%d-%b").downcase t = Time.now.strftime("%H%M_%S.%2N") snapshot_path = File.join(@tmp_path, 'railsbuilder', @app, d,t) FileUtils.mkdir_p snapshot_path FileUtils.copy_entry @app_path, snapshot_path, preserve=true al = ActivityLogger.new dir: File.join(@tmp_path, 'railsbuilder', @app) s = File.join(d,t) s << '; ' + desc if desc al.create s self.save snapshot_path end