in my current project, i was so stupid to make an API which expects the variable private. in the controller it gets mapped to isPrivate, but now i wanted to make a commandObject (#validatable) to check if everything is valid. How can i map the private variable using autobinding on isPrivate?
#Validateable
class EventCommand{
boolean isPrivate
boolean fullDay
String title
String location
String description
static constraints = {
location(nullable: true)
description(nullable: true)
fullDay (nullable: false)
isPrivate(nullable: false)
title (blank: true, nullable: false)
}
}
and the code where the databinding happens (inside a grails controllor):
def add() {
def jsonData = request.JSON
EventCommand command = new EventCommand(jsonData)
if(!command.validate()){
throw new QuivrException(command)
}
boolean isPrivate = jsonData.private
//some things happen, uninmportant
}
i already tried using the #BindUsing annotation, but i always keep getting the error that EventCommand has no property named "private" (the matches works, but he tries to match private to something none-existant)
is there any way to solve this without changing the received private to isPrivated (already got old versions of the application and got 20% not on latest version)
Well from your jsonData remove the private property and then do the binding and after binding add the private manually from a variable in which you should be getting the private value.
Hence your add could be something like
def add() {
def jsonData = request.JSON
String isPrivate = jsonData.private
jsonData.remove("private")
EventCommand command = new EventCommand(jsonData)
if(!command.validate()){
throw new QuivrException(command)
}
command.isPrivate = isPrivate as Boolean
}
Related
I could use a constructor, but I want another way considering the case with many parameters.
Also, I don't want to change private fields to public.
please help me
#Test
#DisplayName("save the post")
void savePost() {
// Arrange
String title = "title...";
String contents = "contents...";
Post post = new Post(title, contents);
// Act
Post savedPost = postRepository.save(post);
...
I have a command object that get populated via Search form and I want to validate that at least 1 field was submitted. Currently I am doing the validation in the Controller and looping through all the properties.
class SearchCommand implements Validateable {
List<String> termID;
List<String> subject;
List<String> title;
}
def getSearch(SearchCommand cmd) {
boolean isFormEmpty = true;
//make sure at least 1 property is filled out.
SearchCommand.metaClass.properties.each{ MetaProperty prop ->
if(prop.field && cmd[prop.name] && !cmd[prop.name].isEmpty()) {
isFormEmpty = false;
}
}
}
So this works but I want to know if there is a better way to do it. I would prefer to have this built into the command object so I can just call cmd.hasErrors(). Not sure if there is a clean & non-hacky way to do this that is dynamic to where when I add/remove properties I don't have to change the validation logic.
I am having a problem initializing a boolean property in my ViewModel. I am not sure the right way to go about this.
I have a Switch control on the main activity, and if I change the switch I want to change the boolean startsWith value. Depending on the boolean value I will call the corresponding Dao function.
I am trying to initialize the value, but not sure how to do this. Should I observe the boolean value, should I use two way binding, should this property be MutableLiveData?
wordListViewModel = ViewModelProviders.of(this).get(WordListViewModel.class);
wordListViewModel.setStartsWith(true);
I get this error, cannot even start Activity:
Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
Code:
public class WordListViewModel extends AndroidViewModel {
final MutableLiveData<String> searchText = new MutableLiveData<>();
final MutableLiveData<Boolean> startsWith = new MutableLiveData<>();
private final LiveData<List<WordEntity>> list;
private AppDatabase appDatabase;
public WordListViewModel(Application application) {
super(application);
appDatabase = AppDatabase.getDatabase(this.getApplication());
if (startsWith.getValue() == true)
list = Transformations.switchMap(searchText, searchText -> {
return appDatabase.wordDao().getWordsStartingWith(searchText);
});
else
list = Transformations.switchMap(searchText, searchText -> {
return appDatabase.wordDao().getWordsLike(searchText);
});
}
I think I figured it out. The check has to be inside the switchMap function.
The rest of the code only runs when the model is initialized.
I changed my code and it worked:
if (startsWith.getValue() == null)
startsWith.setValue(true);
list = Transformations.switchMap(searchText, searchText -> {
if (startsWith.getValue() == true)
return appDatabase.dictWordDao().getWordsStartingWith(searchText);
else
return appDatabase.dictWordDao().getWordsLike(searchText);
});
I'm wanting to make use of the new method for globally logging errors. I've written a class that inherits ExceptionLogger and overrides the Log() method. Then registered it as a replacement.
public class TraceExceptionLogger : ExceptionLogger
{
public async override void Log(ExceptionLoggerContext context)
{
// This is always empty string
var content = await context.Request.Content.ReadAsStringAsync();
// This is almost always null
var actionContext = context.ExceptionContext.ActionContext;
}
}
I can dig through the ExceptionLoggerContext object's properties to get pretty much everything I need, EXCEPT for action parameters. There is indeed an ActionContext property but I've only seen it null and this wiki page states that ActionContext and ControllerContext will almost always be null.
Also, I can't get the content stream because its stream is already read before it gets to my logger. So there's no way for me to get any posted json from the request's content.
Is there maybe a way to get the posted data from HttpContext.Current or in some other way?
Ok it looks like I can get the body text from HttpContext by reading InputStream on the Request object like this:
string bodyText = string.Empty;
using (var sr = new StreamReader(HttpContext.Current.Request.InputStream))
{
sr.BaseStream.Seek(0, SeekOrigin.Begin);
bodyText = sr.ReadToEnd();
}
This code has been successful me so far for getting my posted json data.
Here's action parameters for future reference
public class HomeController : ApiController {
public string Get(string id, [FromHeader] Whoever whoever) {
public string Post(Whatever whatever) {
var args = ((ApiController) context.ExceptionContext
.ControllerContext.Controller)).ActionContext.ActionArguments
if (args.ContainsKey("whatever")) {
var whatever = (Whatever)args["whatever"];
I am implementing a custom module in Orchard to track the number of views for each content item. In my handler, I am checking to see if the content item's type is the default Orchard "Page" type, but right now it is using the Equals function and magic strings. Here's my code:
public class ContentItemViewRecordHandler : ContentHandler
{
private readonly IOrchardServices services;
private readonly IRepository<ContentItemViewRecord> repository;
public ContentItemViewRecordHandler(IOrchardServices services, IRepository<ContentItemViewRecord> repository)
{
this.services = services;
this.repository = repository;
OnGetDisplayShape<CommonPart>(RecordView);
}
private void RecordView(BuildDisplayContext context, CommonPart part)
{
var contentItemType = context.ContentItem.ContentType;
// THIS IS THE IF STATEMENT IN QUESTION
if (!contentItemType.Equals("Page", StringComparison.CurrentCultureIgnoreCase))
{
return;
}
var contentItemViewRecord = new ContentItemViewRecord
{
ContentItemRecordId = context.ContentItem.Id,
Username = services.WorkContext.CurrentUser.UserName,
HostAddress = services.WorkContext.HttpContext.Request.UserHostAddress,
DateCreated = DateTime.UtcNow
};
repository.Create(contentItemViewRecord);
}
}
Anyone know if there is a way to determine the content item's type without the magic strings?
Content types are not .NET types. They are dynamic entities that only exist at runtime. Strings are therefore perfectly fine to identify them.