module MagLoft class RemoteResource attr_accessor :id attr_reader :destroyed def initialize(attributes = {}) allowed_attributes = attributes.slice(*self.class.remote_attributes) Dialers::AssignAttributes.call(self, allowed_attributes.except(:id)) end def changed? changed_data.keys.count > 0 end def destroyed? destroyed == true end def save return false if destroyed? or !changed? if changed_data.keys.count > 0 if id.nil? transformable = Api.client.api_caller.post(self.class.endpoint, changed_data) else transformable = Api.client.api_caller.put("#{self.class.endpoint}/#{id}", changed_data.except(:id)) end transformable.transform_to_existing(self) clear_changed_data! end self end def destroy return false if id.nil? or destroyed? transformable = Api.client.api_caller.delete("#{self.class.endpoint}/#{id}") transformable.transform_to_existing(self) @destroyed = true clear_changed_data! self end def changed_data @changed_data ||= {} end def clear_changed_data! @changed_data = {} self end def update_data(key, value) if send(key) != value instance_variable_set("@#{key}", value) changed_data[key] = value end end class << self def remote_attributes @remote_attributes ||= [] end def remote_attribute(*args) args.each do |arg| remote_attributes.push(arg) class_eval("attr_accessor :#{arg}", __FILE__, __LINE__) class_eval("def #{arg}=(val);update_data(:#{arg}, val);end", __FILE__, __LINE__) end end def endpoint(path = nil) if path.nil? @endpoint else @endpoint = path end end def find(id) api.get("#{endpoint}/#{id}").transform_to_one(self) end def find_one(params) where(params).first end def where(params) api.get(endpoint, params).transform_to_many(self) end def all api.get(endpoint).transform_to_many(self) end def create(attributes = {}) entity = new(attributes) entity.save entity end def method_missing(name, *args, &block) if name[0..7] == "find_by_" and args.length == 1 attribute = name[8..-1].to_sym if remote_attributes.include?(attribute) params = {} params[attribute] = args.first return find_one(params) end end super end def respond_to_missing?(method_name, include_private = false) method_name.to_s.start_with?('find_by_') || super end private def api Api.client.api_caller end end end end