Capture all url segments after the initial match with Nancy - nancy

I would like to have nancy rule that matches/captures all url segments after the initial match.
For example I would like to do this:
have a url like: /views/viewname/pageid/visitid/someother
and a rule like this:
Get["/views/{view}/{all other values}"] = parameters =>
{
string view = parameters.view;
List<string> listOfOtherValues = all other parameters..
return ...
};
listOfOtherValues would end up being:
pageid
visitid
someother
I would also like to do this for querystring parameters.
given the a url like: /views/viewname?pageid=1&visitid=34&someother=hello
then listOfOtherValues would end up being:
1
34
hello
Is this even possible with Nancy?

For your first problem you can use regular expression as well as simple names to define your capture groups. So you just define a catch all RegEx.
For your second, you just need to enumerate through the Request.Query dictionary.
Here is some code that demonstrates both in a single route.
public class CustomModule : NancyModule
{
public CustomModule() {
Get["/views/{view}/(?<all>.*)"] = Render;
}
private Response Render(dynamic parameters) {
String result = "View: " + parameters.view + "<br/>";
foreach (var other in ((string)parameters.all).Split('/'))
result += other + "<br/>";
foreach (var name in Request.Query)
result += name + ": " + Request.Query[name] + "<br/>";
return result;
}
}
With this in place you can call a URL such as /views/home/abc/def/ghi/?x=1&y=2 and get the output
View: home
abc
def
ghi
x: 1
y: 2
Note:
The foreach over Request.Query is support in v0.9+

Related

Snowflake external stage with multiple urls

I am creating an external stage, I want it to be based on 2 URLs.
PROBLEM 1
url1 = s3://bucket1/f1/2022/2/
url2 = s3://bucket1/f3/2022/2/
create or replace stage ext_stage url = ??????????
file_format=data_format
storage_integration=s3_integration;
How can I give 2 URLs in the external stage command? Is it possible?
PROBLEM 2
Also, I need to form the URLs.
I am thinking to use a procedure for it.
CREATE OR REPLACE PROCEDURE get_url()
RETURNS STRING
LANGUAGE SCALA
RUNTIME_VERSION = '2.12'
HANDLER = 'C.run'
PACKAGES = ('com.snowflake:snowpark:latest')
AS
$$
import java.util.Calendar
object C{
def run(session: com.snowflake.snowpark.Session): String = {
try {
val cal = Calendar.getInstance()
val year =cal.get(Calendar.YEAR)
var month =cal.get(Calendar.MONTH) + 1
return "s3://bucket1/folder1/" + year + "/"+ month + "/"
}
catch {
case e: Throwable => println("Not able to for url")
return "Failed"
}
}
}
$$;
create or replace stage ext_stage url = call get_url()
file_format=data_format
storage_integration=s3_integration;
It is failing and I can not call the function. How can I call it?

Receiving errors on Apex class to match fields for two different custom objects

I've been stuck for 18 hours on this apex class. I would really appreciate some help to figure out what's wrong. Basically this code should match the fields between two objects and I don't know why I'm receiving the following errors:
Missing return statement required return type: String - Line 2
Expecting '}' but was: 'for' - Line 26
The output should show that when location and position title from Candidate object matches location and title from Position object then it will just show those values that match on a data table in a lightning web component I made on Visual Studio.
I'd like some help improving this code so I can run it on the dev console.
public class Matchposition {
public static String matchPositionsWithCandidate() {
Set<String> statuses = new Set<String> {'New', 'Open'};
List<Position__c> openPositions = [SELECT Id, Name, Location__c, Status__c FROM Position__c WHERE Status__c IN :statuses];
//system.debug(openPositions);
Set<String> openPositionAndLocation = new Set<String>();
Map<String, Position__c> openPositionMap = new Map<String, Position__c>();
for (Position__c position : openPositions) {
openPositionMap.put(position.Name + '-' + position.Location__c, position);
openPositionAndLocation.add(position.Name + '-' + position.Location__c);
}
}
//for(String key : openPositionMap.keySet()) {
// system.debug('*** Start ***');
// system.debug('key :' + key);
// system.debug('value :' + openPositionMap.get(key));
// system.debug('*** End ***');
//}
Map<String, List<Candidate__c>> candidatesMap = new Map<String, List<Candidate__c>>();
List<Candidate__c> candidates = [SELECT Position__c, Location__c, Mobile__c, First_Name__c, Last_Name__c, Email__c FROM Candidate__c];
for (Candidate__c candidate : candidates) {
if(candidatesMap.containsKey(candidate.Position__c + '-' + candidate.Location__c)) {
candidatesMap.get(candidate.Position__c + '-' + candidate.Location__c).add(candidate);
} else {
candidatesMap.put(candidate.Position__c + '-' + candidate.Location__c, new List<Candidate__c> {candidate});
}
}
system.debug('*************** OPEN POSITIONS ***************');
for (String key : openPositionAndLocation) {
system.debug('====> ' + openPositionMap.get(key).Name);
if(candidatesMap.containsKey(key)) {
system.debug('***** Candidates *****');
for(Candidate__c candidate : candidatesMap.get(key)) {
system.debug('------- Name : ' + candidate.First_Name__c + ' ' + candidate.Last_Name__c);
system.debug('------- Email : ' + candidate.Email__c);
system.debug('------- Mobile : ' + candidate.Mobile__c);
}
} else {
system.debug('********* No Candidates');
}
}
One issue you certainly have, apropos of nothing else, is overall structure. Removing the actual lines of code, here's how your class is laid out now:
public class Matchposition {
public static String matchPositionsWithCandidate() {
// Code here
}
// more code here - problem!
}
You have much of your logic loose in the body of your class, which is not valid in Apex. Additionally, the code in the class body references variables declared inside the method matchPositionsWithCandidate(), which are scoped (visible) to that method.
matchPositionsWithCandidate() is also declared to return a string, but in fact returns nothing at all.
Since you're not returning any data anywhere, one step you can take to try to get this code running is to ensure that all of your logic is inside the scope (the curly braces) of the method matchPositionsWithCandidate(), and declare that method to return void, not String.
You may also have unbalanced braces - it looks like there is one missing after the final else - if it wasn't simply omitted in the copy and paste.
I'm not sure why this code exists. While much of the logic is correct, it makes far more sense to model your data with a relationship between Candidate__c and Position__c, rather than just storing a name in both positions. Then, you don't need any "matching" code at all - just a simple SOQL relationship query.

Dapper.net with unknown quantity of array elements

What I'm trying to do it have a filter object that is populated like so
var filter = new Filter
{
ThingID = 1,
Keywords = new[] { "op", "s" }
};
And then be able to build up the query like this:
var sb = new StringBuilder();
sb.AppendLine("select * from Stuff where 1=1");
if (filter.ThingID.HasValue)
{
sb.AppendLine(" and ThingID = #ThingID");
}
if (filter.Keywords != null)
{
for (int i = 0; i < filter.Keywords.Length; i++)
{
string keyword = filter.Keywords[i];
if (!string.IsNullOrWhiteSpace(keyword))
{
sb.AppendLine(" and ( Model like '%' || #Keywords" + i + " || '%' )");
}
}
}
var sql = sb.ToString();
var results = Query<Stuff>(sql, filter).ToList();
This works fine if just the ThingID prop is populated, but as far as I can tell Dapper is not feeding the Keywords in as a parameter in any way. Is this possible with Dapper, or does it only work in the context of " where Keywords in #Keywords"?
Parameters need to match by name; you are adding parameters like #Keywords17, but there is no Keywords17 property for it to add. It doesn't interpret that as Keywords[17], if that is what you mean. There is some automatic expansion of flat arrays, but that is intended for expanding in #Keywords (although the expansion itself is not specific to in). There is not currently something that would help you automatically there; I would suggest DynamicPaameters instead:
var args = new DynamicParameters();
args.Add("ThingID", 1);
...
if (!string.IsNullOrWhiteSpace(keyword))
{
sb.AppendLine(" and ( Model like '%' || #Keywords" + i + " || '%' )");
args.Add("Keywords" + i, keyword);
}
...
var cmd = new CommandDefinition(sql, args, flags: CommandFlags.NoCache);
var results = Query<Stuff>(cmd).AsList();
note the subtle two changes at the end here - CommandFlags.NoCache will help avoid building lots of lookup entries for similar but different SQL (although you might choose to pay this to reduce per-item cost, up to you). The AsList instead of ToList avoids an extra list allocation.

How do I build a dynamic sql query with Dapper.SqlBuilder and OrWhere

I am attempting to build a dynamic Sql query for multiple search terms. I understand in general how to use the builder, but am not sure what to do in the loop since I actually need the #term to be different each time (I think). Not just in the query, but in the anonymous type as well to match.
I could use a string.Format in the query string, but not sure how to match it in the anonymous type?
public async Task<List<Thing>> Search(params string[] searchTerms)
{
var builder = new SqlBuilder();
var template = builder.AddTemplate("SELECT * /**select**/ from ThingTags /**where**/ ");
for (int i = 0; i < searchTerms.Length; i++)
{
builder.OrWhere("value LIKE #term", new { term = "%" + searchTerms[i] + "%" });
}
...
}
in the current form the query that gets created for terms "abc" "def" "ghi" is
CommandType: Text, CommandText: SELECT * from ThingTags WHERE ( value LIKE #term OR value LIKE #term OR value LIKE #term )
Parameters:
Name: term, Value: %ghi%
Well here is one way to do the query building. I didn't realize that the parameters could be a Dictionary initially.
public async Task<List<Thing>> Search(params string[] searchTerms)
{
var builder = new SqlBuilder();
var template = builder.AddTemplate("SELECT * /**select**/ from ThingTags /**where**/ ");
for (int i = 0; i < searchTerms.Length; i++)
{
var args = new Dictionary<string, object>();
var termId = string.Format("term{0}", i.ToString());
args.Add(termId, "%" + searchTerms[i] + "%");
builder.OrWhere("value LIKE #" + termId, args);
}
...
}
You can easily create that dynamic condition using DapperQueryBuilder:
var query = cn.QueryBuilder($#"
SELECT *
FROM ThingTags
/**where**/");
// by default multiple filters are combined with AND
query.FiltersType = Filters.FiltersType.OR;
foreach (var searchTerm in searchTerms)
query.Where($"value like {searchTerm}");
var results = query.Query<YourPOCO>();
The output is fully parametrized SQL (WHERE value like #p0 OR value like #p1 OR...). You don't have to manually manage the dictionary of parameters.
Disclaimer: I'm one of the authors of this library

Spring MVC + RequestParam as Map + get URL array parameters not working

I'm currently working on an API controller. This controller should be able to catch any - unknown - parameter and put it in a Map object. Now I'm using this code to catch all parameters and put them in a Map
public String processGetRequest(final #RequestParam Map params)
Now the url I call is as follows:
server/api.json?action=doSaveDeck&Card_IDS[]=1&Card_IDS[]=2&Card_IDS[]=3
Then I print out the parameters, for debugging purposes, with this piece of code:
if (logger.isDebugEnabled()) {
for (Object objKey : params.keySet()) {
logger.debug(objKey.toString() + ": " + params.get(objKey));
}
}
The result of that is:
10:43:01,224 DEBUG ApiRequests:79 - action: doSaveDeck
10:43:01,226 DEBUG ApiRequests:79 - Card_IDS[]: 1
But the expected result should be something like:
10:43:XX DEBUG ApiRequests:79 - action: doSaveDeck
10:43:XX DEBUG ApiRequests:79 - Card_IDS[]: 1
10:43:XX DEBUG ApiRequests:79 - Card_IDS[]: 2
10:43:XX DEBUG ApiRequests:79 - Card_IDS[]: 3
Or atleast tell me that the Card_IDS is an String[] / List<String> and therefore should be casted. I also tried casting the parameter to a List<String> manually but that does not work either:
for (Object objKey : params.keySet()) {
if(objKey.equals(NameConfiguration.PARAM_NAME_CARDIDS)){ //Never reaches this part
List<String> ids = (List<String>)params.get(objKey);
for(String id : ids){
logger.debug("Card: " + id);
}
} else {
logger.debug(objKey + ": " + params.get(objKey));
}
}
Could someone tell me how to get the array Card_IDS - It must be dynamically - from the Map params by using the NameConfiguration.PARAM_NAME_CARDIDS?
When you request a Map annotated with #RequestParam Spring creates a map containing all request parameter name/value pairs. If there are two pairs with the same name, then only one can be in the map. So it's essentially a Map<String, String>
You can access all parameters through a MultiValueMap:
public String processGetRequest(#RequestParam MultiValueMap parameters) {
This map is essentially a Map<String, List<String>>. So parameters with the same name would be in the same list.

Resources