Why do I get different results?
class Car {
has $.wheels;
}
my $my_car = Car.new( wheels => 4 );
say $my_car ; # Car.new(wheels => 4)
say "$my_car"; # Car<94582644384824>
put $my_car ; # Car<94582644384824>
I suppose that in the 2nd and 3rd cases $my_car is stringified, but what does the result mean?
The say command calls .gist on its argument. The put command calls .Str on its argument. And this also happens when you interpolate your object.
The default gist method looks at the public attributes of an object, and creates a string from that.
You can control how your object gets stringified by supplying your own Str method.
Related
I have a method that parses YAML files. The returned object is a nested Hash, where the keys are always Strings and the leaf-values are always strings, e.g.
{
"a" => "foo",
"b" => {
"c" => "bar",
"d" => "baz"
}
}
I don't know in advance how deep the hash is.
The closest I got to typing the return value was the following signature:
T.any(T::Hash[String,String], T::Hash[String,T::Hash[String, T.untyped]])
This is obviously a bad solution, since it doesn't check anything beneath the second nesting, but the documentation about custom types seems a bit sparse.
Is there any way to type nested hashes, using a custom type, nested types or something similar?
Unfortunately, you won't be able to do much more than what you got to at this point. Even though Shapes are supported, they are an experimental feature.
If you really want to go with hashes, you could express it as:
MyType = T.type_alias {T::Hash[String, T.any(String, T::Hash[String, T.untyped])]}
Alternatively, you could use a T::Struct:
class MyType < T::Struct
const :key, String
const :value, T.any(String, MyType)
end
You'd still have the uncertainty of what the type of the value is, but with flow sensitivity, it should be easy to process the structure:
class Processor
extend T::Sig
sig {params(my_object: MyType).returns(String)}
def process(my_object)
key = my_object.key
obj_value = my_object.value # this is needed for flow sensitivity below
value = case obj_value
when String
value
when MyType
process(obj_value)
else
T.absurd(obj_value) # this makes sure that if you add a new type to `value`, Sorbet will make you handle it
end
return "key: #{key}, value: #{value}"
end
end
This question already has an answer here:
Calling feature file with multiple arguments
(1 answer)
Closed 1 year ago.
I am passing argument to karate.call as following:
...getting object by name
* def id = response.content[0].id
And eval if (size(response.content) == 1) { karate.call('delete/delete-object.feature', id); }
However, I am getting: unexpected feature call arg type: class java.lang.String. Should I somehow cast the argument at first?
I am just creating the scenario which should at first delete the object if existing. Deletion I am doing in delete-object.feature.
Please read the docs, the (single) call argument always has to be a JSON or array of JSONs (unless it is a call to a JS function): https://github.com/intuit/karate#calling-other-feature-files
It is easy to shape, e.g. : * def arg == { id: '#(id)' }
Just for the sake of reference, I'm posting a solution here.
* def id = response.content[0].id
And eval if (size(response.content) == 1) { karate.call('delete/delete-object.feature') { id : '#(id)' } ; }
Inside delete-object.feature file, just use id to access that value. Keep in mind that there's a strange behavior in karate. If you pass in an object such as " { car: '#(carobject)'} ", you cannot access that object by calling "car" inside the feature file you pass this object in. You need to use the object name itself, not the attribute name. So, in this case, it would be "carobject". Hope that helps
I am new to Perl 6. I have the following code in my Atom Editor, but I still don't understand how this works. I copied the following code, as the docs.raku.org said, but it seems that it does not work. So I changed the code to this:
use v6;
class HTTPHeader { ... }
class HTTPHeader does Associative {
has %!fields handles <self.AT-KEY self.EXISTS-KEY self.DELETE-KEY self.push
list kv keys values>;
method Str { say self.hash.fmt; }
multi method EXISTS-KEY ($key) { %!fields{normalize-key $key}:exists }
multi method DELETE-KEY ($key) { %!fields{normalize-key $key}:delete }
multi method push (*#_) { %!fields.push: #_ }
sub normalize-key ($key) { $key.subst(/\w+/, *.tc, :g) }
method AT-KEY (::?CLASS:D: $key) is rw {
my $element := %!fields{normalize-key $key};
Proxy.new(
FETCH => method () { $element },
STORE => method ($value) {
$element = do given $value».split(/',' \s+/).flat {
when 1 { .[0] } # a single value is stored as a string
default { .Array } # multiple values are stored as an array
}
}
);
}
}
my $header = HTTPHeader.new;
say $header.WHAT; #-> (HTTPHeader)
"".say;
$header<Accept> = "text/plain";
$header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>;
$header.push('Accept-Language' => "fr"); # like .push on a Hash
say $header.hash.fmt;
"".say;
say $header<Accept-Language>.values;
say $header<Accept-Charset>;
the output is:
(HTTPHeader)
Accept text/plain
Accept-Charset utf-8
Accept-Encoding gzip
Accept-Language en fr
(en fr)
utf-8
I konw it works, but the document in docs.raku.org is a little different to this, which doesn't have "self" before the AT-KEY method in the 7th line. Is there any examples that more detail about this?
Is there any examples that more detail about this?
Stack overflow is not really the place to request more detail on a published example. This is the perl6 doco on the community itself - I would suggest that the most appropriate place if you have further queries is the Perl6 users mailing list or, failing that, the IRC channel, perhaps.
Now that you've posted it though, I'm hesitant to let the question go unaddressed so, here are a couple of things to consider;
Firstly - the example you raised is about implementing associative subscripting on a custom (ie user defined) class - it's not typical territory for a self-described newbie. I think you would be better off looking at and implementing the examples at Perl6 intro by Naoum Hankache whose site has been very well received.
Option 1 - Easy implementation via delegation
Secondly, it's critical to understand that the example is showing three options for implementing associative subscripting; the first and simplest uses delegation to a private hash attribute. Perl6 implements associative and positional subscripts (for built-in types) by calling well-defined methods on the object implementing the collection type. By adding the handles trait on the end of the definition of the %!fields attribute, you're simply passing on these method calls to %!fields which - being a hash - will know how to handle them.
Option 2 - Flexible keys
To quote the example:
However, HTTP header field names are supposed to be case-insensitive (and preferred in camel-case). We can accommodate this by taking the *-KEY and push methods out of the handles list, and implementing them separately...
Delegating all key-handling methods to the internal hash means you get hash-like interpretation of your keys - meaning they will be case-sensitive as hash keys are case-sensitive. To avoid that, you take all key-related methods out of the handles clause and implement them yourself. In the example, keys are ran through the "normalizer" before being used as indexes into %!fields making them case-insensitive.
Option 3 - Flexible values
The final part of the example shows how you can control the interpretation of values as they go into the hash-like container. Up to this point, values supplied by assigning to an instance of this custom container had to either be a string or an array of strings. The extra control is achieved by removing the AT_KEY method defined in option 2 and replacing it with a method that supplies a Proxy Object. The proxy object's STORE method will be called if you're assigning to the container and that method scans the supplied string value(s) for ", " (note: the space is compolsory) and if found, will accept the string value as a specification of several string values. At least, that's what I think it does.
So, the example has a lot more packed into it than it looks. You ran into trouble - as Brad pointed out in the comments - because you sort-of mashed option 1 togeather with option 3 when you coppied the example.
I'm new to Moq, so any help would be great. I keep getting a null reference error in my code when I'm trying to set up a test. Here is the line of code where I'm getting the error below.
_iMailController.RequesterEmail(model).Deliver();
Here is what my test looks like:
_mockMailController = new Mock<IMailController>();
mockMailController .Setup(x => x.RequesterEmail(new Model())).Returns(**new EmailResult()**);
The bold part is where I'm stuck at. It takes 7 parameters and dont know what to put to fake out the EmailResult.
You are confusing, The Return part will single return values like string, list, bool or Int ect.
So you can easily pass the value which you get in return on the RequesterEmail on the IMailController. So you have to check the which value get retun from the RequesterEmail method.
You may also use the below code as example:
mockMailController .Setup(x => x.RequesterEmail(It.IsAny<Model>())).Returns(**new EmailResult()**);
Refet the below Part too.
It mentioned about how many parameter you passed in the RequesterEmail method. If there is 7 parameters passed on the method then you may have to pass 7 parmeter like bleow
Please look deeply in parameter and return on both codes down here.
And look where i use ModelClass in both below codes.
If the Method have parameters like below:
public void RequesterEmail( string, int, list, EmailClass, someClass, bool, string);
{
return ModelClass;
}
then you may have to write the code as below
mockMailController .Setup(x => x.RequesterEmail(It.IsAny<string>(), It.IsAny<int>(),
It.IsAny<EmailClass>(), It.IsAny<someClass>(), It.IsAny<bool>(),
It.IsAny<string>())).Return(ModelClass)
I am looking to pass a value to a custom validation. I have done the following as a test:
validate :print_out, :parameter1 => 'Hello'
With this:
def print_out (input="blank")
puts input
end
When creating an object or saving an object, the output is 'blank.' However, if called directly:
object.print_out "Test"
Test is instead outputted. The question is, why is my parameter not passing properly?
Inside the 'config\initializers\' directory, you can create your own validations. As an example, let's create a validation 'validates_obj_length.' Not a very useful validation, but an acceptable example:
Create the file 'obj_length_validator.rb' within the 'config\intializers\' directory.
ActiveRecord::Base.class_eval do
def self.validates_obj_length(*attr_names)
options = attr_names.extract_options!
validates_each(attr_names, options) do |record, attribute, value|
record.errors[attribute] << "Error: Length must be " + options[:length].to_s unless value.length == options[:length]
end
end
end
Once you have this, you can use the very clean:
validates_obj_length :content, :length => 5
Basically, we reopen ActiveRecord::Base class and implement a new sub-validation. We use the splat (*) operator to accept an array of arguments. We then extract out the hash of options into our 'options' variable. Finally we implement our validation(s). This allows the validation to be used with any model anytime and stay DRY!
You could try
validate do |object_name|
object_name.print_out "Hello"
end
Instead of your validate :print_out, :parameter1 => 'Hello'.