Ember Js ·

Generate Ember.js models using your Rails Schema

I love Ember.js. I hate typing and I especially hate typing code that a machine could build. I got really tired of reading
a Rails schema to build new Ember.js models so I create a rake task for it. I make no guarantees that this code will
work for you or that it won’t delete some of your code or start a nuclear war. Enjoy!

(Link to gist if that’s easier.)

(Updated for Ember Data 1.0.0 beta.)


namespace :ember do

  desc "Build ember models from schema"
  task :models => :environment do

    # Change these values to fit your project
    namespace = 'App' # The Ember application's namespace.
    output_dir = File.join(Rails.root, "app/assets/javascripts/common/models") # The directory where ember models will be written

    schema_file = File.join(Rails.root, 'db/schema.rb')

    current = ''
    file = ''
    max = 0
    attrs = []

    File.readlines(schema_file).each do |line|

      # Stuff to ignore
      next if line.strip.blank?
      next if /#.*/.match(line)
      next if /add_index.+/.match(line)
      next if /ActiveRecord::Schema.define/.match(line)

      # Find tables in the schema
      if m = /create_table \"(.+)\".*/.match(line)
        current = "#{namespace}.#{m.captures[0].classify.singularize} = DS.Model.extend({\n"
        file = "#{m.captures[0].singularize}.js"
      elsif m = /t\.(.+)\s+"([0-9a-zA-z_]+)".*/.match(line)
        max = m.captures[1].length if m.captures[1].length > max
        attrs << m.captures
      elsif m = /end/.match(line) && current.present?
        attrs.each_with_index do |attr, i|
          spaces = ''
          type = 'string'
          if %w(integer float).include?(attr[0])
            type = 'number'
          elsif %w(datetime time date).include?(attr[0])
            type = 'date'
          elsif %w(boolean).include?(attr[0])
            type = 'boolean'
          end
          comma = ','
          if attrs.size-1 == i
            comma=''
          end
          ((max + 1) - attr[1].length).times{spaces << ' '}
          if attr[1].ends_with?('_id')
            relation = attr[1][0...(attr[1].length-3)]
            current << "  #{relation}:    #{spaces}DS.belongsTo('#{namespace}.#{relation.classify.singularize}'),\n"
          end
          current << "  #{attr[1]}: #{spaces}DS.attr('#{type}')#{comma}\n"
        end
        current << "});\n"
        f = File.join(output_dir, file)
        if File.exists?(f)
          puts "Ember model already exists: #{f}"
        else
          current.gsub!('_spaces_', '')
          puts "Writing Ember model: #{f}"
          File.open(f, 'w'){|f| f.write(current)}
        end

        current = ''
        file = ''
        max = 0
        attrs = []

      else
        if /end/.match(line).blank?
          puts "Don't know how to handle: #{line}"
        end
      end

    end

  end

end

</pre>