lib/rfm/layout.rb in ginjo-rfm-1.4.4 vs lib/rfm/layout.rb in ginjo-rfm-2.0.pre31

- old
+ new

@@ -117,10 +117,12 @@ # * +value_lists+ is a hash of arrays. The keys are value list names, and the values in the hash # are arrays containing the actual value list items. +value_lists+ will include every value # list that is attached to any field on the layout class Layout + + include ComplexQuery # Initialize a layout object. You never really need to do this. Instead, just do this: # # myServer = Rfm::Server.new(...) # myDatabase = myServer["Customers"] @@ -131,131 +133,186 @@ # # In case it isn't obvious, this is more easily expressed this way: # # myServer = Rfm::Server.new(...) # myLayout = myServer["Customers"]["Details"] - def initialize(name, db) - @name = name - @db = db + def initialize(name, db_obj) + raise Rfm::Error::RfmError.new(0, "New instance of Rfm::Layout has no name.") if name.to_s == '' + @name = name.to_s + rfm_metaclass.instance_variable_set :@db, db_obj @loaded = false @field_controls = Rfm::CaseInsensitiveHash.new - @value_lists = Rfm::CaseInsensitiveHash.new + @value_lists = Rfm::CaseInsensitiveHash.new + # @portal_meta = nil + # @field_names = nil end - attr_reader :name, :db + meta_attr_reader :db + attr_reader :name #, :db + attr_writer :field_names, :portal_meta, :table + def_delegator :db, :server + alias_method :database, :db - # Returns a ResultSet object containing _every record_ in the table associated with this layout. - def all(options = {}) - get_records('-findall', {}, options) - end - # Returns a ResultSet containing a single random record from the table associated with this layout. - def any(options = {}) - get_records('-findany', {}, options) - end - - # Finds a record. Typically you will pass in a hash of field names and values. For example: - # - # myLayout.find({"First Name" => "Bill"}) - # - # Values in the hash work just like value in FileMaker's Find mode. You can use any special - # symbols (+==+, +...+, +>+, etc...). - # - # If you pass anything other than a hash as the first parameter, it is converted to a string and - # assumed to be FileMaker's internal id for a record (the recid). - def find(hash_or_recid, options = {}) - if hash_or_recid.kind_of? Hash - get_records('-find', hash_or_recid, options) - else - get_records('-find', {'-recid' => hash_or_recid.to_s}, options) - end - end - - # Updates the contents of the record whose internal +recid+ is specified. Send in a hash of new - # data in the +values+ parameter. Returns a RecordSet containing the modified record. For example: - # - # recid = myLayout.find({"First Name" => "Bill"})[0].record_id - # myLayout.edit(recid, {"First Name" => "Steve"}) - # - # The above code would find the first record with _Bill_ in the First Name field and change the - # first name to _Steve_. - def edit(recid, values, options = {}) - get_records('-edit', {'-recid' => recid}.merge(values), options) - end + # These methods are to be inclulded in Layout and SubLayout, so that + # they have their own descrete 'self' in the master class and the subclass. + module LayoutModule - # Creates a new record in the table associated with this layout. Pass field data as a hash in the - # +values+ parameter. Returns the newly created record in a RecordSet. You can use the returned - # record to, ie, discover the values in auto-enter fields (like serial numbers). - # - # For example: - # - # result = myLayout.create({"First Name" => "Jerry", "Last Name" => "Robin"}) - # id = result[0]["ID"] - # - # The above code adds a new record with first name _Jerry_ and last name _Robin_. It then - # puts the value from the ID field (a serial number) into a ruby variable called +id+. - def create(values, options = {}) - get_records('-new', values, options) - end + # Returns a ResultSet object containing _every record_ in the table associated with this layout. + def all(options = {}) + get_records('-findall', {}, options) + end + + # Returns a ResultSet containing a single random record from the table associated with this layout. + def any(options = {}) + get_records('-findany', {}, options) + end + + # Finds a record. Typically you will pass in a hash of field names and values. For example: + # + # myLayout.find({"First Name" => "Bill"}) + # + # Values in the hash work just like value in FileMaker's Find mode. You can use any special + # symbols (+==+, +...+, +>+, etc...). + # + # If you pass anything other than a hash as the first parameter, it is converted to a string and + # assumed to be FileMaker's internal id for a record (the recid). + def find(hash_or_recid, options = {}) + if hash_or_recid.kind_of? Hash + get_records('-find', hash_or_recid, options) + else + get_records('-find', {'-recid' => hash_or_recid.to_s}, options) + end + end + + # Updates the contents of the record whose internal +recid+ is specified. Send in a hash of new + # data in the +values+ parameter. Returns a RecordSet containing the modified record. For example: + # + # recid = myLayout.find({"First Name" => "Bill"})[0].record_id + # myLayout.edit(recid, {"First Name" => "Steve"}) + # + # The above code would find the first record with _Bill_ in the First Name field and change the + # first name to _Steve_. + def edit(recid, values, options = {}) + get_records('-edit', {'-recid' => recid}.merge(values), options) + end + + # Creates a new record in the table associated with this layout. Pass field data as a hash in the + # +values+ parameter. Returns the newly created record in a RecordSet. You can use the returned + # record to, ie, discover the values in auto-enter fields (like serial numbers). + # + # For example: + # + # result = myLayout.create({"First Name" => "Jerry", "Last Name" => "Robin"}) + # id = result[0]["ID"] + # + # The above code adds a new record with first name _Jerry_ and last name _Robin_. It then + # puts the value from the ID field (a serial number) into a ruby variable called +id+. + def create(values, options = {}) + get_records('-new', values, options) + end + + # Deletes the record with the specified internal recid. Returns a ResultSet with the deleted record. + # + # For example: + # + # recid = myLayout.find({"First Name" => "Bill"})[0].record_id + # myLayout.delete(recid) + # + # The above code finds every record with _Bill_ in the First Name field, then deletes the first one. + def delete(recid, options = {}) + get_records('-delete', {'-recid' => recid}, options) + return nil + end + + def get_records(action, extra_params = {}, options = {}) + include_portals = options[:include_portals] ? options.delete(:include_portals) : nil + xml_response = db.server.connect(db.account_name, db.password, action, params.merge(extra_params), options).body + Rfm::Resultset.new(db.server, xml_response, self, include_portals) + end + + def params + {"-db" => db.name, "-lay" => self.name} + end + + end # LayoutModule + include LayoutModule - # Deletes the record with the specified internal recid. Returns a ResultSet with the deleted record. - # - # For example: - # - # recid = myLayout.find({"First Name" => "Bill"})[0].record_id - # myLayout.delete(recid) - # - # The above code finds every record with _Bill_ in the First Name field, then deletes the first one. - def delete(recid, options = {}) - get_records('-delete', {'-recid' => recid}, options) - return nil - end def field_controls load unless @loaded @field_controls end + def field_names + load unless @field_names + @field_names + end + + def field_names_no_load + @field_names + end + def value_lists load unless @loaded @value_lists end - private + def total_count + any.total_count + end + + def portal_meta + @portal_meta ||= any.portal_meta + end + + def portal_meta_no_load + @portal_meta + end + + def portal_names + portal_meta.keys + end + + def table + @table ||= any.table + end + + def table_no_load + @table + end def load - #require 'rexml/document' - require 'nokogiri' - @loaded = true - fmpxmllayout = @db.server.load_layout(self) - doc = Nokogiri::XML(fmpxmllayout) + fmpxmllayout = db.server.load_layout(self) + doc = XmlParser.new(fmpxmllayout.body, :namespace=>false, :parser=>server.state[:parser]) # check for errors - error = doc.xpath('//ERRORCODE').children[0].to_s.to_i + error = doc['FMPXMLLAYOUT']['ERRORCODE'].to_s.to_i raise Rfm::Error::FileMakerError.getError(error) if error != 0 # process valuelists - if doc.xpath('//VALUELIST').size > 0 - doc.xpath('//VALUELIST').each {|valuelist| + vlists = doc['FMPXMLLAYOUT']['VALUELISTS']['VALUELIST'] + if !vlists.nil? #root.elements['VALUELISTS'].size > 0 + vlists.each {|valuelist| name = valuelist['NAME'] - @value_lists[name] = valuelist.children.collect{|value| - Rfm::Metadata::ValueListItem.new(value.children[0].to_s, value['DISPLAY'], name) + @value_lists[name] = valuelist['VALUE'].collect{|value| + Rfm::Metadata::ValueListItem.new(value['__content__'], value['DISPLAY'], name) } rescue [] } @value_lists.freeze end # process field controls - doc.xpath('//FIELD').each {|field| + doc['FMPXMLLAYOUT']['LAYOUT']['FIELD'].each {|field| name = field['NAME'] - style_xml = field.children[0] - style = style_xml['TYPE'] - value_list_name = style_xml['VALUELIST'] + style = field['STYLE'] + type = style['TYPE'] + value_list_name = style['VALUELIST'] value_list = @value_lists[value_list_name] if value_list_name != '' - field_control = Rfm::Metadata::FieldControl.new(name, style, value_list_name, value_list) + field_control = Rfm::Metadata::FieldControl.new(name, type, value_list_name, value_list) existing = @field_controls[name] if existing if existing.kind_of?(Array) existing << field_control else @@ -263,19 +320,14 @@ end else @field_controls[name] = field_control end } - @field_controls.freeze + @field_names ||= @field_controls.collect{|k,v| v.name rescue v[0].name} + @field_controls.freeze end - def get_records(action, extra_params = {}, options = {}) - include_portals = options[:include_portals] ? options.delete(:include_portals) : nil - xml_response = @db.server.connect(@db.account_name, @db.password, action, params.merge(extra_params), options).body - Rfm::Resultset.new(@db.server, xml_response, self, include_portals) - end - - def params - {"-db" => @db.name, "-lay" => self.name} - end - end -end + private :load, :get_records, :params + + + end # Layout +end # Rfm \ No newline at end of file