extends 'Catalyst::Model';
with 'CatalystX::Component::Traits';
-our $VERSION = '0.24';
+our $VERSION = '0.26';
use namespace::autoclean;
use Carp::Clan '^Catalyst::Model::DBIC::Schema';
use Data::Dumper;
use DBIx::Class ();
use Moose::Autobox;
+use Class::Inspector ();
use Catalyst::Model::DBIC::Schema::Types
- qw/ConnectInfo SchemaClass CursorClass/;
+ qw/ConnectInfo LoadedClass/;
use MooseX::Types::Moose qw/ArrayRef Str ClassName Undef/;
=head1 METHODS
+Methods not listed here are delegated to the connected schema used by the model
+instance, so the following are equivalent:
+
+ $c->model('DB')->schema->my_accessor('foo');
+ # or
+ $c->model('DB')->my_accessor('foo');
+
+Methods on the model take precedence over schema methods.
+
=head2 new
Instantiates the Model based on the above-documented ->config parameters.
=cut
-has schema => (is => 'rw', isa => 'DBIx::Class::Schema');
-
has schema_class => (
is => 'ro',
- isa => SchemaClass,
+ isa => LoadedClass,
coerce => 1,
required => 1
);
has storage_type => (is => 'rw', isa => Str);
-has connect_info => (is => 'ro', isa => ConnectInfo, coerce => 1);
+has connect_info => (is => 'rw', isa => ConnectInfo, coerce => 1);
has model_name => (
is => 'ro',
has _default_cursor_class => (
is => 'ro',
- isa => CursorClass,
+ isa => LoadedClass,
default => 'DBIx::Class::Storage::DBI::Cursor',
coerce => 1
);
$self->composed_schema($schema_class->compose_namespace($class));
+ $self->meta->make_mutable;
+ $self->meta->add_attribute('schema',
+ is => 'rw',
+ isa => 'DBIx::Class::Schema',
+ handles => $self->_delegates
+ );
+ $self->meta->make_immutable;
+
$self->schema($self->composed_schema->clone);
+ $self->_pass_options_to_schema;
+
$self->schema->storage_type($self->storage_type)
if $self->storage_type;
sub connect { shift->composed_schema->connect(@_); }
-sub storage { shift->schema->storage(@_); }
-
-sub resultset { shift->schema->resultset(@_); }
-
=head2 setup
-Called at C<BUILD>> time before configuration, but after L</connect_info> is
+Called at C<BUILD> time before configuration, but after L</connect_info> is
set. To do something after configuuration use C<< after BUILD => >>.
=cut
return $model_name;
}
+sub _delegates {
+ my $self = shift;
+
+# XXX change this to CMOP once CAG is updated
+ my @schema_methods = @{ Class::Inspector->methods($self->schema_class) };
+
+# combine with any already added by other schemas
+ my @handles = eval {
+ @{ $self->meta->find_attribute_by_name('schema')->handles }
+ };
+
+# now kill the attribute, otherwise add_attribute in BUILD will not do the right
+# thing. May be a Moose bug.
+ eval { $self->meta->remove_attribute('schema') };
+
+ my %schema_methods;
+ @schema_methods{ @schema_methods, @handles } = ();
+ @schema_methods = keys %schema_methods;
+
+ my @my_methods = $self->meta->get_all_method_names;
+ my %my_methods;
+ @my_methods{@my_methods} = ();
+
+ my @delegates;
+ for my $method (@schema_methods) {
+ push @delegates, $method unless exists $my_methods{$method};
+ }
+
+ return \@delegates;
+}
+
+sub _pass_options_to_schema {
+ my $self = shift;
+
+ my @attributes = map $_->name, $self->meta->get_all_attributes;
+ my %attributes;
+ @attributes{@attributes} = ();
+
+ for my $opt (keys %$self) {
+ if (not exists $attributes{$opt}) {
+ next unless $self->schema->can($opt);
+ $self->schema->$opt($self->{$opt});
+ }
+ }
+}
+
__PACKAGE__->meta->make_immutable;
=head1 SEE ALSO
L<DBIx::Class>, L<DBIx::Class::Schema>,
L<DBIx::Class::Schema::Loader>, L<Catalyst::Helper::Model::DBIC::Schema>,
-L<MooseX::Object::Pluggable>
+L<CatalystX::Component::Traits>, L<MooseX::Traits::Pluggable>
Traits:
=head1 AUTHOR
-Brandon L Black, C<blblack at gmail.com>
+Brandon L Black C<blblack at gmail.com>
-Contributors:
+=head1 CONTRIBUTORS
-Rafael Kitover, C<rkitover at cpan.org>
+caelum: Rafael Kitover C<rkitover at cpan.org>
=head1 COPYRIGHT