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 %w(handlebars-v1.3.0.js ember.js ember-data.js).each do |filename| base.send :get, "/#{filename}" do content_type :js, :charset => 'utf-8' File.read File.join(File.dirname(File.expand_path(__FILE__)), "../assets/#{filename}") 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 # Parse JSON payload # http://stackoverflow.com/a/17049683 before do request.body.rewind request_body = request.body.read @request_payload = JSON.parse(request_body, :symbolize_names => true) unless request_body.empty? end # 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, @request_payload[:post])}.to_json else param_names = model.properties.select{ |prop| prop.class != DataMapper::Property::Serial }.map{ |prop| prop.name } m = model.get(id) m.update(@request_payload[:post].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(@request_payload[:post])}.to_json else param_names = model.properties.select{ |prop| prop.class != DataMapper::Property::Serial }.map{ |prop| prop.name } m = model.create(@request_payload[:post].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