How to insert link to controller action in Play framework 2.0 template - templates

If I have an action Application.show(tag: String), and also have a corresponding routing entry, how can I insert a link to this action to a template without crafting the url manually?
I would like to do something like magiclink(Application.show("tag")).

syntax:
<a href='#routes.Application.show("some")'>My link with some string</a>
By analogy you can also generate urls in your controllers. ie. for redirecting after some action:
public static Result justRedirect(){
// use as String
String urlOfShow = routes.Application.index().toString().
// or pass as a redirect() arg
return redirect(routes.Application.show("some"));
}

The format for putting a URL from your routes file in your html is as follow:
#routes.NameOfYourClass.nameOfyourMethod()
So, if in your routes file you have:
GET /products controllers.Products.index()
And your Products class looks like this:
public class Products extends Controller {
public Result index() {
return ok(views.html.index.render());
}
}
Your <a> should look like this:
Products
In addition: If your method can accept parameters, then you can of course pass them in between the parenthesize of your method like this: index("Hi").
I hope this answer is more clear to understand.

The accepted answer is right, but it doesn't cover the case where the controller is in a sub-package, i.e.: controllers.applications.MyFavouriteApplication.show()
Since I had a hard time finding the answer, I'll post it here.
To put a non-scoped link into a template, the proper pattern is #controllers.{sub-packages if any}.routes.{your class}.{your method}()
So in this case it would be #controllers.applications.routes.MyFavouriteApplication.show()
IF you were using the recommended Play pattern of using #Inject to create singleton controller objects, and IF you thought the correct answer was #controllers.applications.MyFavouriteApplication.show(), you would get an error like this:
Object MyFavouriteApplication is not a member of controllers.applications. Note: class MyFavouriteApplication exists, but it has no companion object.
Given that you had already supplied the #Inject() #Singleton annotation, this would seem like a very strange error indeed. It might make you question if you were building the project correctly. Determining the true cause could cost you considerably in blood and treasure.

Ah, as simple as #{routes.Application.show("tag")}.

Related

Find the class name of a relation from the instance of a model in ember JS

I have foo an instance of the ember-data model thing. thing.js has the following property :
owner: DS.belongsTo('user')
If I have foo with an empty owner, how can I, with only foo and the 'owner' string, retrieve the value 'user' representing the model of the owner relation?
EDIT: I want to allow my select-relation component to works with relations where the name is different from the class name
It sounds like you have some work to do to finish setting up your relationships. Have a read through this page of the guides.
If the relationships are set up correctly, to get the associated user, you should be able to do foo.owner. This assumes that users are already present in the store. I recommend using the Ember Inspector browser plugin to debug the relationships.
This looks like a use case for typeForRelationship.
In your example you should be able to do something like
store.modelFor('thing').typeForRelationship('owner', store);
If you don't like that approach you can use the belongsTo reference API, where you use the meta data from the relationship to get the type
foo.belongsTo('owner').type
The only thing with that approach is that the type property may not be public API and possible (though unlikely) to change at some point.
It seems I can do the following :
this.get('model').get('_internalModel._relationships.initializedRelationships.'+this.get('relation')+'.relationshipMeta.type')
model being an instance and relation the string of the relation name, it correctly return the model of the relation.
EDIT : a better solution not using private API courtesy from the ember discord :
function getRelatedModelName(record, relationName){
let ParentModelClass = record.constructor;
let meta = get(ParentModelClass, 'relationshipsByName').get(relationName);
return meta.type;
}

How do I return a formatted string in the controller using Ember?

I thought this would be super simple but its turning into a pain in the butt.
I need to create a function that will accept a string and return it re-formatted as a URL slug. For example I'd pass in the string "The Adventures of Huckleberry Finn" and my function would return the string "the_adventures_of_huckleberry_finn". I have no problem doing the actual conversion. However in Ember actions can only return True, False or Undefined so the action always returns an object named Undefined rather than the string I told it to return.
How can I go about creating this function/action/computed property in my controller so that it correctly returns the formatted string? I have attempted to just add a normal JS function into the controller. I also tried to define this as a computed property but this action will be used only in the controller, the template has no need to know anything about the slug so a computed property dosn't really make sense and I couldn't get it to work anyways.
Ok, here is an example in how to achieve that: jsfiddle.net/NQKvy/837
I would return a computed property call something like slug
slug: function(){
return this.get('title').split(' ').join('_');
}.property('title')
Then you can use {{slug}} in your template of this.get('slug') in your controller.
Cheers

Can I use "Where" block and helper methods at the same time in spock

I have a specification which essentially looks like this:
def "my example specification"(){
given:"some mocked object which depends on a object created in the where clause"
def display = mockDisplay()
and:"a activityt"
def activity = new ConfigActivity(display)
when:
activity.doStuff()
then:
1 * display.select()
where:
dependency << new Dependency()
}
private mockDisplay() {
def display = Mock(ConfigActivity.Display)
display.addDependency(dependency)
return display
}
I understand that that the "mockDisplay()" method is out of scope from the "where" clause. However since a few specifications tend to get rather cluttered with boilerplate code (not in this over simplified example offcourse) I really need some way to reuse my "given" statements and in doing so I would really like to make use of the Spock "where" clauses as well.
Is this doable? Or is there another way to go about this problem?
There is no magic way to access a data variable from a helper method, but you can pass it as a method parameter.

node.js jade template - custom syntax and replacements?

I'm trying to get jade to automatically generate urls for me:
so if I have a user link like this:
.userLink
a(href="/#{user}") #{user}
I want to be able to replace it with something like (hypothetical syntax):
.userLink
userLink(#{user})
Anyway to do this?
Thanks
Edit: OKAY I got it:
mixin userLink(user)
a(href="/" + user)= user
mixin userLink("Bob")
Seems like that will work.
UPDATE:
Here's a version using jade mixins. Sadly, I can't seem to find the "user" variable within the parenthesized attributes list of the "a" tag.
mixin userLink(user)
a(href="/" + user)= user
mixin userLink("Bob")
mixin userLink("Alice")
mixin userLink("Cooper")
Generates this HTML
Bob
Alice
Cooper
Just put a helper function into your locals object and call it from the template
locals = {userLink: function(userName) { return "<a href=....."}}
jade.render('myview', {locals: locals})
Then in your jade template do:
= userLink(user)
You may also want to look at possibly registering a dynamicHelper function.

.Net MVC route for undetermined number of folders (nested category structure)

I'm exploring the possibility of using MVC for my next e-commerce site. One thing I can't seem to figure out is whether or not I can use the same URL convention I normally use. Currently, the URL for any product could be one of the following:
Category/SubCategory/Product1.html
Category/SubCategory/SubSubCategory/Product2.html
Category/SubCategory/SubSubCategory/Product3.html
Category/SubCategory/SubSubCategory/SubSubSubCategory/Product4.html
etc.
The issue I'm having is with the nested category structure. So far the only thing I've come up with is as follows:
routes.MapRoute(
"Products",
"{categories}/{productname}",
new { controller = "Product", action = "Details", productname = UrlParameter.Optional },
new { categories = #"\w+/\w+" }
);
I was hoping that {categories} could be matched with any one of the following which I could process to identify the right category that the product belongs to:
Sport/Tennis/Rackets/ProductA
Sport/Badminton/Rackets/ProductB
But the route shown above doesn't work correctly.
Does anyone know how this can be achieved, or if it can't be done?
The routing system allows you to define catchall parameters, which ignore slashes and capture
everything up to the end of a URL. Designate a parameter as being catchall by prefixing it with an
asterisk (*).
routes.MapRoute(null, "Articles/{*articlePath}",
new { controller = "Articles", action = "Show" }
);
You can only have one catchall parameter in a URL pattern, and it must be the last (i.e.,
rightmost) thing in the URL, since it captures the entire URL path from that point onward.
One Caveat though, it doesn’t capture anything from the query string as route objects only look at the
path portion of a URL.
Catchall parameters are useful if you’re letting visitors navigate through some kind of arbitrary
depth hierarchy, such as in a content management system (CMS).
You can use the RouteData object to extract information about the route. For your needs, you would probably create a custom route handler that parses the route data and calls the correct controller methods.
You need access to the individual segments of the URL so you need to divide the category segment into two segments. That would make it much easier.
Let's say we call Tennis and Badminton categories and Rackets within those categories as a product class
You need a way to access the category, productClass and productName parameters. Supposing that "Sport" is fixed in this case, I will do it like this:
routes.MapRoute(
"Products",
"sport/{category}/{productClass}/{productName}",
new { controller = "Product", action = "Details", productClass = UrlParameter.Optional, productName = UrlParameter.Optional }
);
Your action method will be something like this
public ActionResult Details(string category, string productClass, string productName){
//Do whatever you need to do in order to get the specified product
}
You could use Areas in MVC2
So it would read:
Area/Controller/View/id
So in your case it would end up being:
Sport being the area,
Tennis The controller,
Rackets the view,
ProductA being an ID or querystring,
http://www.asp.net/mvc/videos/aspnet-mvc-2-areas
Hope this makes sense.