I am writing a build script to build a Catalyst app and apparently it's an older app since it uses Catalyst::Plugin::Cache::FileCache instead of the newer Catalyst::Plugin::Cache which supports a FileCache option. When doing a build through Makefile.PL I can't use cpanm because Catalyst::Plugin::Cache::FileCache is no longer retrievable. :-(
Finding the way to do that is what is proving problematic for me though.
I suppose I could make changes to the app to use Catalyst::Plugin::Cache but I'm not finding the documentation clear, or any easy way to do it.
Currently the app uses this....
__PACKAGE__->config( name => 'Stats', cache =>{storage=>'./tmp'} );
http://search.cpan.org/~mramberg/Catalyst-Plugin-Cache-FileCache-0.7/lib/Catalyst/Plugin/Cache/FileCache.pm is the documentation for the deprecated module.
The new documentation for Catalyst::Plugin::Cache is here..... http://metacpan.org/pod/Catalyst::Plugin::Cache
In one of my models, I have this....
__PACKAGE__->config(
schema_class => 'Schema::STATS',
connect_info => [
'dbi:ODBC:DSN=....;driver=...;Server=...;database=...;RB_CONFIG=...;',
'USER',
'PASS',
{limit_dialect=>'GenericSubQ',
on_connect_do => ['set dateformat ymd'],
cursor_class => 'DBIx::Class::Cursor::Cached'
}
],
);
sub COMPONENT {
my $self = shift->NEXT::COMPONENT(#_);
$self->schema->default_resultset_attributes({ cache_object => Cache::FileCache->
new({ namespace => 'Schema::STATS' }), cache_for=>3600});
return $self;
}
I'm looking to make as few changes as possible right now to this app but is anyone aware of any easier way to make the couple of changes I need to switch to the newer Catalyst::Plugin::Cache?
Worse comes to worse I could always just package the older Catalyst::Plugin::Cache::FileCache source and install it but I was hoping there would just be an easier way to to use the new one.
Many thanks!
Janie
__PACKAGE__->config(
'Plugin::Cache' => {
backends => {
default => {
class => "Cache::FileCache",
cache_root => "./tmp",
namespace => "Pick Something",
}
}
);
and removing Plugin::Cache::FileCache and adding Plugin::Cache should get you about 90% of the way there. $c->cache will keep working as you expect, and it will be a vanilla Cache::FileCache object.
Related
I'd like to ask you for an advice regarding attribute accessors' naming.
I started to develop a project that is supposed to have quite a ramified hierarchy of classes, for example, the SomeFramework class, a bunch of classes like SomeFramework::Logger and, let's say, classes similar to SomeFramework::SomeSubsystem::SomeComponent::SomeAPI classes.
My goal is to design the most efficient communication between all these classes. I'll explain how I'm doing it now, so maybe you would like to share some opinions on how to make it better.
When I initialize the SomeFramework class, I have an object reference which I use from my application.
my $someframework = SomeFramework->new(parameter => 'value');
The SomeFramework class has some attributes, such as logger, configuration, etc, here are some examples of their definitions:
has 'logger' => (
is => 'ro',
isa => 'SomeFramework::Logger',
reader => 'get_logger',
writer => '_set_logger',
builder => '_build_logger',
lazy => 1
);
sub _build_logger {
my $self = shift;
SomeFramework::Logger->new(someframework => $self);
}
I'm passing the reference to the parent object to the child object, because I need the child to have access to the parent and its methods & accessors. So in the SomeFramework::Logger I have such attribute:
has 'someframework' => (
is => 'ro',
isa => 'SomeFramework',
reader => 'get_someframework',
writer => '_set_someframework',
required => 1
);
It lets me to have access to any object from within the SomeFramework::Logger class, usually it looks something like that:
my $configuration =
$self->
get_someframework->
get_configuration->
get_blah_blah;
To extrapolate it, let's look into the SomeFramework::SomeSubsystem::SomeComponent::SomeAPI class. This class has its own "parent" attribute (let's call it somecomponent) which is supposed to have a reference to a SomeFramework::SomeSubsystem::SomeComponent object as the value. The SomeFramework::SomeSubsystem::SomeComponent class has the attribute for its own parent attribute (we can call it somesubsystem) which is supposed to contain a reference to a SomeFramework::SomeSubsystem object. And, finally, this class has the attribute for its own parent too (someframework), so it contains the reference to a SomeFramework object.
It all makes it possible to have something like that inside of the SomeFramework::SomeSubsystem::SomeComponent::SomeAPI class:
my $configuration =
$self->
get_someframework->
get_somesubsystem->
get_somecomponent->
get_configuration->
get_blah_blah;
The first thing I'd like to know: is it a good practice? I hope, it is, but maybe you would advice me to go some more smooth way?
The second question is a bit more complicated (as for me), but I hope you'll help me with it. :) I like canonical names of accessors recommended by D.Conway in his "Perl Best Practices", but I'd like to do something like that:
my $configuration = $self->sc->ss->sf->conf->blah_blah;
Surely I can name all readers in this laconical manner:
has 'some_framework' => (
is => 'ro',
isa => 'SomeFramework',
reader => 'sf',
writer => '_set_someframework',
required => 1
);
But I don't like the idea of managing without the "standard" accessors names. :(
Also I can use MooseX::Aliases, it works fine for something like that:
has 'some_framework' => (
is => 'ro',
isa => 'SomeFramework',
reader => 'get_someframework',
writer => '_set_someframework',
required => 1,
alias => 'sf'
);
It looks fine, but there's an issue with attributes which names do NOT needed to be shortened. For example:
has 'api' => (
is => 'ro',
isa => 'SomeFramework::SomeSubsystem::SomeComponent::API',
reader => '_get_api',
writer => '_set_api',
required => 1,
alias => 'api'
);
In this case Moose throws an exception: Conflicting init_args: (api, api) at constructor. :( As I understand, MooseX::Aliases tries to create an attribute with the same value of the init_args parameter, so it fails. By the way, sometimes it happens, but sometimes it works fine, I haven't discovered when exactly it doesn't work.
Maybe I should have something like that:
has 'api' => (
is => 'ro',
isa => 'SomeFramework::SomeSubsystem::SomeComponent::API',
reader => '_get_api',
writer => '_set_api',
required => 1,
handles => {
api => 'return_self' # It's supposed to have some method that only
# returns the reference to its own object
}
);
? But it doesn't seem to be the best option too, because it helps me only if the attribute contains a reference some object for which I can define the return_self method. If the attribute contains a reference to some "foreign" object or some other value (e.g., a hash), it won't be possible to call that method. :(
Ugh... Sorry for such a long rant! I hope, you have managed to read to here. :)
I'll be very happy to get to know what do you thing and what would you suggest to do. Feel free to share any your ideas on this topic, any fresh ideas will be very appreciated!
Updated on 25.10.2015
As for the bigger question, let me see if I understood. There are an Apple and a Banana. The Fridge has both of them inside. But you want the Apple to know about the Fridge, and the Worm should know about the Apple, so that it can go from Worm up to Apple up to Fridge and turn the $fridge->light off when it wants to sleep. Is that correct? Sounds like a horrible idea that breaks all kinds of design patterns
Well, to be frank, I didn't think it's horrible. As for me, it's quite good when it's possible to have access from some class to some other class within the same framework. Why not? For example, let's imagine we have some class for the jobs-queue runner (let's call it SomeFramework::JobsQueue::Executor) and some class for jobs. Is it really bad to do something like:
package SomeFramework::JobsQueue::Executor;
use Moose;
use MooseX::Params::Validate;
has queue {
isa => 'SomeFramework::JobsQueue',
required => 1,
reader => 'get_queue',
writer => '_set_queue'
}
# This attribute is being set by the framework when the framework
# creates the SomeFramework::JobsQueue::Executor-based object
sub execute {
my($self, $job, $options) = validated_hash(
\#_,
job => { isa => 'SomeFramework::JobsQueue::Job' },
options => { isa => 'HashRef' }
);
my $queue = $self->get_queue;
$queue->mark_as_running($job->get_id);
$job->execute(options => $options);
$queue->mark_as_completed($job->get_id);
}
? So, our queue-runner object is aware about the queue object it "belongs" to, so it can call some methods of this queue object.
Or let's look at much more simple example:
package SomeFramework::SomeSubsystem;
use Moose;
has 'some_framework' => {
isa => 'SomeFramework',
required => 1,
reader => 'get_some_framework',
writer => '_set_some_framework'
}
sub some_method {
my $self = shift;
$self->get_some_framework->get_logger->log_trace("Hello, world!");
}
So, our object knows how to call methods of the framework's object that has initialized that object, moreover it can call some methods of the framework's object and even some methods of other objects initialized and stored by the framework's object.
If it's really bad, would you be so kind as to help me to understand why? Thank you!
I'm very new to Puppet, and can't seem to find the answer to this question. I have a defined Puppet resource that takes a few arguments:
class xy::xy {
include apache:regular_apache
define setup($pkg_name, $xy_version, $pas_ver) {
file { '/etc/xy':
ensure => present,
notify => Service['apache'],
}
}
I'm trying to require this custom resource for another resource in another file.
class soft::buy {
include xy::xy
$xt_requires = [Xy::Xy::Setup["{'xt_buy': pkg_name => 'xt_buy_v01',
xy_version => '1.0.1',
pas_version => '2.1.4'}"]]
package { 'buy.xt':
ensure => $::buy_xt_version,
provider => 'xt',
require => $xt_requires,
}
}
The error that I get is this: Syntax error at 'require'; expected '}'
From reading the Puppet docs, it seems like I'm missing a comma or colon somewhere, but I've tried a variety of things. I was wondering how to properly require a custom defined resource with parameters for another resource? Thanks!
The syntax error can be fixed by the following code snippet.
package { 'buy.xt':
ensure => $::buy_xt_version,
provider => 'xt',
require => $xt_requires
}
[EDIT: The original code defines $xt_requires, not $requires]
You are defining the parameter require (which defines which resource needs to be handled first).
This is different from the language statement require (which is including a class and adding a dependency on the required class).
However, in the require-paramter, you cannot specify the parameters for the requirement, just it's presence. Fully correct would be:
xy::xy::setup {'xt_buy':
pkg_name => 'xt_buy_v01',
xy_version => '1.0.1',
pas_version => '2.1.4'
}
package { 'buy.xt':
ensure => $::buy_xt_version,
provider => 'xt',
require => Xy::Xy::Setup['xt_buy']
}
I understand that using builder enables subclasses to override attribute defaults easily and roles can require them. This can also be accomplished using default like so:
has 'foo' =>
is => 'rw',
isa => 'Str',
default => sub { $_[0]->_build_foo };
I'm wondering if there are further advantages to using builder I'm not aware of? I've come up with some myself:
builder is declarative so you can introspect that foo is built by _build_foo
builder eliminates a subroutine wrapper making it a bit faster
builder allows the use of the helpful lazy_build.
UPDATE To clarify, this isn't about default vs builder in general but default => sub { $_[0]->_build_foo } vs builder => '_build_foo'.
I think you've already answered your own question. Using builder allows late-binding, which plays nicely with roles and classes that are intended to be subclassed. It's also valuable if the builder is pretty long — I never put a default more than a line long into an attribute definition. There's no real functional difference; default can easily emulate builder, but the result isn't very pretty.
Using 'builder' and 'default' appropriately can make your code easier to read and organize.
'builder' also can fit a familiar pattern of programming where private methods begin with an underscore.
has json => ( is => 'ro', default => sub { JSON->new } )
has schema => ( is => 'ro', builder => '_schema' }
sub _schema {
my $self = shift;
$self->log_debug('constructing schema') if($self->debug);
My::App::Schema->connect($self->dsn,$self->username,$self->password)
}
Additionally, using builder allows you to turn expensive functions into memoized accessors without touching the original method:
sub get_things {
my $self = shift;
return +{ map { $_ => $self->price_for($_) }
$self->wodgets->calulate_expensive_things };
Refactor with memoization:
has things => ( is => 'ro', lazy => 1, builder => 'get_things' );
Those are most of the ways I've used builder to clarify my code.
There's no difference between
default => sub { $_[0]->_build_foo }
and
builder => '_build_foo'
The primary difference between default and builder is that one one calls an anon sub and the other calls a named method.
has created_time_stamp => (
default => sub { time() },
);
versus
has created_time_stamp => (
builder => '_build_created_time_stamp',
);
sub _build_created_time_stamp { time() }
Using default reduces scrolling through the code as everything is where you need it. I use it for that reason. That is uses less typing is a bonus.
It also force you to be more explicit about overriding the builder. Other answers have considered this a con, but I consider calling virtual methods on an object that hasn't even been constructed yet to be a bad practice! That's what BUILD is for.
I want to use PayPal, Express Checkout, in a Symfony/Doctrine 1.4.8 the current plugins all seem to be in Beta and also somewhat over the top in the way they are implemented. I can follow the logic of the PayPal provided information and code although some items are a bit vague as to how i deal with them in Symfony.
Any class files are ok as i create a lib directory and rename the class and this gets instantiated. However i have some plain procedural PHP files i.e. expresscheckout.php and i am not sure where to put this to load as it doesn't seem to fit in the templates. Perhaps it goes in the actions?
I am not looking for a line by line solution here (but if you have one feel free) but really a few pointers as to where the elements go. As i say i am still suffering form a bit of Symfony blindness.
Finally would i be better to implement a simple (is that possible?) plugin to handle this or group the paypal items in a module on their own?
What I did was write a class, I called it PaypalNvp, name the file PaypalNvp.class.php and put it in your /lib folder and put in functions for the Nvp Ops.
Then you can choose to either call the functions statically (change your class functions as needed) or initialize the class and call the functions...
So something like:
PaypalNvp::doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
or
$paypal = new PaypalNvp();
$paypal->doExpressCheckoutPaypment($token, $payer_id, $amount, $currency, $payment_action);
I don't think there is a set way of of saying which way is better... I use the latter method myself.
My class has a helper function in it that does the final communication operation with Paypal:
protected function api($data = array())
{
if (empty($data) || !is_array($data)) return false;
// INIT
$data = array_merge($data, array(
'VERSION' => $this->VERSION,
'PWD' => $this->PASSWORD,
'USER' => $this->USERNAME,
'SIGNATURE' => $this->SIGNATURE
));
array_walk($data, array(&$this, 'urlencode_walk'));
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $this->getUrl() . '/nvp',
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($data)
));
$response = curl_exec($curl);
if (curl_errno($curl)) {
curl_close($curl);
return false;
} else {
curl_close($curl);
return $this->deformatNVP($response);
}
}
Main things you need to remember is to set the api method, e.g. SetExpressCheckout, and any required fields according to the PaypalNvp API
I was usually using Storable with nstore, but now I have a module that has CODE and apparently Storable doesn't like that.
I found YAML (and YAML::XS which I can't really get to work).
I also experimented a bit with MooseX::Storage without much success.
Are there other alternatives?
What would you recommend?
You can dump a coderef with Data::Dumper after setting $Data::Dumper::Deparse to a true value, but this is only intended for debugging purposes, not for serialization.
I would suggest you go back to looking at why MooseX::Storage isn't working out for you, as the authors tried really hard to present a well-abstracted and robust solution for Moose object serialization.
Update: it looks like you are running into issues serializing the _offset_sub attribute, as described in this question. Since that attribute has a builder, and its construction is fairly trivial (it just looks at the current value of another attribute), you shouldn't need to serialize it at all -- when you deserialize your object and want to use it again, the builder will be invoked the first time you call $this->offset. Consequently, you should just be able to mark it as "do not serialize":
use MooseX::Storage;
has '_offset_sub' => (
is => 'ro',
isa => 'CodeRef',
traits => [ 'DoNotSerialize' ],
lazy => 1,
builder => '_build_offset_sub',
init_arg => undef,
);
Lastly, this is somewhat orthogonal, but you can fold the offset and
_offset_sub attributes together by using the native attribute 'Code' trait:
has offset => (
is => 'bare',
isa => 'CodeRef',
traits => [ qw(Code DoNotSerialize) ],
lazy => 1,
builder => '_build_offset',
init_arg => undef,
handles => {
offset => 'execute_method',
},
);
sub _build_offset {
my ($self) = #_;
# same as previous _build_offset_sub...
}
Have a look at KiokuDB, its designed with and for Moose so it should really cover all the corners (NB. I haven't tried it myself but I keep meaning to!)
/I3az/
I believe Data::Dump::Streamer can serialize coderefs. Haven't used it myself though.