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