- Interface::Action::DBIC::ResultSet::Create - InterfaceModel::Action - parameter_hashref = names/values of all the parameter_attributes which can be read and do not have a false predicate - parameter_attributes = all the applicable attributes which are of type ParameterAttribute (?) - target_model is read-only+required ? - can_apply is false if an attribute is required and we have no predicate (?), or ... - Meta::InterfaceModel::Action::ParameterAttribute - has_valid_values = "this attribute is a pick-list and we need to verify the value is in the list" - valid_values = returns the pick-list values - check_valid_value = check the value is an arrayref if the typeconstraint of the attribute is one or is descended from one; call _check_single_valid for each array item, return mapped results. Else _check_single_valid. - _check_single_valid = If valid is an array to check against, return the value if it is in the array. Otherwise, if the value is blessed, assume $valid is an RS and find $value using it's ident_condition (PK, in DBIC terms). Return undef if not fonud. - valid_values (attribute) isa coderef, with predicate 'has_valid_values'. - all_valid_values = return valid_values as a list, call ->all on valid_values result if it isnt an ARRAY. - valid_value_collection = returns valid_values if it is a resultset, dies otherwise. - target_model set to isa DBIx::Class::ResultSet for this action - do_apply = creates a new target_model, find the attributes using the parameter_hashref keys, find the write/accessor method, store value from p_hashref. If the attribute has a type constraint of arrayref, store those values (calling accessor mehod on new, which is presumably "add_to" here), and create after ->insert. returns the new object. - InterfaceModel::Action::DBIC::Role::CheckUniques - check_all_uniques = Uses the sources unique_constraints; finds all the current values of the parameter_attributes (using reader/accessor) to look for existing rows matching this one - Reaction::UI::CRUDController - create - add a new viewport using push_viewport, ActionForm_class, ->get_model_action, next_action => list .. - get_model_action = If the target (the model class) supports "action_for" then return it using params action name ("Create") and $c. Otherwise find $c->model('Action::' actioname. . ->model_name, and return a new instance with the target_model and $c. - Catalyst::Controller::action_for = find and return the action object for the given action - get_collection = ->model_base '::' ->model_name - model_base = attribute - model_name = attribute - ActionForm_class = attribute, defaults to the ActionForm class - after_create_callback = redirect to 'update' ? - Reaction::UI::Controller::redirect_to = $c->res->redirect to the uri_for the given controller action So: CRUDController creates ActionForm viewports in it's create+update actions. The action passed in is a new instance of MyApp::Model::Action::Create. where the TableName is set in the CRUDController descendent config as model_baes, model_name. The list action uses these (via get_collection) to tell the ListView what to display. The object (view) action uses the collection to find() the object to display by id. Can we use this? Can we call find() on a search result ? Action classes should be isa Reaction::InterfaceModel::Action (see ActionForm). BUILD uses the parameter_attributes to create the field_map and field_names. ====== 2008-04-24: Non-CRUD actions. Layers: - Data (database, file, web source, etcetc) - Data Interface (Domain model), for DBIC a Catalyst::Model::Reaction::InterfaceModel::DBIC, - knows what the class is for the interface model - returns IM objects when fetched via $c->model - Abstract Data Interface (InterfaceModel), can be reflected from the domain model - hides the data interface's API - adds abstractions for Collections and Actions that can be performed (eg for CRUD) - add your own generic methods here - http://en.wikipedia.org/wiki/Facade_pattern - View Model (ViewPort) - knows which parts of the model/data the user is currently interacting with - created by catalyst actions, or other ViewPorts - standard ones included, eg "Action" for a form - Controller (catalyst) (Reaction::UI::Controller) - creates IM/collection objects containing the current data for the current action - creates the viewport objects for the current action - stuffs them in the viewport stack to be rendered by the view - End action (Reaction::UI::Controller::Root) - calls flush on the Window object in stash (has viewports in) - View (catalyst) (Reaction::UI::View) - - View, loades Reaction::UI::Skin - creates new Skin with ->skin_name, view => $self, skin_base_dir = path_to share/skin - view->app isa $context - render_window retrieves the widget via render_viewport_args - render_viewport_args calls layout_set_for(vp), widget_for(vp, layoutset) - widget_for returns layout_set->widget_class->new(view, layoutset) - layout_set_for calls vp->layout then tries layout_set_name_from_viewport(vp class) Rendering a Page: After all the ViewPorts for the current page are created and stuffed onto the viewport stack, flow is passed to Reaction::UI::View which will attempt to render the page. Ingredients: * LayoutSet class: Reaction::UI::LayoutSet * RenderingContext class: Reaction::UI::RenderingContext::TT * A Reaction::UI::Skin object built from: * The skin_name set on your View * The View object * The skin_base_dir (MyApp/share/skin) * The share/skin/defaults.conf + share/skin//skin.conf * A Reaction::UI::LayoutSet object built from: * The layoutset file itself, found in the share/skin//layout directory or the share/skin/default/layout directory. * The Skin object * A Reaction::UI::Widget object built from: * It's class, determined from the name of the ViewPort or read from the layoutset file, and found in the widget_search_path. * The View object * The LayoutSet object * A Reaction::UI::RenderingContext::TT object built from: * Nothing To render the window the correct Reaction::UI::Widget object is retrieved via the LayoutSet for the root ViewPort of the page. The LayoutSet used defaults to the "layout" attribute on the ViewPort. If there is no layout attribute value set, it takes the class name of the ViewPort, extracts the parts following "::ViewPort::" and constructs the layoutset from converting camel cased parts of the namespace to lower-case underscored, and namespace parts into directories. ## eg: My::ViewPort::Action::UserForm ## becomes action/user_form The layoutset file should exist in the skin_base_dir, in the "layout" directory under the "skin_name" dir set in your View config, or in the "default/layout" directory. [[ A LayoutSet object is created based on the layoutset name, skin object, source_file (path to file), top_skin (skin object), next_skin if exists ]]. The layoutset file is parsed as the LayoutSet object is created, if a "=widget" line is found, the "widget_type" attribute is set. The class of the Widget object can be set in the layoutset object args, or it defaults to being fetched via the Skin. The type of widget is either specified in the layoutset file via the "=widget" directive or retrieved by recreating the camelcased name from the layoutset name. The Widget is assumed to be in the widget search path provided by defaults.conf or your skin.conf. The Widget itself is passed the ViewPort to render, and the RenderingContext. The initial fragment name to render is also passed, "widget". The render stack is created using the widget order. The widget order is fetched for the fragment from the layoutset, this is either the widget class/layoutset, or retrieved from the extended layouts. As the render_stack is built, the fragment methods in the Widget are called to assign values from the ViewPort to arguments for the layout. (Or other interesting things). The stack is passed to the RenderingContext to complete. ========= CRUD+IMs - Reaction::UI::Controller::Collection::CRUD - isa Reaction::UI::Controller::Collection - create/list/update/delete/delete_all all call basic_model_action - $target is either the stashed object or $self->get_collection - Collection::get_collection calls $collectionname on the $model - The model isa: Catalyst::Model::Reaction::InterfaceModel::DBIC - isa Catalyst::Component ========= - Reaction::UI::Controller - push_viewport, pop_viewport, pop_viewports_to, redirect_to