require 'erb' FRONTEND_MODELS = {} class ZWRouter attr_reader :routes def initialize @routes = {} @active = false end def has_route? route_name @routes.has_key? route_name end def switch new_val = true @active = new_val end def method_missing method_name, *args, &block if [:create, :read, :update, :destroy, :index].include? method_name if @active @routes[method_name].call args else @routes[method_name] = block end else super end end end module ZWResources # Collect resources for ember model definitions def frontend_model model_name, model FRONTEND_MODELS[model_name] = ( model.properties.to_a.map! do |property| {name: property.name} end ) end # Route to send model definitions to ember def self.extended base base.send :get, '/models.js' do content_type :js, :charset => 'utf-8' # @@models_js_template defined at bottom of module def Tilt::ERBTemplate.new{@@models_js_template}.render end Dir.glob(File.join('..', 'assets')) do |file| # TODO cross-platform? probably not. base.send :get, file.split('/').last do content_type :js, :charset => 'utf-8' send_file file end end end def resource model_sym, &block model_name_string = model_sym.to_s model_name = model_name_string[0].upcase + model_name_string[1..-2] model = Kernel.const_get(model_name) frontend_model model_name, model # Sends model definition to ember router = ZWRouter.new if block_given? block.call(router) end router.switch puts "***" puts router.routes.inspect # Find get "/#{model_name_string}/:id" do |id| content_type :json, :charset => 'utf-8' if router.has_route? :read {post: router.read(id)}.to_json else {post: model.get(id)}.to_json end end # Find All get "/#{model_name_string}" do content_type :json, :charset => 'utf-8' if router.has_route? :index {posts: router.index}.to_json else {posts: model.all}.to_json end end # Update put "/#{model_name_string}/:id" do |id| content_type :json, :charset => 'utf-8' if router.has_route? :update {post: router.update(id, params)}.to_json else param_names = model.properties.select{ |prop| prop.class != DataMapper::Property::Serial }.map{ |prop| prop.name } m = model.get(id) m.update(params.select{ |k,v| param_names.include? k.to_sym }) {post: m}.to_json end end # Create post "/#{model_name_string}" do content_type :json, :charset => 'utf-8' if router.has_route? :create {post: router.create(params)}.to_json else param_names = model.properties.select{ |prop| prop.class != DataMapper::Property::Serial }.map{ |prop| prop.name } m = model.create(params.select{ |k,v| param_names.include? k.to_sym }) {post: m}.to_json end end # Delete delete "/#{model_name_string}/:id" do |id| content_type :json, :charset => 'utf-8' if router.has_route? :destroy {post: router.destroy(params)}.to_json else model.get(id).destroy {}.to_json end end end # ERB template for models.js file @@models_js_template = <<'END' window.App = Ember.Application.create(); var attr = DS.attr; <% FRONTEND_MODELS.each do |model_name, model| %> App.<%= model_name %> = DS.Model.extend({ <%= model.delete_if do |property| property[:name] == :id end.map do |property| "#{property[:name]}: attr()" end.join(",\n ") %> }); <% end %> END end