How to get rid of the __actions__ entry in the CrudRestController's response? - rest

I'm subclassing the CrudRestController to implement an REST interface. It works fine, but the response dict contains an __actions__ entry which contains some html code that I really don't want in my response.
According to the TableFiller class' docstring something like this should work:
class ProcessController(CrudRestController):
model = Process
#...
class table_filler_type(TableFiller):
__model__ = Process
__actions__ = False
But the page always throws an AttributeError: 'Process' object has no attribute '__actions__'
Any advice?

Despite the inline docs, the correct way seems to be:
class table_filler_type(TableFiller):
__model__ = Process
__omit_fields__ = ['__actions__', ]

Related

Eloquent - load accessor along with model data

My model was eager loading a lot of things with accessors. I want to change it to specify accessors in each case. How do I include such accessors with the query, so that I get the basic model data plus the accessor data
Accessors would previously be eager loaded with:
protected $appends = [
'status',
]
But if I get rid of eager loading, and I want to include this acccessor:
public function getStatusAttribute() {
return self::STATUS_ACTIVE;
}
Then I can do this according to the documentation:
$prod = \App\Product::find(736)->status;
That works but I don't get the basic model data.
I can't do: return $prod = \App\Product::find(736)->with('status')->first()
It gives error: Call to undefined relationship [status] on model
So how do I add such accessors to be included with the model data?
Edit:
As Staudenmeir commented, i can do \App\Product::find(736)->append('status');
That solves it for single results. But how do I append data for many results?
Neither append or appends work:
This: \App\Product::whereIn([34, 55])->appends('status');
results in "Method appends does not exist.",
I saw that you can use "appends" on "->paginate()"
$products = \App\Product::whereIn([34, 55])
->paginate(12)
->appends('status');
But that appends it as a query string to the url. Very strange - I want to append it in the same way as for a single result in the json response.
You have not fetched the collection first, and then access the attribute of result.
$prod = \App\Product::find(736);
$status = $prod->status;

PowerShell Class; property "System.Collections.Specialized.OrderedDictionary"; how to add dictionary entry

(As I have searched the web quite intensively for an answer and didn't get any hint in the right direction, I allow myself to ask you the following question:)
I have a PowerShell class like this:
class settings
{
[string]$CFG_Name
[string]$CFG_Template_Path
[string]$CFG_Target_Path
[System.Collections.Specialized.OrderedDictionary]$ConfigSettings
}
I then instantiate this class and want to use it like this:
$CurrentSettings = New-Object settings <-- works fine
$CurrentSettings.CFG_Name = 'MPD' <-- works fine
$CurrentSettings.CFG_Template_Path = $CFG_Template_MPD_Path <-- works fine
$CurrentSettings.CFG_Target_Path = $CFG_MPD_Path <-- works fine
$CurrentSettings.ConfigSettings.Add("TID",$EFT_TID) <-- doesn't work
The line above throws: You cannot call a method on a null-valued expression.
According to this page: Documentation from Microsoft the add method is supported.
Why can't I just use this property like I can use for example $CFG_Name?
How would I add dictionary entries to this property?
The solution is the following:
Before the adding of the first dictionary entry, you have to initialize the property like this:
$CurrentSettings.ConfigSettings = New-Object System.Collections.Specialized.OrderedDictionary
Then you can add the entry:
$CurrentSettings.ConfigSettings.Add("TID",$EFT_TID)

How to debug in TYPO3 if <f:debug> returns strings instead of object?

In a custom TYPO3 8.7.12 extbase extension I am unable to f:debug items in templates.
We are in the listAction controller and simply do:
$institutions = $this->institutionRepository->findAll();
$this->view->assignMultiple([
'institutions' => $institutions,
// ... pagination limit ...
]
);
And in the template:
<f:debug>
{institutions}
</f:debug>
This returns
sometimes the string 'Array' in the fluid debugger (can't reproduce now)
When the code is on 3 lines: #1273753083: Cannot cast object of type "TYPO3\CMS\Extbase\Persistence\Generic\QueryResult" to string.
Or also #1273753083: Cannot cast object of type "TYPO3\CMS\Extbase\Persistence\Generic\LazyObjectStorage" to string.
When the code is on 1 line: #1234386924: Cannot create empty instance of the class "TYPO3\CMS\Extbase\Persistence\ObjectStorage" because it does not implement the TYPO3\CMS\Extbase\DomainObject\DomainObjectInterface.
If I loop through {institutions} with f:for and then f:debug:
<f:for each="{institutions}" as="institution" iteration="i">
<f:debug>
{institution}
</f:debug>
</f:for>
I get the first property of the object, e.g. the name.
EDIT: this is due to a __toString() magic method in the model. If I remove it, instead I get the namespace and uid STUBR\Extension\Domain\Model\Institution:55 – this looks again as if the object isn't rendered.
Wait... php.net says The __toString() method allows a class to decide how it will react when it is treated like a string. So could something be treating (typecasting?) the object as a string?
Working with the properties is normal, the issue just occurs when trying to print the whole object.
Where should I look? Lazy loading? There are some lazy loading properties, but not that many. Or maybe something is missing from the class? Or is there a workaround.
PS:
Unable to print_r or var_dump the query result, I get a memory limit error.
I saw https://wiki.typo3.org/Exception/CMS/1234386924 but initStorageObjects() is already called in the constructor
To answer the question;
<f:debug>{institutions}</f:debug>
will be parsed as an object, but any whitespace inside will make it parse as a string so.
The following methods do the same job as <f:debug> and work similarly in my case:
\TYPO3\CMS\Core\Utility\DebugUtility::debug(
$var = $variable,
$header = 'Institutions',
$group = ''
);
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump(
$variable,
$title = 'Institutions',
$maxDepth = 8,
$plainText = FALSE,
$ansiColors = TRUE,
$return = FALSE,
$blacklistedClassNames = NULL,
$blacklistedPropertyNames = NULL
);
execute in list or show action in controller.
It's less convenient than with f:debug (because you have to do the work in two different places, e.g. when you're in a loop in the template, you have to go to the controller and build that loop again), but it's a helpful workaround.
EDIT: I found it's sufficient to do
<f:debug>{var}</f:debug>
on one line

Cannot access the parameter of a Menu.param from a Lift Snippet

I'm trying to extract the parameter from a Lift Menu.param within a snippet so that I can use it to create a named Comet. However, I get a NullPointerException when I try to pass the parameter to the snippet using SnippetDisptach in my Boot.scala, as suggested here:
http://comments.gmane.org/gmane.comp.web.lift/44299
I've created the Menu item as follows:
object AnItemPage {
// create a parameterized page
def menu = Menu.param[Item]("Item", "Item",
s => fetchItem(s), item => item._id.toString) / "item"
private def fetchItem(s:String) : Box[Item] = synchronized {
ItemDAO.findById(ObjectId.massageToObjectId(s))
}
}
I've added the menu to SiteMap. I've also created a Snippet which I would like to pick up the Item parameter. (I'm using fmpwizard's InsertNamedComet library here):
class AddCometItemPage(boxedItem: Box[Item]) extends InsertNamedComet with DispatchSnippet{
val item : Item = boxedItem.openOr(null)
override lazy val name= "comet_item_" + item._id.toString
override lazy val cometClass= "UserItemCometActor"
def dispatch = null
}
My next step is to crate an instance of this class as demonstrated by David Pollak here:
http://comments.gmane.org/gmane.comp.web.lift/44299
This is what I have added to my Boot.scala:
LiftRules.snippetDispatch.append {
case "item_page" => new AddCometItemPage(AnItemPage.menu.currentValue)
}
My item.html references this snippet:
<div class="lift:item_page">
I get the following null pointer exception when I compile and run this:
Exception occurred while processing /item/5114eb4044ae953cf863b786
Message: java.lang.NullPointerException
net.liftweb.sitemap.Loc$class.siteMap(Loc.scala:147)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.siteMap(Menu.scala:170)
net.liftweb.sitemap.Loc$class.allParams(Loc.scala:123)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.allParams(Menu.scala:170)
net.liftweb.sitemap.Loc$class.net$liftweb$sitemap$Loc$$staticValue(Loc.scala:87)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.net$liftweb$sitemap$Loc$$staticValue(Menu.scala:170)
net.liftweb.sitemap.Loc$$anonfun$paramValue$2.apply(Loc.scala:85)
net.liftweb.sitemap.Loc$$anonfun$paramValue$2.apply(Loc.scala:85)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.sitemap.Loc$class.paramValue(Loc.scala:85)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.paramValue(Menu.scala:170)
net.liftweb.sitemap.Loc$$anonfun$currentValue$3.apply(Loc.scala:114)
net.liftweb.sitemap.Loc$$anonfun$currentValue$3.apply(Loc.scala:114)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.sitemap.Loc$class.currentValue(Loc.scala:114)
net.liftweb.sitemap.Menu$ParamMenuable$$anon$9.currentValue(Menu.scala:170)
bootstrap.liftweb.Boot$$anonfun$lift$8.apply(Boot.scala:107)
bootstrap.liftweb.Boot$$anonfun$lift$8.apply(Boot.scala:106)
net.liftweb.util.NamedPF$$anonfun$applyBox$1.apply(NamedPartialFunction.scala:97)
net.liftweb.util.NamedPF$$anonfun$applyBox$1.apply(NamedPartialFunction.scala:97)
net.liftweb.common.Full.map(Box.scala:553)
net.liftweb.util.NamedPF$.applyBox(NamedPartialFunction.scala:97)
net.liftweb.http.LiftRules.snippet(LiftRules.scala:711)
net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:1506)
net.liftweb.http.LiftSession$$anonfun$net$liftweb$http$LiftSession$$findSnippetInstance$1.apply(LiftSession.scala:1506)
net.liftweb.common.EmptyBox.or(Box.scala:646)
net.liftweb.http.LiftSession.net$liftweb$http$LiftSession$$findSnippetInstance(LiftSession.scala:1505)
net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$88.apply(LiftSession.scala:1670)
net.liftweb.http.LiftSession$$anonfun$locateAndCacheSnippet$1$1$$anonfun$apply$88.apply(LiftSession.scala:1669)
Has anybody any idea where I'm going wrong? I've not been able to find a lot of information on Menu.param.
Thank you very much for your help.
f
I have never tried what you are doing, so I am not sure the best way to accomplish it. The way you are using the Loc Param, you are extracting a variable from a URL pattern. In your case, http://server/item/ITEMID where ITEMID is the string representation of an Item, and which is the value that gets passed to the fetchItem function. The function call will not have a value if you just arbitrarily call it, and from what I can see you are requesting a value that is not initialized.
I would think there are two possible solutions. The first would be to use S.location instead of AnItemPage.menu.currentValue. It will return a Box[Loc[Any]] representing the Loc that is currently being accessed (with the parameters set). You can use that Loc to retrive currentValue and set your parameter.
The other option would be to instantiate the actor in your snippet. Something like this:
item.html
<div data-lift="AnItemPage">
<div id="mycomet"></div>
</div>
And then in your AnItemPage snippet, something like this:
class AnItemPage(item: Item) {
def render = "#mycomet" #> new AddCometItemPage(item).render
}
I haven't tested either of those, so they'll probably need some tweaking. Hopefully it will give you a general idea.

scala spring web mvc

I have a scala controller:
#Controller
#RequestMapping(Array("/welcome"))
class HelloController{
#RequestMapping{val method = Array(RequestMethod.GET)}
def printWelcome(model: ModelMap) = {
println("IN: printWelcome(..)")
val greeting = new GreetingBean("Yo!", "Adam")
model.addAttribute("message", greeting);
"secure" // sends to the /jsf/secure.xhtml page
}
#RequestMapping{val value = Array("/greeting"), val method = Array(RequestMethod.GET)}
def greeting(model: ModelMap) = {
println("IN: greeting(..)")
val greeting = new GreetingBean("Greetings", "Davies")
model.addAttribute("greeting", greeting);
"greeting"; // sends to the /jsf/greeting.xhtml page
}
}
When i call http://localhost:8080/jsf-spring-guice/welcome the message IN: printWelcome(..) is displayed in the console and the correct page is navigated to.
when I call http://localhost:8080/jsf-spring-guice/welcome/greeting I get a 404 error.
I have tried specifying the #RequestMapping on the greetings method in different ways:
#RequestMapping{val value = Array("greeting"), val method = Array(RequestMethod.GET)}
#RequestMapping{val value = Array("/greeting")}
#RequestMapping(Array("/greeting"))
#RequestMapping(Array("/greeting"), Array(RequestMethod.GET))
and de-compiled the generated class which always looks fine. But I always get OK with welcome and always 202 with /welcome/greeting
The decompiled Scala class has this:
#RequestMapping({"/welcome"})
and this:
#RequestMapping(value={"/greeting"}, method={org.springframework.web.bind.annotation.RequestMethod.GET})
I can't see any reason why this should not be working. Can anyone help?
Haven't check it and compile, but #RequestMapping annotation for printWelcome method should also have specified value, even if it is empty ("").
The specified value acts as a filter and that's likely the cause of the problem.
Solved
...But couldn't find the answer on Spring documentation.
Situation was I had in web.xml
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/welcome/*</url-pattern>
</servlet-mapping>
This meant that the mapping '#RequestMapping(Array("/welcome"))' had no effect and any request to http://localhost:8080/jsf-spring-guice/welcome would be processed by method marked with #RequestMapping{val method = Array(RequestMethod.GET)}. A kind of default get.
The clue was that when I entered http://localhost:8080/jsf-spring-guice/welcome/welcome/greeting/ the method marked with #RequestMapping{val value = Array("/greeting"), val method = Array(RequestMethod.GET)} was called. At this point it was clear that the double welcome meant something was amiss.
So basically, the url-pattern acts as a pre-fix to URL patters (we all know that), but the catch is that the controller with a simple GET method will act as a default.
Note to self do not use controller with same request mapping as url-pattern