'Apply CRUD methods
@param r: the S3Request
@param attr: dictionary of parameters for the method handler
@return: output object to send to the view'

def apply_method(self, r, **attr):

    self.settings = current.response.s3.crud
    sqlform = self._config('crud_form')
    self.sqlform = (sqlform if sqlform else S3SQLDefaultForm())
    self.data = None
    if ((r.http == 'GET') and (not self.record_id)):
        populate = attr.pop('populate', None)
        if callable(populate):
            try:
                self.data = populate(r, **attr)
            except TypeError:
                self.data = None
            except:
                raise
        elif isinstance(populate, dict):
            self.data = populate
    method = self.method
    if ((r.http == 'DELETE') or (self.method == 'delete')):
        output = self.delete(r, **attr)
    elif (method == 'create'):
        output = self.create(r, **attr)
    elif (method == 'read'):
        output = self.read(r, **attr)
    elif (method == 'update'):
        output = self.update(r, **attr)
    elif (method == 'list'):
        output = self.select(r, **attr)
    elif (method in ('datatable', 'datatable_f')):
        _attr = Storage(attr)
        _attr['list_type'] = 'datatable'
        if (method == 'datatable_f'):
            self.hide_filter = False
        output = self.select(r, **_attr)
    elif (method in ('datalist', 'datalist_f')):
        _attr = Storage(attr)
        _attr['list_type'] = 'datalist'
        if (method == 'datalist_f'):
            self.hide_filter = False
        output = self.select(r, **_attr)
    elif (method == 'validate'):
        output = self.validate(r, **attr)
    elif (method == 'review'):
        if r.record:
            output = self.review(r, **attr)
        else:
            output = self.unapproved(r, **attr)
    else:
        r.error(405, current.ERROR.BAD_METHOD)
    return output
