I'm building a Flux app using MartyJS (which is pretty close to "vanilla" Flux and uses the same underlying dispatcher). It contains stores with an inherent dependency relationship. For example, a UserStore tracks the current user, and an InstanceStore tracks instances of data owned by the current user. Instance data is fetched from an API asynchronously.
The question is what to do to the state of the InstanceStore when the user changes.
I've come to believe (e.g. reading answers by #fisherwebdev on SO) that it's most appropriate to make AJAX requests in the action creator function, and to have an AJAX "success" result in an action that in turn causes stores to change.
So, to fetch the user (i.e. log in), I'm making an AJAX call in the action creator function, and when it resolves, I'm dispatching a RECEIVE_USER action with the user as a payload. The UserStore listens to this and updates its state accordingly.
However, I also need to re-fetch all the data in the InstanceStore if the user is changed.
Option 1: I can listen to RECEIVE_USER in the InstanceStore, and if it is a new user, trigger an AJAX request, which in turn creates another action, which in turn causes the InstanceStore to update. The problem with this is that it feels like cascading actions, although technically it's async so the dispatcher will probably allow it.
Option 2: Another way would be for InstanceStore to listen to change events emitted by UserStore and do the request-action dance then, but this feels wrong too.
Option 3: A third way would be for the action creator to orchestrate the two AJAX calls and dispatch the two actions separately. However, now the action creator has to know a lot about how the stores relate to one another.
One of the answers in Where should ajax request be made in Flux app? makes me think option 1 is the right one, but the Flux docs also imply that stores triggering actions is not good.
Something like option 3 seems like the cleanest solution to me, followed by option 1. My reasoning:
Option 2 deviates from the expected way of handling dependencies between stores (waitfor), and you'd have to check after each change event to figure out which ones are relevant and which ones can be ignored, or start using multiple event types; it could get pretty messy.
I think option 1 is viable; as Bill Fisher remarked in the post you linked, it's OK for API calls to be made from within stores provided that the resulting data is handled by calling new Actions. But OK doesn't necessarily mean ideal, and you'd probably achieve better separation of concerns and reduce cascading if you can collect all your API calls and action initiation in one place (i.e. ActionCreators). And that would be consistent with option 3.
However, now the action creator has to know a lot about how the stores
relate to one another.
As I see it, the action creator doesn't need to know anything about what the stores are doing. It just needs to log in a user and then get the data associated with the user. Whether this is done through one API call or two, these are logically very closely coupled and make sense within the scope of one action creator. Once the user is logged in and the data is obtained, you could fire two actions (e.g. LOGGED_IN, GOT_USER_DATA) or even just one action that contains all the data needed for both. Either way, the actions are just echoing what the API calls did, and it's up to the stores to decide what to do with it.
I'd suggest using a single action to update both stores, because this seems like a perfect use case for waitfor: when one action triggers a handler in both stores, you can instruct InstanceStore to wait for UserStore's handler to finish before InstanceStore's handler executes. It would look something like this:
UserStore.dispatchToken = AppDispatcher.register(function(payload) {
switch (payload.actionType) {
case Constants.GOT_USER_DATA:
...(handle UserStore response)...
break;
...
}
});
...
InstanceStore.dispatchToken = AppDispatcher.register(function(payload) {
switch (payload.actionType) {
case Constants.GOT_USER_DATA:
AppDispatcher.waitFor([UserStore.dispatchToken]);
...(handle InstanceStore response)...
break;
...
}
});
Option 1 seems the best choice conceptually to me. There are 2 separate API calls, so you have 2 sets of events.
It's a lot of events in a small amount of code, but Flux relies always using the simple, standard Action->Store->View approach. Once you do something clever (like option 2), you've changed that. If other devs can no longer safely assume that any Action flow works the exact same as every other one, you've lost a big benefit of Flux.
It won't be the shortest approach in code though. MartyJS looks like it will be a little neater than Facebook's own Flux library at least!
A different option; if logins must always refresh the InstanceStore, why not have the login API call include all of the InstanceStore data as well?
(And taking it further; why have 2 separate stores? They seem very strongly coupled either way, and there's no reason you couldn't still make calls to the InstanceStore API without re-calling login anyway)
I usually use promises to resolve such situation.
For example:
// UserAction.js
var Marty = require( 'marty' );
var Constants = require( '../constants/UserConstants' );
var vow = require( 'vow' );
module.exports = Marty.createActionCreators({
...
handleFormEvent: function ( path, e ) {
var dfd = vow.defer();
var prom = dfd.promise();
this.dispatch( Constants.CHANGE_USER, dfd, prom );
}
});
// UserStore.js
var Marty = require( 'marty' );
var Constants = require( '../constants/UserConstants' );
module.exports = Marty.createStore({
id: 'UserStore',
handlers: {
changeUser : UserConstants.CHANGE_USER
},
changeUser: function ( dfd, __ ) {
$.ajax( /* fetch new user */ )
.then(function ( resp ) {
/* do what you need */
dfd.resolve( resp );
});
}
});
// InstanceStore.js
var Marty = require( 'marty' );
var UserConstants = require( '../constants/UserConstants' );
module.exports = Marty.createStore({
id: 'InstanceStore',
handlers: {
changeInstanceByUser : UserConstants.CHANGE_USER
},
changeInstanceByUser: function ( __, prom ) {
prom.then(function ( userData ) {
/* OK, user now is switched */
$.ajax( /* fetch new instance */ )
.then(function ( resp ) { ... });
}
});
Related
i thought i got the hang of dexie, but now i'm flabbergasted:
two tables, each with a handful of records. Komps & Bretts
output all Bretts
rdb.Bretts.each(brett => {
console.log(brett);
})
output all Komps
rdb.Komps.each(komp=> {
console.log(komp);
})
BUT: this only outputs the Bretts, for some weird reason, Komps is empty
rdb.Bretts.each(brett => {
console.log(brett);
rdb.Komps.each(komp=> {
console.log(komp);
})
})
i've tried all kinds of combinations with async/await, then() etc, the inner loop cannot find any data in the inner table, whatever table i want to something with.
2nd example. This Works:
await rdb.Komps.get(163);
This produces an error ("Failed to execute 'objectStore' on 'IDBTransaction…ction': The specified object store was not found.")
rdb.Bretts.each(async brett => {
await rdb.Komps.get(163);
})
Is there some kind of locking going on? something that can be disabled?
Thank you!
Calling rdb.Bretts.each() will implicitly launch a readOnly transaction limited to 'Bretts' only. This means that within the callback you can only reach that table. And that's the reason why it doesn't find the Comps table at that point. To get access to the Comps table from within the each callback, you would need to include it in an explicit transaction block:
rdb.transaction('r', 'Komps', 'Bretts', () => {
rdb.Bretts.each(brett => {
console.log(brett);
rdb.Komps.each(komp=> {
console.log(komp);
});
});
});
However, each() does not respect promises returned by the callback, so even this fix would not be something that I would recommend either - even if it would solve your problem. You could easlily get race conditions as you loose the control of the flow when launching new each() from an each callback.
I would recommend you to using toArray(), get(), bulkGet() and other methods than each() where possible. toArray() is also faster than each() as it can utilize faster IDB Api IDBObjectStore.getAll() and IDBIndex.getAll() when possible. And you don't nescessarily need to encapsulate the code in a transaction block (unless you really need that atomicy).
const komps = await rdb.Komps.toArray();
await Promise.all(
komps.map(
async komp => {
// Do some async call per komp:
const brett = await rdb.Bretts.get(163));
console.log("brett with id 163", brett);
}
)
);
Now this example is a bit silly as it does the exact same db.Bretts.get(163) for each komp it founds, but you could replace 163 with some dynamic value there.
Conclusion: There are two issues.
The implicit transaction of Dexie's operation and the callback to each() lives within that limited transaction (tied to one single table only) unless you surround the call with a bigger explicit transaction block.
Try avoid to start new async operation within the callback of Dexie's db.Table.each() as it does not expect promises to be returned from its callback. You can do it but it is better to stick with methods where you can keep control of the async flow.
I am working on a project using Parse where I need some information calculated for each user and updated when they update their account. I created a Cloud Code trigger that does what I need whenever a user account is updated, and that is working well. However, I have about two thousand accounts that are already created that I need to update as well. After hours of trying to get a Cloud Job to work, I decided to try to simplify it. I wrote the following job to simply count the user accounts. To reiterate; I'm not actually trying to count the users, there are much more efficient ways to do that, I am trying to verify that I can query and loop over the existing user accounts. (The option to useMasterKey is in there because I will need that later.)
Parse.Cloud.job("getUserStatistics", function(request, status) {
// Set up to modify user data
Parse.Cloud.useMasterKey();
// Query for all users
var query = new Parse.Query(Parse.User);
var counter = 0;
query.each(function(user) {
counter = counter+1;
}).then(function() {
// Set the job's success status
status.success("Counted all User Accounts.");
}, function(error) {
// Set the job's error status
status.error("Failed to Count User Accounts.");
});
console.log('Found '+counter+' users.');
});
When I run the code, I get:
I2015-07-09T17:29:10.880Z]Found 0 users.
I2015-07-09T17:29:12.863Z]v99: Ran job getUserStatistics with:
Input: "{}"
Result: Counted all User Accounts.
Even more baffling to me, if I add:
query.limit(10);
...the query itself actually fails! (I would expect it to count 10 users.)
That said, if there is a simpler way to trigger an update on all the users in a Parse application, I'd love to hear it!
The reference actually says that:
The query may not have any sort order, and may not use limit or skip.
https://parse.com/docs/js/api/symbols/Parse.Query.html#each
So forget about "query.limit(10)", that's not relevant here.
Anyways, by their example for a background job, it seems you might have forgotten to put return in your "each" function. Plus, you called console.log('Found '+counter+' users.'); out side of your asynchronous task, that makes sense why you get 0 results. maybe you try:
query.each(function(user) {
counter = counter+1;
// you'll want to save your changes for each user,
// therefore, you will need this
return user.save();
}).then(function() {
// Set the job's success status
status.success("Counted all User Accounts.");
// console.log inside the asynchronous scope
console.log('Found '+counter+' users.');
}, function(error) {
// Set the job's error status
status.error("Failed to Count User Accounts.");
});
You can check again Parse's example of writing this cloud job.
https://parse.com/docs/js/guide#cloud-code-advanced-writing-a-background-job
In form Journal Voucher (AR>Journal> PaymentJournal> clicking buttonLines). I want to create a new record from x++ code.
I have seen few methods in the form viz create(), initvalue(), ledgerJournalEngine_custPayment... etc which are called when we press ctrl+n . How we could use these methods through x++ code to create a record using standard functionality.
plz help.
Before you elaborated, I thought you were trying to create your own custom form extending the journal functionality. If you're just trying to create a tool, you can just create a new Settlement Using Cust Group button. In the clicked event, call your transaction marking form or whatever you do to get the transactions you want to use. Then put something like this in it:
void clicked()
{
;
element.lock();
super();
// Put your code here to call the open transaction editing code
// CREATE THIS CUSTOM METHOD on C\LedgerJournalEngine_CustPayment\settleTransCustGroup
ledgerJournalEngine.settleTransCustGroup(ledgerJournalTable);
ledgerJournalTrans_ds.active();
ledgerJournalTrans_ds.reread();
ledgerJournalTrans_ds.executeQuery();
//recalculate balances
ledgerJournalEngine.newJournalActive(ledgerJournalTable, true);
element.firstField();
element.unLock();
}
Then in the new method you created, which I named settleTransCustGroup, you can loop over your records in the testLedgerJournalSpecTrans modeling off of something similar to this (custom method created on the engine class):
void settleTransCustGroup(LedgerJournalTable _ledgerJournalTable)
{
LedgerJournalTrans ledgerJournalTrans;
;
// Turn this stuff into a loop and default whatever else you need
ledgerJournalTrans.clear();
ledgerJournalTrans.initValue();
ledgerJournalTrans.AccountNum = '100003';
ledgerJournalTrans.AmountCurCredit = 10;
this.initValue(ledgerJournalTrans);
ledgerJournalTrans.insert();
this.write(ledgerJournalTrans);
ledgerJournalTrans.clear();
ledgerJournalTrans.initValue();
ledgerJournalTrans.AccountNum = '100005';
ledgerJournalTrans.AmountCurCredit = 15;
this.initValue(ledgerJournalTrans);
ledgerJournalTrans.insert();
this.write(ledgerJournalTrans);
}
Generally, your X++ code would look something like this:
static void InsertRecord(Args _args)
{
LedgerJournalTrans ledgerJournalTrans;
;
ledgerJournalTrans.AccountNum = "10000";
ledgerJournalTrans.AmountCurCredit = 50.64;
ledgerJournalTrans.AccountType = LedgerJournalACType::Ledger;
ledgerJournalTrans.insert();
}
You can replace the fields and values as needed. If any fields are missing, the error will display in the infolog (for example, if you were to run the above, you will get a "Currency code must be specified" error), so be sure all required fields are addressed.
In most cases, you can also call ledgerJournalTrans.initValue(); before assigning your values to pre-populate the record with default AX values. I believe this will be the same as what you see when you use Ctrl + N on the form. In the above example, doing so will cause the Currency Code to be filled in, and the record to be saved correctly (at least on our system).
There is no magical way of calling standard funcionality out of the frameworks quoted here on other comments. For each Ledger Type (Accounting, Inventory, Orders, Payments, ...), the way of creating and initializing lines is different and you have to work on this specific way if you want the journal to post properly.
There are a lot of examples on google of X++ code that inserts journal transactions for almost every type of them. It's not easy, but at least it's always almost the same code and it can be easilly reused.
I am using the FullCalendar jQuery plugin: http://arshaw.com/fullcalendar/
I am also using the example where you can drag external events onto the calendar: http://arshaw.com/js/fullcalendar-1.5.2/demos/external-dragging.html
Right now, I have an event click function as follows:
eventClick: function(event) {
$.ajax({
type: "POST",
url: "ajax-schedule.php",
data: 'id=' + event.id + '&start=' + event.start + '&end=' + event.end,
success: function(data){
alert('done!');
}
});
}
This posts to a file "ajax-schedule.php" where the data is inserted into the mysql database.
I would like to create a link that when clicked will take all of the new/changed events and post the data as shown above, instead of one-by-one.
Something like:
Update Schedule
The "updateSchedule" function would then post all the data.
Looks like the solution may involve the "clientEvents" method: http://arshaw.com/fullcalendar/docs/event_data/clientEvents/
... but I'm sort of lost here.
Any ideas as to how to do this?
You can create an array to store all the events:
var arrayOfEvents = [];
$('#calendar').fullCalendar({
...
drop: function(date) {
...
// retrieve the dropped element's stored Event Object
var originalEventObject = $(this).data('eventObject');
// we need to copy it, so that multiple events don't have a reference to the same object
var copiedEventObject = $.extend({}, originalEventObject);
// Push the event into the array
arrayOfEvents.push(copiedEventObject);
...
},
...
)};
function updateSchedule()
{
var data = "numOfEvents=" + arrayOfEvents.length;
// You can get all events out of the array here
for (var i = 0 ; i < arrayOfEvents.length ; i++) {
var event = arrayOfEvents[i];
data += "&id" + i + "=" + event.id
+ "&start" + i + "=" + event.start
+ "&end" + i + "=" + event.end;
}
// Make your ajax post here
$.ajax({
type: "POST",
url: "ajax-schedule.php",
data: data,
success: function(response){
alert('done!');
}
});
}
So on server-side, your code can get "numOfEvents" and just run a for loop from 0 to numOfEvents to get all events out.
This is something I am planning to implement in future when I get to tweaking performance of my project. My general idea would be something like this:
create handler that stores every change made in fullcalendar, so new events, events updates (drag&drop, resize, title/description/color/whatever is needed), event deletions. I guess the best way would be to create "class" that will be part of fullcalendar itself, tweakable by options of cource, if it wont be part of fc you would need to call it in every state changing function.
This handler stores array of events as well as it provides some basic methods to add fc changes into queue. My idea is to make it event-based, so in array there is member defined by event id which has information about every update made on this event. The way I imagine this to work is not exactly like every event has its own array of updates which server will run sequentially. I think of making this in way, that handler will be set to be saving data every 15/30... seconds (will be set by user) or on user call (pressing button for example). In time between two saves, queue will be populated in way where all updates will be merged into one global change (for example, if you move one event in calendar 5 times, resize 3 times and change title 5 times but at the end its gonna be the very same as it was at the last save, there will be nothing send to server for saving because in reality, no change was made. Or if you do the same and then delete event, its senseless to save all changes and then delete event, instead of that handler will send only delete command as this command is not affected by any other previously done. But if you move event for example two days in future and then 1 day back, it will calculate it was actually moved only by one day forward so there wont be any unnecessary data posted to server).
Eventhought it would be the best to implement it directly to fullCalendar plugin, it also can be standalone class/plugin which could be associated with any kind of application which makes a lot of changes on some set of datas and requires communication to be highly efficient to maximize speed (so user wont be bothered by slow updates/saves). It can be tweaked even more by recognizing exactly which fields (I use fc basically as google calendar, I can change color, desription, title and many more fields, but It would be useless to send whole event as it is if for example only title is changed, no need to send fields that remained the same) in event had been updated and send only those, so there will absolutely no redundant data sent to server. I guess I would do this as every event would have its member in queue array (as I said before) and when new member for event is added to queue, it will store also current event data (which are for comparison only, wont be send to server) for further comparison with next updates (if there will be any).
Hope you didnt get lost and catch my drift. This is just my idea for usefull feature, but I dont see myself working on it this year, depends on school/job. Its not that hard to make it actually, at least not in way I imagine it to be, so there may be someone else who will do it before I even start :)
My main question here is dealing with the pramas map when having a one-to-many relationship managed within one dynamic form, as well as best practices for dealing with one-to-many when editing/updating a domain object through the dynamic form. The inputs for my questions are as follows.
I have managed to hack away a form that allows me to create the domain objects shown below in one Dynamic form, since there is no point in having a separate form for creating phone numbers and then assigning them to a contact, it makes sense to just create everything in one form in my application. I managed to implement something similar to what I have asked in my Previous Question (thanks for the people who helped out)
class Contact{
String firstName
String lastName
// ....
// some other properties
// ...
static hasMany = [phones:Phone]
static mapping = {
phones sort:"index", cascade: "all-delete-orphan"
}
}
class Phone{
int index
String number
String type
Contact contact
static belongsTo = [contact:Contact]
}
I basically managed to get the values from the 'params' map and parse them on my own and create the domain object and association manually. I.e. i did not use the same logic that is used in the default scaffolding, i.e.
Contact c = new Contact(params)
etc...., i just looped through all the params and hand crafted my domain objects and saved them and everything works out fine.
My controller has code blocks that look like this (this is stripped down, just to show a point)
//create the contact by handpicking params values
def cntct = new Contact()
cntct.firstName = params.firstName
cntct.lastName = params.lastName
//etc...
//get array of values for number,type
def numbers = params['phone.number']
def types = params['phone.type']
//loop through one of the arrays and create the phones
numbers.eachWithIndex(){ num, i ->
//create the phone domain object from
def phone = new Phone()
phone.number = num
phone.type = types[i]
phone.index = i
cntct.addToPhones(phone)
}
//save
My questions are as follows:
What is the best practice of handeling such a situation, would using Command objects work in this case, if yes where can i found more info about this, all the examples I have found during my search deal with one-to-one relationships, I couldn't find an example for one-to-many?
What is the best way to deal with the relatiohsips of the phones in this case, in terms of add/removing phones when editing the contact object. I mean the creation logic is simple since I have to always create new phones on save, but when dealing with updating a contact, the user might have removed a phone and/or editing an exiting one and/or added some new phones. Right now what I do is just delete all the phones a contact has and re-create them according to what was posted by the form, but I feel that's not the best way to do it, I also don't think looping over the existing ones and comparing with the posted values and doing a manual diff is the best way to do it either, is there a best practice on how to deal with this?
Thanks, hopefully the questions are clear.
[edit] Just for more information, phone information can be added and deleted dynamically using javascript (jquery) within the form [/edit]
disclaimer: i do not know if the following approach works when using grails. Let me know later.
See better way for dynamic forms. The author says:
To add LineItems I have some js that calculates the new index and adds that to the DOM. When deleting a LineItem i have to renumber all the indexes and it is what i would like to avoid
So what i do
I have a variable which stores the next index
var nextIndex = 0;
When the page is loaded, i perform a JavaScript function which calculates how many child The collection has and configure nextIndex variable. You can use JQuery or YUI, feel free.
Adding a child statically
I create a variable which store the template (Notice {index})
var child = "<div>"
+= "<div>"
+= "<label>Name</label>"
+= "<input type="text" name=\"childList[{index}].name\"/>"
+= "</div>"
+= "</div>"
When the user click on the Add child button, i replace {index} - by using regex - by the value stored in the nextIndex variable and increment by one. Then i add to the DOM
See also Add and Remove HTML elements dynamically with Javascript
Adding a child dinamically
Here you can see The Paolo Bergantino solution
By removing
But i think it is the issue grow up when deleting. No matter how many child you remove, does not touch on the nextIndex variable. See here
/**
* var nextIndex = 3;
*/
<input type="text" name="childList[0].name"/>
<input type="text" name="childList[1].name"/> // It will be removed
<input type="text" name="childList[2].name"/>
Suppose i remove childList1 What i do ??? Should i renumber all the indexes ???
On the server side i use AutoPopulatingList. Because childList1 has been removed, AutoPopulatingList handles it as null. So on the initialization i do
List<Child> childList = new AutoPopulatingList(new ElementFactory() {
public Object createElement(int index) throws ElementInstantiationException {
/**
* remove any null value added
*/
childList.removeAll(Collections.singletonList(null));
return new Child();
}
});
This way, my collection just contains two child (without any null value) and i do not need to renumber all the indexes on the client side
About adding/removing you can see this link where i show a scenario wich can gives you some insight.
See also Grails UI plugin
Thanks,
Your answer brought some insight for me to do a wider search and I actually found a great post that covers all the inputs in my question. This is just a reference for anyone reading this. I will write a blog entry on how I implemented my case soon, but this link should provide a good source of ino with a working exmaple.
http://www.2paths.com/2009/10/01/one-to-many-relationships-in-grails-forms/
Most of the time I use ajax to manage such problem.
So when the user clicks add new phone I get the template UI from the server for manageability purpose ( the UI just same GSP template that I use to edit, update the phone), so this way you are not mixing your UI with your js code, whenever you want to change the UI you have to deal only with our GSP code.
Then after getting the UI I add it to the page using jquery DOM manipulation. Then after filling the form when they hit add(save) the request is sent to the server via ajax and is persisted immediately.
When the user clicks edit phone the same UI template is loaded from the server filled with existing phone data, then clicking update will update the corresponding phone immediately via ajax, and same thing applies to delete operation.
But one day I got an additional scenario for the use case that says, "until I say save contact no phone shall be saved on the backend, also after adding phones to the contact on the ui if navigate away to another page and come back later to the contact page the phones I added before must be still there." ugh..
To do this I started using the Session, so the above operations I explained will act on the phone list object I stored on the session instead of the DB. This is simple perform all the operation on the phonesInSession but finally dont forget to do this(delete update):
phonesToBeDeleted = phonesInDB - phonesInSession
phonesToBeDeleted.each{
contact.removeFromPhones(it)
it.delete()
}
I know I dont have to put a lot of data in session but this is the only solution I got for my scenario.
If someone has got similar problem/solution please leave a comment.
First, in all your input fields names you add an #:
<input type="text" name="references[#].name"/>
Second, add call a function before submitting:
<g:form action="save" onsubmit="replaceAllWildCardsWithConsecutiveNumbers();">
Third, this is the code for the function that you call before submitting the form:
function replaceAllWildCardsWithConsecutiveNumbers(){
var inputs = $('form').find("[name*='#']");
var names = $.map(inputs, function(el) { return el.name });
var uniqueNames = unique(names);
for (index in uniqueNames) {
var uniqueName = uniqueNames[index];
replaceWildCardsWithConsecutiveNumbers("input", uniqueName);
replaceWildCardsWithConsecutiveNumbers("select", uniqueName);
}
}
function unique(array){
return array.filter(function(el, index, arr) {
return index === arr.indexOf(el);
});
}
function replaceWildCardsWithConsecutiveNumbers(inputName, name){
counter = 0;
$(inputName + "[name='" + name + "']").each(function (i, el) {
var curName = $(this).attr('name');
var newName = curName.replace("#", counter);
$(this).attr('name', newName);
counter += 1;
});
}
Basically, what the code for replaceAllWildCardsWithConsecutiveNumbers() does, is to create a list for all input (or select) elements whose name contains an #. Removes the duplicates. And then iterates over them replacing the # with a number.
This works great if you have a table and you are submitting the values to a command object's list when creating a domain class for the first time. If you are updating I guess you'll have to change the value of counter to something higher.
I hope this helps someone else since I was stuck on this issue for a while myself.