I'm creating some models using MonogID and one of them is a boolean value that can accept nil values. Here is how I defined the model.
class Status
include Mongoid::Document
field :pending, type: Boolean
validates :pending, inclusion: { in: [true, false], allow_nil: true }
#...
end
As you can see I set the accepted values as booleans and nil. The problem is that when I assign a string, it is transformed to false and accepted. In this way the validation does not work. The second test in this case just fails.
it { [true, false, nil].each { |value| should allow_value(value).for(:pending) } }
it { ['not_valid', ''].each { |value| should_not allow_value(value).for(:pending) } }
Now, the only solution I'm coming out with is to make a custom validator that check out for the value being a TrueClass, FalseClass or NilClass, but it seems I'm loosing an easier solution. I've checked around the web, but I didn't find out a solution.
Thanks.
You didn't able to find the solution because when you assign a value to Boolean field it interprets that value as true, false or nil and when you try to save it will have value one out of this (true, false, nil) which will pass the validation.
Related
The decisioning is to permit if the user has required roles. The required roles and the user's current permissions are in JSON format.
Required permissions: (Saved as a attribute)
{
"data": {
"service1": {
"service1.1": true
},
"service2": {
"service2.1: false,
"service2.2": true,
"service2.3": false
}
}
}
User's current permissions:
{
"data": {
"service1": {
"service1.1": true
},
"service2": {
"service2.1: false,
"service2.2": false,
"service2.3": true
}
}
}
To make the decision, we need to check if the user has the services as true similar to required Permissions. In the above example, the user has data.service1.service1.1 as true and data.service2.service2.3 as true where the required roles being data.service1.service1.1 as true and data.service2.service2.2 as true, in this case we deny.
I wrote separate rules to check for each and every service, but that would only be a check of combination of services.
rule service1.1{
permit
condition
(allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))
&&
(allOf(function[booleanEqual], true, requiredRoles.data.service1.service1.1))
on permit {
advice reasonForPermit{
reasonAttribute= "Contains Valid services"
}
}
}
Would someone please help on how to write a if.. then check in alfa?
There is no if..then construct in ALFA (or XACML). You use combining algorithms instead. In particular, onPermitApplySecond is the policy combining algorithm that resembles an if..then construct the most.
However, there is usually a simpler way to express what you want if you can make reasonably assumptions on your attribute data. In your example, for instance, if it's always guaranteed that both the required and current permissions contain exactly one boolean value for each available service, then you could write:
rule {
target
clause requiredRoles_service1_1 == false or permitted_service1_1 == true
clause requiredRoles_service2_1 == false or permitted_service2_1 == true
...
permit
}
Remember that in a target, clauses are AND'ed together. This rule then checks that, for every service, the role is either not required or is given in the current permissions.
If instead it may happen than any of those attributes is not present (i.e. there are no values for the attribute), then you have to guard against that case. You can do that using a condition like the following one, but there are other ways too:
rule {
permit
condition
(not(booleanIsIn(true, requiredRoles_service1_1)) || booleanIsIn(true, permitted_service1_1))
&&
(not(booleanIsIn(true, requiredRoles_service2_1)) || booleanIsIn(true, permitted_service2_1))
&&
...
}
All in all, there are usually simpler ways to express a policy if you can massage attribute data into other forms. Having a pair of attributes per service, like in the examples above, may not be necessary.
If you could gather all required roles and current permissions in one attribute each, then the policy can be expressed much more compactly. Let's say you have two attributes, requiredRoles and permittedRoles whose values list the service roles required and permitted for a given user, respectively. In your example, this would mean that requiredRoles has value, say, ["service1.1", "service2.2"] and permittedRoles has value ["service1.1", "service2.3"]. Then you can write a rule like this:
rule {
permit
condition stringSubSet(requiredRoles, permittedRoles)
}
I was able to do this by creating separate attributes for each service and wrote a rule with the target clause with the service from required roles and the condition will be if the service in the permitted role is true. I combined all the rules as below in the policy using permitunlessDeny algorithm
rule rule1 {
target clause requiredRoles.service1_1 == true
deny
condition
not(permittedRoles.service1_1 == true)
on permit {
advice reasonForPermit {
reasonAttribute= "User has valid services"
}
}
}
Thank you for the suggestion Pablo.
When I write this:
property bool token: false
Settings {
property alias token: root.token
}
and then change token somewhere in application to true, next time when I run the application token is true.
But when I write this:
property var token: null
Settings {
property alias token: root.token
}
and change token to {'a': 'b'} for example, next time I run the application token is null like Settings doesn't save JS Object. Any idea what's wrong here?
Update:
It seems that problem is not with saving the js object {'a': 'b'}, QML saves it successfully, the problem is with null if I change it to false everything works alright. I guess it's related to this question Storing data using Settings element in QML but I don't understand why null is being post processed, though using false instead of null as default value for this property solves the problem I don't like it as I don't want false here, it's not appropriate morally, I want null.
Update 2:
I found my solution, setting no default value for property (not false nor null) seems to solve the issue and it seems appropriate morally like this:
property var token
Settings {
property alias token: root.token
}
I don't understand why null doesn't work yet. Any explanation would be welcome.
Setting no default value for property (not false nor null) seems to solve the issue:
property var token
Settings {
property alias token: root.token
}
According to RavenDB document, when BeforeStore() returns false, the entity instance should not updated.
Whatever the entity instance was modified and requires us re-serialize it.
Returning true would force re-serialization of the entity, returning false would
mean that any changes to the entityInstance would be ignored in the current SaveChanges call.
I have tested return both true and false, no difference. Return false won't stop saving the entity to database.
Here is my listener:
public bool BeforeStore(string key, object entityInstance, RavenJObject metadata, RavenJObject original)
{
if (entityInstance is Person)
{
var person = (Person)entityInstance;
person.Firstname = "Tom"; // used be John
return false;
}
}
It turns out the person's first name is changed to "Tom" even it returns false.
Do I miss anything?
Please re-read the documentation. The return value just says whether you have changed the document in your IDocumentStoreListener.
I need a validation to check whether an attribute is less or equal than another (virtual) attribute of the same record. How can I do that?
Sample code (not working - NoMethodError):
attr_reader :virt
attr_accessible :virt
validates :my_attr, :numericality => {:only_integer => true, :less_or_equal => self.virt}
(please be gentle and explicit, I'm a RoR newb :])
Since those validation lines are going to be executed when the class definition is first encountered, self.virt doesn't exist.
You can usually pass in a lambda/proc instead that will be called at validation time from the scope of the object:
validates :my_attr, :numericality => { :less_or_equal => lambda { virt } }
This still isn't that great, though. A better route would be to just define your own validation method:
validate :my_attr_is_within_range
def my_attr_is_within_range
my_attr <= virtual_attribute
end
This is much cleaner and more explicit. Note that you don't need to use self here since there is no ambiguity (if you were setting you would need the self).
(ExtJS 4.0.7)
I'm using Model.save() to PUT an update to a server. Everything works fine and the server returns a simple JSON response {success: true} (HTTP status 200). Model.save() throws the following error, however:
Uncaught TypeError: Cannot read property 'data' of undefined
Here's where this is happening in the ExtJS code (src/data/Model.js):
save: function(options) {
...
callback = function(operation) {
if (operation.wasSuccessful()) {
record = operation.getRecords()[0]; <-- getRecords() return an empty array
me.set(record.data); <-- record is undefined, so .data causes error
...
}
I've figured out this is happening because Model.save() expects the server to respond with JSON for the entire object that was just updated (or created).
Does anyone know of a clever way to make Model.save() work when the server responds with a simple success message?
I was able to come up with a work-around by using a custom proxy for the model, and overriding the update function:
Ext.define('kpc.util.CustomRestProxy', {
extend: 'Ext.data.proxy.Rest',
alias: 'proxy.kpc.util.CustomRestProxy',
type: 'rest',
reader : {
root: 'data',
type: 'json',
messageProperty: 'message'
},
// Model.save() will call this function, passing in its own callback
update: function(operation, callback, scope) {
// Wrap the callback from Model.save() with our own logic
var mycallback = function(oper) {
// Delete the resultSet from the operation before letting
// Model.save's callback use it; this will
oper.resultSet = undefined;
callback(op);
};
return this.doRequest(operation, mycallback, scope);
}
});
In a nutshell, when my proxy is asked to do an update it makes sure operation.resultSet == undefined. This changes the return value for operation.getRecords() (which you can see in the code sample from my question). Here's what that function looks like (src/data/Operation.js):
getRecords: function() {
var resultSet = this.getResultSet();
return (resultSet === undefined ? this.records : resultSet.records);
}
By ensuring that resultSet == undefined, operation.getRecords returns the model's current data instead of the empty result set (since the server isn't returning a result, only a simple success message). So when the callback defined in save() runs, the model sets its data to its current data.
I investigate this problem and found truly simple answer. Your result must be like this:
{
success: true,
items: { id: '', otherOpt: '' }
}
And items property MUST be equal Model->Reader->root property (children in tree for example).
If you want to use items instead children you can use defaultRootProperty property in Store and configure your nested collections as you want.
PS
Object in items property must be fully defined because it replaces actual record in store.