Perl - When <%method PREPARE> gets called - perl

I am new to Perl Mason.
I came across this with the suggestion that service calls should be put inside PREPARE block. But when I placed my service calls inside it, seems like the code inside it is never getting executed itself.
<%method PREPARE>
Kindly suggest what is the above block for and its usage.

From the Mason Manual:
The base component class, Mason::Component, has but a few built-in
methods: handle, render, wrap, main, m, and cmeta.
The main method contains the mix of HTML and Perl in the main part of
the component.
You can add other methods that output HTML via the section;
these methods automatically have access to $self and $m.
<%method leftcol>
<table><tr>
<td><% $foo %></td>
...
</tr></table>
</%method>
...
<% # call leftcol method and insert HTML here %>
<% $.leftcol %>
Which means you are declaring a method named PREPARE without any argument lists by <%method PREPARE> and after writing the method body you will end it using </%method>.
And, later somewhere you will call it using <% $.PREPARE %>.For more info refer the Mason Manual.

Related

EJS include functions defined in a separate ejs file

I am trying to include an ejs file that contains functions for setting up my views. These functions were defined to be used a helpers. I have tried using:
<% include helpers.ejs %>
But when I try to use the function from this file:
<% module_start('$body', [{name:'display',value:'block'}], 'body'); %>
I get the error:
Reference Error: module_start is not defined
When I copy over the code from 'helpers.ejs' to my original view file, 'test.ejs', it works as expected. I have gone through several answers and,
am still confused what am I doing wrongly in this case.
Thanks for your help in advance.
After some grueling hours of trying every conceived solutions out there, I have landed upon a solution that is working. The solution was borrowed from:
EJS Functions
Looking at the solution presented in this code, I updated my 'helpers.ejs' to 'helpers.js'. Following this, I added the exported functions from 'helpers.js' to the ejs render context object:
const ejs_helpers = require('path/to/helpers.js');
...
ejs.renderFile('filename', { helpers:ejs_helpers, ...}, (err,data)=>{});
In the ejs view file:
<%- helpers.function_name(params); %>
This considerably changes how I initially approached the problem. With plain ejs helper file, the functions include HTML in between the control flow statements. In the case presented here, the functions returns plain string. Notice the '-' with the 'Scriptlet' tag.
Hope this helps someone.

Pass variable between views (erb) using sinatra

How can I pass a variable from one view to a partial view in Sinatra?
I already tried this:
view1.erb
<%= erb_partial :view2, locals: {test: "hello"} %>
view2.erb
<%= puts params[:test] %>
and also I tried:
view1.erb
<%= erb_partial :view2, test: "hello" %>
There are info. but for rails and for sinatra for sending one variable from controller to view, like this, but It did not help me unfortunately.
Any idea?
The local variable is passed correctly to the partial view. So, in the partial view, it will be available as a normal local variable -- test. You should not use params to access them, the data it contains are different from the local variables available in a view.
So you should use it just like how you use a normal local variable :
view2.erb
<%= test %>

Where does the value of $Form come from, when using a standard SilverStripe template?

The Page Layout template for the "simple" theme (the default) contains:
<% include SideBar %>
<div class="content-container unit size3of4 lastUnit">
<article>
<h1>$Title</h1>
<div class="content">$Content</div>
</article>
$Form
$CommentsForm
</div>
Where does the value of $Form come from? ie to make use of it, what do I need to do?
Is it intended that I define a function Form() within the page controller that returns the form?
Yeah, it's a bit of an oddity. $Form is used by the Security controller, which is invoked in login situations (/Security/login, /Security/lostpassword, etc..) and because those templates can be themed, it assumes that you have a $Form variable somewhere in your template that indicates where the form should render.
You only need it in your Page.ss template, as the Security controller just renders a generic Page.
Anything in Silverstripe that extends ViewableData basically doubles as a ViewModel. This includes DataObject and Controller. So things that are publicly accessible on these objects are exposed to the View layer and callable as template variables (be they properties or methods).
Where does the value of $Form come from? ie to make use of it, what do I need to do?
So basically yes, your assumption is correct. If you define public function Form() (which returns a Form instance) in the page controller class you want the form to show on, it will render a form on the template (for all pages of that type).
Is it intended that I define a function Form() within the page controller that returns the form?
What UncleCheese intends to say in his answer is that the variable name $Form is arbitrary. Your method could for instance be named ContactForm(), in which case you'd need to give the template $ContactForm to show the form (be sure that the second parameter to Form constructor reflects this too - http://docs.silverstripe.org/en/3.1/developer_guides/forms/introduction/ using - __FUNCTION__ is a great way to avoid this gotcha).
Form() however does not appear as a function by default in page.php, nor in ContentController, etc. The Security controller however uses Page.ss to render (when you have the CMS module installed) - thus meaning if you do not have $Form in Page.ss somewhere, you will never be able to log in. So it's important to keep this unless you also define a Security.ss to make the login/lostpassword/etc. pages different to the normal Page.ss layout (in which case that template needs $Form).

Silverstripe 3.0 customize tools panel

I want to show some customized content in the left panel which usually contains the treeview.
As the stuff in this panel will be an editable Gridfield wich should be related to the EditForm, I tried to built a new EditFormTools panel in this way:
I copied the CMSMain_Content.ss in mysite/templates/Includes and changed $Tools into $EditFormTools
I created the file CMSMain_EditFormTools.ss in the same directory with this code:
<div class="cms-content-tools west cms-panel" data-expandOnClick="true" data-layout-type="border" id="cms-content-tools-CMSMain">
<div class="cms-panel-content west">
<% include Test %>
</div>
</div>
I created a Test.php with:
class Test extends CMSMain{
public $var = 'test';
public function testfunction(){
$variable = 'hakuna matata';
return $variable;
}
}
Then I created a Test.ss with this code:
some Text
$var
$testfunction
$variable
The Panel appears in my CMS now but it only contains "some Text". So the include of Test.ss works perfectly fine but passing variables from Test.php to Test.ss doesn't.
Can anybody help?
Greetings
It may not directly answer your question but may give you direction.
You need to extend a controller class.
Then you can use a called functions to tell controller which template file it should use using renderWith().
for example,
public function index(){
return $this->renderWith("Test");
}
Then your function references in Test.ss will call functions in Test.php given it is the controller.
If Test class is not the controller rendering the template, the template doesnt know where your variable returning function is.
By the way, you can pass variables from layout to include template.

Call to Subroutine from Catalyst Controller

I am working on catalyst to design a front end for a database. I am new to perl and catalyst. I am stuck with one error in the controller.
I want to fetch gene names from one table and pass each gene name to a subroutine gene_name(call a subroutine gene_name) which will perform certain function. I some how fetched the column with gene names but they are in the form of Hash reference to other table. My call to gene_name is not working.
Any idea how to pass the values to the subroutine rather than reference?
My code is as follows:
my #gene_list = $c->model('Gene::GeneTable')->search({
},{
column =>[qw/symbol/],
}
);
foreach my $gene (#gene_list){
push #gene_aliases, &gene_name($gene);
}
The error I am getting after executing the code is as follows:
DBIx::Class::ResultSet::find(): Can't bind a reference (MyApp::Model::Gene::GeneTable=HASH(0x7ff6d88b7c58))
UPDATED
My gene_name() subroutine is in another module which I have included in the controller. Now I have changed the for loop(in controller) as following and currently it is passing gene name to gene_name() to fetch aliases(But query remains the same):
foreach my $gene (#gene_list){
push #gene_aliases, &gene_name($gene-> symbol);
}
I am accessing the #gene_aliases in my view file as follows:
[% FOREACH g in gene_aliases -%]
[% g %]
[% END -%]
The above code is fetching hash references instead of names in the page. I am not able to display the gene names on web page.If I give [% g.symbol %] in for loop then the page would be empty with no error message.Hope this would be sufficient information for answering my question. If not I would elaborate on it.
My SQL query is as follows:
Select Symbol from GeneTable;
Thanks in advance
UPDATED2
As I am not a full time programmer, I am asking these questions on the blog. Kindly help me resolve my issues. If in case I have search form which takes gene name from user and this gene name has to be passed to the gene_name() subroutine, how do I pass this (to the controller and how to call the gene_name()). Kindly help me in resolving this issue.
My form in view.tt is as follows:
<form method="post" action "[% c.uri_for('/gene')%]">
<input type="text" name="search_alias">
<input type="submit" name="alias_search" value="Search">
</form>
All my aliases are in the other table called Alias, which is been used in gene_name() subroutine.
Either the gene_name() function needs to expect a GeneTable object being passed to it, or you would call it like this: gene_name($gene->symbol).
Having said that, the Controller does not look like the right place for this, based on what limited information you've provided.
It would make a lot more sense to have gene_name as a method of Gene::GeneTable itself, ie:
package GeneTable;
...
sub gene_name {
my $self = shift;
my $gene_name = ... # do something with $self->symbol
$gene_name
}
...
So that the ->gene_name method is available to any GeneTable object in any context.
UPDATE following OP's initial two comments
It sounds like gene_name() (which possibly should be called gene_aliases()) is a method of a Gene object. Putting such a conversion into a Controller does not adhere to good MVC philosophy.
Presumably you have model code somewhere - MyApp/Model/Gene/ most likely - and this sub should exist inside Gene/GeneTable.pm. Then you could use it thus:
[%- FOREACH g IN gene_list -%]
[% g.symbol %]<br/><ul>
[%- FOREACH gn IN g.gene_name -%]
<li>[% gn %]</li>
[%- END -%]
</ul>
[%- END -%]
in your template, and anywhere else you have a GeneTable object or collection thereof.
UPDATE #2 Following updated question
DBIx:Class will return an array of objects when called in list context as you do. Perhaps you need to add some Data::Dumper->Dumper() calls to get a handle on what each step is returning to you.
I suggest you add the following line immediately after your call to ->search():
$c->log->debug("gene_list contains: ", Data::Dumper->Dumper(\#gene_list));
...and possibly the equivalent debug for #gene_aliases after you've populated that.
That might give you a clearer picture of what you're getting back from your search, but I'd hazard a guess you're getting Gene::GeneTable objects.