How to find a specific object on hierarchy - plone

I'm trying to get a specific object on hierarchy to set a custom index.
I usually get the object using request.PARENTS
def getHierarchyObject(obj):
cparents = obj.request.get('PARENTS')
for cparent in cparents:
if cparent.Type() == u'SpecificType':
return cparent
return false
But it doesn't work to set the index, the parents request is empty.
I created the index following this link:
http://plone.org/products/dexterity/documentation/manual/developer-manual/advanced/catalog
I'll need to climb all levels using aq_parent() to find the object?

PARENTS in the request is the sequence of objects that where traversed over to get to the published object.
You cannot rely on that value if you need to index your objects, as they are not going to be published.
Instead use their acquisition chain:
from Acquisition import aq_inner, aq_chain
def getParentObject(obj, type):
for parent in aq_chain(aq_inner(obj)):
if parent.Type() == type:
return parent

Related

change.after.val() returns full JSON object rather than value of the object

I'm working on a Firebase Cloud Function. When I log the value of change.after.val() I get a printout of a key-value pair
{ DCBPUTBPT5haNaMvMZRNEpOAWXf3: 'https://m.youtube.com/watch?v=t-7mQhSZRgM' }
rather than simply the value (the URL). Here's my code. What am I not understanding about .val() ? Shouldn't "updated" simply contain the URL?
exports.fanOutLink = functions.database.ref('/userLink').onWrite((change, context) => {
const updated = change.after.val();
console.log(updated);
return null
});
If you want only the URL value, you should include a wildcard in your trigger path for the URL key:
exports.fanOutLink = functions.database.ref('/userLink/{keyId}').onWrite((change, context) => {
console.log('keyId=', context.params.keyId);
const updated = change.after.val();
console.log(updated);
return null
});
In the Realtime Database, data is modeled as a JSON tree. The path specified in an event trigger identifies a node in the tree. The value of the node, being JSON, includes all child nodes. The change parameter for the trigger event refers to the value of the entire node.
I indicated above that you can change the trigger path to refer one level down. An alternative is to access the children of the node using the child() method of DataSnapshot.
Without knowing your use-case, it's hard to be more specific about the trigger event path you should use. Keep in mind that the event fires when any element of the node value changes, whether it be a simple value at the root level, or a value of a child node. It is often the case that you want the trigger to be as specific as possible, to better identify what changed. That's where wildcards in the path are useful. As I showed in the code I posted, the string value of a wildcard is available from the context parameter.

How to find if a filter is in the C# GlobalFilter

The ASP.Net MVC has the GlobalFilters.Filters. I want to find if RequireHttpsAttribute is in the GlobalFilters. I tried using GlobalFilters.Filters.Contains() but not knowing what type the RequiredHttpsAtrribute is. Thanks.
You can use some LINQ:
var hasAttribute = GlobalFilters.Filters
.Where(f => f.Instance is RequireHttpsAttribute)
.Any();
Filters collection has a list of System.Web.Mvc.Filter elements. I filtered global filters collection for a filter, whose property Instance is of type RequireHttpsAttribute. Then I used Any to find out if there is at least one element in the collection.
The result hasAttribute is true if global filters collection has RequireHttpsAttribute, and false if not.

react create dynamic tree recursively

thanks for reading and helping. Here is my situation so far:
I have much data in database, each piece of data has id, parentid(which means you can find the id of its parent using this parentid ), name, description.
I want to create a dynamic tree using react,but I do not know how many levels of nodes I have. Each node represents for an id in database. An user clicks on a node A on this tree, the children nodes whose parentid equals to A's id will show/hide.
I do not intend to retrieve all the data because it will take long time. Now I am able to get one node's children by sending request and get response.body:
getChildren(id){
ajax.get('http://localhost:8080/configmgmt/code/category/retriveTree/' + id)
.end((error, response) => {
if (!error && response) {
console.dir(response.body );
this.setState(subdata:response.body});
} else {
console.log('There was an error fetching from database', error);
}
}
);
}
in render part, I wrote:
{this.state.subdata.map((rb,index)=>{
return <li><div>{rb.name}</label></div></li>})
}
Here comes the question, I still do not know how to create the tree recursively(because any node might has its children nodes ). how to do this when we can only get a node's children nodes from the database?
I would do your task in two steps:
Create a structure for an augmented tree with loading status flags. It should have a structure like this (this is pseudocode):
class Node {
loaded: boolean,
expanded: boolean,
children: list<Node>
}
Create a component for this:
If node isn't expanded don't render its children
If use clicks on expand sign
If children are loaded, do nothing, just change the expanded field
If children aren't loaded
set expanded to true
initiate ajax request
as soon as the request completes, set loaded to true, and assign children
Creating a component which recursively uses itself isn't a problem. If you don't know how to do this read here: how to render child components in react.js recursively

Getting the reference from $firebaseArray to make a new reference object

Related to this question, I need to be able to get an element from a collection as a Firebase reference, ie given a $firebaseArray I need a $firebaseObject pointing to one of its elements. Unlike that example, I can't just hard-code a path the array and take a child from there because the location of the array will vary. And I can't use $firebaseArray.$getRecord() or the object provided by my ng-repeat followed by array.$save() because I may need to do a push() on this element.
So I settled on this reusable approach:
In a service:
function selectElement(array, element) {
var obj = $firebaseObject(array.$ref().child(element.$id));
return obj;
}
In the controller:
function onItemClicked(e) {
vm.selected = dataservice.selectElement(vm.observations, e);
}
In the template:
<div class="list-item" ng-repeat="o in vm.observations" ng-click="vm.onItemClicked(o)">
The first line of selectElement produces an error: array.$ref(...).child is not a function at Object.selectElement
Here array has all the properties you'd expect, but logging array.$ref() shows this obfuscated object:
Y {k: Ji, path: P, n: Ce, pc: true}
That is what it looks like from the time the array is created. What's going on here and how do I use this reference? Is there another way to get a working Firebase object out of an array?

what is #params in Iron:router

with meteor's IronRouter, I'm trying to use the this.params object elsewhere, but confused as to what it is. It seems to be a zero length array, that is actually an object with named methods after the path components.
# coffee
#route 'magnets',
path: '/magnets/lesson/:lessonCname'
data: ->
if #ready()
debugger;
console.log("route.params", #params)
with this code, in the debug console I will get:
this.params
[]
this.params.lessonCname
"despite-magnets-01"
typeof(this.params)
"object"
this.params.length
0
this.ready()
but in passing the params object to a server method, the methods (ie "lessonCname") disappear.
If my understanding is correct, then the near-term question is what is the best way to retrieve/convert these methods to {property:value} so they can be serialized and passed to server calls?
There are two easy ways of solving your problem, you can either set a global variable from within the data scope (but this is considered bad practice, at least IMO) or you can use the "data" function, which returns the data context for the current template:
data: ->
window._globalscopedata = #params.whatever #setting global variable
return someCollection.findOne #returns data context
_id: #params.whatever
when proccessing this route I will have the whatever param available in _globalscoredata and my document available in the template context.
Take a look at the source code for retrieving the parameters from a path. params is an array, but may have named properties. To iterate over everything, you can use the for in loop:
for(var x in myArray){
// Do something.
}
In this way, you can copy over everything to a new object (there may be a simpler way to create a copy).
The params property attached to a RouteController is an object with the following properties :
hash : the value of the URL hash.
query : an object consisting of key/value pairs representing the query string.
a list of URL fragments with their name and actual value.
Let's take an example, for this route definition :
// using iron:router#1.0.0-pre2 new route definition
Router.route("/posts/:slug");
And this URL typed in the browser address bar : /posts/first-post#comments?lang=en
We can use the console to find out precisely what params will actually contain :
> Router.current().params
Which will display this result :
Object {
hash: "comments",
slug: "first-post",
query: {
lang: "en"
}
}
Here slug is already a property of the params object whose value is "first-post", this is not a method.
If you want to extract from params these URL fragments as an object of key/value pairs, you can use underscore omit :
// getting rid of the hash and the query string
var parameters=_.omit(this.params,["hash","query"]);

Resources