Skip to content

Commit b03a112

Browse files
authored
v2.3.2 (#35)
* test search with spaces issue #33 * Update README.md * typo fix (fields) * add IgnoreNotMappedFiels Configuration #34 * use IgnoreNotMappedFields in orderings #34 * fix comment * add some summary * update to version 2.3.2
1 parent 25707ac commit b03a112

7 files changed

+129
-18
lines changed

src/Gridify.EntityFramework/Gridify.EntityFramework.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<PropertyGroup>
1010
<TargetFramework>netstandard2.0</TargetFramework>
1111
<PackageId>Gridify.EntityFramework</PackageId>
12-
<Version>2.3.1</Version>
12+
<Version>2.3.2</Version>
1313
<Authors>Alireza Sabouri</Authors>
1414
<Company>TuxTeam</Company>
1515
<PackageDescription>Gridify (EntityFramework), Easy and optimized way to apply Filtering, Sorting, and Pagination using text-based data.</PackageDescription>

src/Gridify/Gridify.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<PackageId>Gridify</PackageId>
6-
<Version>2.3.1</Version>
6+
<Version>2.3.2</Version>
77
<Authors>Alireza Sabouri</Authors>
88
<Company>TuxTeam</Company>
99
<PackageDescription>Gridify, Easy and optimized way to apply Filtering, Sorting, and Pagination using text-based data.</PackageDescription>

src/Gridify/GridifyExtensions.cs

+28-3
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
using Gridify.Syntax;
77

88
[assembly: InternalsVisibleTo("Gridify.EntityFramework")]
9+
910
namespace Gridify
1011
{
1112
public static partial class GridifyExtensions
1213
{
1314
internal static bool EntityFrameworkCompatibilityLayer { get; set; }
1415
public static int DefaultPageSize { get; set; } = 20;
15-
16+
1617
#region "Private"
1718

1819
/// <summary>
@@ -132,13 +133,37 @@ public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, IGridifyO
132133
: ProcessOrdering(query, gridifyOrdering.OrderBy!, startWithThenBy, mapper);
133134
}
134135

136+
/// <summary>
137+
/// adds Ordering to the query
138+
/// </summary>
139+
/// <param name="query">the original(target) queryable object</param>
140+
/// <param name="orderBy">the ordering fields</param>
141+
/// <param name="mapper">this is an optional parameter to apply ordering using a custom mapping configuration</param>
142+
/// <param name="startWithThenBy">if you already have an ordering with start with ThenBy, new orderings will add on top of your orders</param>
143+
/// <typeparam name="T">type of target entity</typeparam>
144+
/// <returns>returns user query after applying Ordering </returns>
145+
public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, string orderBy, IGridifyMapper<T>? mapper = null,
146+
bool startWithThenBy = false)
147+
{
148+
mapper = mapper.FixMapper();
149+
return string.IsNullOrWhiteSpace(orderBy)
150+
? query
151+
: ProcessOrdering(query, orderBy, startWithThenBy, mapper);
152+
}
153+
135154
private static IQueryable<T> ProcessOrdering<T>(IQueryable<T> query, string orderings, bool startWithThenBy, IGridifyMapper<T> mapper)
136155
{
137156
var isFirst = !startWithThenBy;
138157
foreach (var (member, isAscending) in ParseOrderings(orderings))
139158
{
140-
// skip if there is no mappings available
141-
if (!mapper.HasMap(member)) continue;
159+
if (!mapper.HasMap(member))
160+
{
161+
// skip if there is no mappings available
162+
if (mapper.Configuration.IgnoreNotMappedFields)
163+
continue;
164+
165+
throw new GridifyMapperException($"Mapping '{member}' not found");
166+
}
142167

143168
if (isFirst)
144169
{

src/Gridify/GridifyMapper.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public IEnumerable<IGMap<T>> GetCurrentMaps()
135135

136136
/// <summary>
137137
/// Converts current mappings to a comma seperated list of map names.
138-
/// eg, filed1,field2,field3
138+
/// eg, field1,field2,field3
139139
/// </summary>
140140
/// <returns>a comma seperated string</returns>
141141
public override string ToString() => string.Join(",", _mappings.Select(q => q.From));

src/Gridify/GridifyMapperConfiguration.cs

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ namespace Gridify
33
public record GridifyMapperConfiguration
44
{
55
public bool CaseSensitive { get; set; }
6+
7+
/// <summary>
8+
/// This option enables the 'null' keyword in filtering operations
9+
/// </summary>
610
public bool AllowNullSearch { get; set; } = true;
11+
/// <summary>
12+
/// If true, in filtering and ordering operations,
13+
/// gridify doesn't return any exceptions when a mapping
14+
/// is not defined for the fields
15+
/// </summary>
16+
public bool IgnoreNotMappedFields { get; set; }
717
}
818
}

src/Gridify/Syntax/SyntaxTreeToQueryConvertor.cs

+20-9
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ public static class ExpressionToQueryConvertor
1212
private static (Expression<Func<T, bool>> Expression, bool IsNested)? ConvertBinaryExpressionSyntaxToQuery<T>(
1313
BinaryExpressionSyntax binarySyntax, IGridifyMapper<T> mapper)
1414
{
15-
1615
var fieldExpression = binarySyntax.Left as FieldExpressionSyntax;
17-
16+
1817
var left = fieldExpression?.FieldToken.Text.Trim();
1918
var right = (binarySyntax.Right as ValueExpressionSyntax);
2019
var op = binarySyntax.OperatorToken;
@@ -23,10 +22,10 @@ private static (Expression<Func<T, bool>> Expression, bool IsNested)? ConvertBin
2322

2423
var gMap = mapper.GetGMap(left);
2524

26-
if (gMap == null) return null;
27-
25+
if (gMap == null) throw new GridifyMapperException($"Mapping '{left}' not found");
26+
2827
if (fieldExpression!.IsCollection)
29-
gMap.To = UpdateExpressionIndex(gMap.To,fieldExpression.Index);
28+
gMap.To = UpdateExpressionIndex(gMap.To, fieldExpression.Index);
3029

3130
if (gMap.IsNestedCollection)
3231
{
@@ -44,11 +43,11 @@ private static (Expression<Func<T, bool>> Expression, bool IsNested)? ConvertBin
4443

4544
private static LambdaExpression UpdateExpressionIndex(LambdaExpression exp, int index)
4645
{
47-
var parameter = exp.Parameters[0];
46+
var parameter = exp.Parameters[0];
4847
var unary = exp.Body as UnaryExpression;
4948
var body = unary!.Operand as MemberExpression;
50-
var newBody = new PredicateBuilder.ReplaceExpressionVisitor(exp.Parameters[1],Expression.Constant(index,typeof(int))).Visit(body!);
51-
return Expression.Lambda(newBody,parameter);
49+
var newBody = new PredicateBuilder.ReplaceExpressionVisitor(exp.Parameters[1], Expression.Constant(index, typeof(int))).Visit(body!);
50+
return Expression.Lambda(newBody, parameter);
5251
}
5352

5453
private static Expression<Func<T, bool>>? GenerateNestedExpression<T>(
@@ -382,7 +381,19 @@ internal static (Expression<Func<T, bool>> Expression, bool IsNested)
382381
var bExp = expression as BinaryExpressionSyntax;
383382

384383
if (bExp!.Left is FieldExpressionSyntax && bExp.Right is ValueExpressionSyntax)
385-
return ConvertBinaryExpressionSyntaxToQuery(bExp, mapper) ?? throw new GridifyFilteringException("Invalid expression");
384+
{
385+
try
386+
{
387+
return ConvertBinaryExpressionSyntaxToQuery(bExp, mapper) ?? throw new GridifyFilteringException("Invalid expression");
388+
}
389+
catch (GridifyMapperException e)
390+
{
391+
if (mapper.Configuration.IgnoreNotMappedFields)
392+
return (_ => true, false);
393+
394+
throw;
395+
}
396+
}
386397

387398
(Expression<Func<T, bool>> exp, bool isNested) leftQuery;
388399
(Expression<Func<T, bool>> exp, bool isNested) rightQuery;

test/Gridify.Tests/GridifyExtensionsShould.cs

+68-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void ApplyFiltering_DisableNullHandlingUsingMapper()
9797
}
9898

9999
[Fact]
100-
public void ApplyFiltering_DuplicateFiledName()
100+
public void ApplyFiltering_DuplicatefieldName()
101101
{
102102
const string gq = "name=John|name=Sara";
103103
var actual = _fakeRepository.AsQueryable()
@@ -457,6 +457,7 @@ public void ApplyFiltering_GreaterThanBetweenTwoStrings()
457457
Assert.Equal(expected, actual);
458458
Assert.True(actual.Any());
459459
}
460+
460461

461462
[Fact] // issue #27
462463
public void ApplyFiltering_LessThanBetweenTwoStrings()
@@ -551,6 +552,43 @@ public void ApplyFiltering_NotEqual_ProcessingNullOrDefaultValueNonStringTypes()
551552
Assert.Equal(expected, actual);
552553
Assert.True(actual.Any());
553554
}
555+
556+
[Fact] // issue #33
557+
public void ApplyFiltering_WithSpaces()
558+
{
559+
var actual = _fakeRepository.AsQueryable().ApplyFiltering("name =ali reza").ToList();
560+
var expected = _fakeRepository.Where(q => q.Name == "ali reza" ).ToList();
561+
562+
Assert.Equal(expected.Count, actual.Count);
563+
Assert.Equal(expected, actual);
564+
Assert.True(actual.Any());
565+
}
566+
567+
568+
[Fact] // issue #34
569+
public void ApplyFiltering_UnmappedFields_ShouldThrowException()
570+
{
571+
var gm = new GridifyMapper<TestClass>()
572+
.AddMap("Id", q => q.Id);
573+
574+
var exp = Assert.Throws<GridifyMapperException>(() => _fakeRepository.AsQueryable().ApplyFiltering("name=John,id>0", gm).ToList());
575+
Assert.Equal("Mapping 'name' not found",exp.Message);
576+
}
577+
578+
[Fact] // issue #34
579+
public void ApplyFiltering_UnmappedFields_ShouldSkipWhenIgnored()
580+
{
581+
var gm = new GridifyMapper<TestClass>(configuration => configuration.IgnoreNotMappedFields = true)
582+
.AddMap("Id", q => q.Id);
583+
584+
// name=*a filter should be ignored
585+
var actual = _fakeRepository.AsQueryable().ApplyFiltering("name=*a, id>15", gm).ToList();
586+
var expected = _fakeRepository.Where(q => q.Id > 15).ToList();
587+
588+
Assert.Equal(expected.Count, actual.Count);
589+
Assert.Equal(expected, actual);
590+
Assert.True(actual.Any());
591+
}
554592

555593
#endregion
556594

@@ -644,12 +682,38 @@ public void ApplyOrdering_EmptyOrderBy_ShouldSkip()
644682
[Fact]
645683
public void ApplyOrdering_NullGridifyQuery_ShouldSkip()
646684
{
685+
GridifyQuery gq = null;
647686
var actual = _fakeRepository.AsQueryable()
648-
.ApplyOrdering(null)
687+
.ApplyOrdering(gq)
649688
.ToList();
650689
var expected = _fakeRepository.ToList();
651690
Assert.Equal(expected, actual);
652691
}
692+
693+
[Fact] // issue #34
694+
public void ApplyOrdering_UnmappedFields_ShouldThrowException()
695+
{
696+
var gm = new GridifyMapper<TestClass>()
697+
.AddMap("Id", q => q.Id);
698+
699+
var exp = Assert.Throws<GridifyMapperException>(() => _fakeRepository.AsQueryable().ApplyOrdering("name,id", gm).ToList());
700+
Assert.Equal("Mapping 'name' not found",exp.Message);
701+
}
702+
703+
[Fact] // issue #34
704+
public void ApplyOrdering_UnmappedFields_ShouldSkipWhenIgnored()
705+
{
706+
var gm = new GridifyMapper<TestClass>(configuration => configuration.IgnoreNotMappedFields = true)
707+
.AddMap("Id", q => q.Id);
708+
709+
// name orderBy should be ignored
710+
var actual = _fakeRepository.AsQueryable().ApplyOrdering("name,id", gm).ToList();
711+
var expected = _fakeRepository.OrderBy(q => q.Id ).ToList();
712+
713+
Assert.Equal(expected.Count, actual.Count);
714+
Assert.Equal(expected, actual);
715+
Assert.True(actual.Any());
716+
}
653717

654718
#endregion
655719

@@ -784,7 +848,8 @@ private static IEnumerable<TestClass> GetSampleData()
784848
lst.Add(new TestClass(23, "LI | AM", null));
785849
lst.Add(new TestClass(24, "(LI,AM)", null, tag: string.Empty));
786850
lst.Add(new TestClass(25, "Case/i", null, tag: string.Empty));
787-
lst.Add(new TestClass(26, "/iCase", null));
851+
lst.Add(new TestClass(26, "/iCase", null));
852+
lst.Add(new TestClass(27, "ali reza", null));
788853

789854
return lst;
790855
}

0 commit comments

Comments
 (0)