Best way to use BLoC as global state management - flutter

So I have a BLoC which I need to access globally through my app - CurrentUserBloc and its purpose is to hold data of currently logged in user. It can hold some states like CurrentUserWaiting, CurrentUserReady, CurrentUserError etc. Some of them hold user instance - like CurrentUserReady, and some don't - like CurrentUserWaiting. Now I need to access this user data in order to send an event to another BLoC. For example I want to post a photo and I need userId of currently logged in user to do this. But I can't just use BlocProvider.of<CurrentUserCubit>(context).state.user to get user data because some of this bloc's states - like CurrentUserWaiting - don't store user property and compiler won't take this.
I get around it by creating abstract state class CurrentUserWithUserInstance and extending it in states that hold user property. Then I just access state like this:
final currentState = BlocProvider.of<CurrentUserCubit>(context).state
as CurrentUserWithUserInstance;
Then I get user property from this and use it to add event in another BLoC.
I was wondering what would be a better way to do this. I need to access user data in multiple places in the app and I don't know if this is a good approach. I know I could use just one state class with all properties and then change it by copyWith method. By that doesn't really seem that good to me.
How do you store and access global state using BLoC?

Related

Flutter: BloC inject mocks in app testing

I'm trying to create a flutter app using flutter_bloc, firebase auth and firestore.
I following flutter_firebase_login example which is truly amazing for all the testing coverage.
I would like to go one step further. Once the use is authenticated, I want to load the user profile from firestore, then actually display the app. (In practice, once the profile is loaded, I will have to do new firestore lookups that will depend on the profile info).
So I kind of have a chain of events:
Authenticate -> Load profile for user "uid" -> Load data depending on profile.
I'm wondering what is the good way to do that which still allows me to test my full app using mocks only.
The example injects the authenticationRepository into the App class then we can inject it in the test. My problem now is that, once the user is logged in and we redirect to the HomePage widget, this widget will have to create a new provider. But if it does create a new one, then I can't inject it anymore.
What is the good practice there? Here are the few options I've been considering:
Inject all the providers in the main()
I guess this would be the simplest solution. Though since those providers are kind of chained, I would have to pass the context data to every call on the "sub" providers, the context from the previous one. For instance:
ProfileRepository {
... getProfile(uid);
}
DataRepository {
... getData(... profile)
}
Dynamically build the providers
Ideally, I would like to not need those extra params in my providers and instead build my providers with those context values. Example:
ProfileRepository {
ProfileRepository(uid)...
... getProfile();
}
DataRepository {
DataRepository(profile)...
... getData()
}
So each time the uid changes, we would create a new provider for the profile and for each profile change we would create a new data provider.
This will simplify the calls in my app to not have to load the profile to get the data. The sub widgets just need to get the current provider and call the functions without the depending contexts.
Though just calling the constructor from my widgets would create problems for the tests DI which means I would have to create provider factories that I could then inject. And from the tests I would pass mock factories and in my main(), the prod factories.
Adding a state to my providers
I would inject all my factories in the main but instead of constructing them using the uid or the profile. Pseudo code:
ProfileRepository {
setUid(uid)...
... getProfile();
}
DataRepository {
setProfile(profile)...
... getData(... otherParams)
}
Each time the user changes or the profile changes, I just call the setters. That way I don't need to pass provider factories from the main.
Note
I considered to wrap the AuthenticationRepository into a UserProfileRepository which would remove one step here but for the data, this would not work.
I'm not sure what is the good practice here and would love to get feedback.
Thank you in advance!

Playframework(Scala): passing user model around

I wonder what's the best practise for passing user 'model' around. I take http request and convert it to user model in my controller. I don't want to explicitly add an argument to all the templates for this model, and neither to main.
What are the best practises for doing this?
THanks.
If you are logging in, and the user is your authenticated user, then you should put the user in a WrappedRequest and make your request implicit in your templates. If you use something like SecureSocial, then UserAwareAction will provide you with a RequestWithUser (see http://securesocial.ws/guide/user-service.html) and you can do things like
#()(implicit req:RequestWithUser)
Email = #{req.user.map(_.email)}
in your template.
Use the Session scope.
Here is documentation for Play 2.0
http://www.playframework.com/documentation/2.0.2/ScalaSessionFlash
So for example, on the login, add the user to the Session
And on logout remove the user from the Session
Cheers!

Where does related logic go on model creation when working with REST api with Django, Backbone, and Tastypie?

We are trying to move some of our app to use backbone and tastypie. I have the REST api set up and it is working on some basic examples. However, there are a few issues where currently we post an ajax request to a custom url, and in that view do a few things like
make related objects
call a few related functions
However, now that I've switched some of this functionality to using backbone and the REST api, I'm not sure where all of that should go!
For example, I had a view to make a Message, and when I made a Message, I also made a Notification and called a function to add some points to the user. Something like
def ajax_send_message(request):
## ... set up some variables ...
## Make the new message
message = Message(user=user, content=message)
message.save()
## Make the notification
notification = Notification(message=message)
notification.save()
## Give the user points
user.add_points_for_message();
return json_response({"status": "ok"})
Now--am I just supposed to do this all in JavaScript? I have a Message Backbone model as well.
// Create message backbone object
var msg = new Message({content:content, user: user});
// Post to server
msg.save();
// Add to backbone collection
messages.add(msg);
I've looked at different parts of tastypie, and it seems you can create custom URL endpoints, and also do validation, but that doesnt seem like the right spot to call related methods. It seems that calling related methods goes against the REST part of it---but then where are they supposed to go?
If I want to add some logic to backbone only when an object is created, where does that go?
The first thing I would suggest is to switch your mindset to an event-based model, where your code reacts to events. In your example above, you save the model to the server then immediately dd it to the collection. How do you even know that the model was saved correctly? That procedural style of programming works better in a synchronous, server-side style of programming.
In the asynchronous world of client-side programming, you make a request and then set up callbacks which determine what will happen next, depending on the events your are listening for. In your case, you want to react a certain way when the message is saved successfully, correct? You can define a success callback for your save operation like so:
msg.save({
success: function(model, response, options) {
messages.add(model);
// code to add notification
// code to add points
}
});
Basically, you are saying "I would like to save this model, and then listen for a success event. When the event comes in, execute the following code." Notice also that I am adding the model returned from the API to the collection, since this is the exact object that was persisted to the server so it's more appropriate to add than the model you created.

Web.api Get method to show only selected properties from entity

Let's say I have 3 entities: Advert, User and UserRole. And in Web.Api project GetAllAdverts method.
public IEnumerable<Advert> GetAllAdverts()
{
return repository.GetAll<Advert>();
}
When i enter url ../api/advert I get JSON with all Adverts and data about adverts, but I get all data about user and user role too.
How can I get for example all advert data and only UserName form entity User ?
Is this done by creating DTOs ?
Thanks in advance !
Using DTO's is usually a good idea. It is more work, but it gives you full control and it abstracts out peculiarities of a specific data layer.
In your case, if you really only want UserName you even have to use a DTO, because it is impossible to partly load the User as navigation property from Advert.
If it does not matter that you see all properties of User except its navigation properties (like role), you may also consider to (temporarily) turn off lazy loading for the context in the repository and eager load Advert.User by using Include.

how to set read only properties to the particular info path form control based on user logged in?

how to set read only properties to the particular info path form control based on user logged in?
Your best option (assuming you are using managed code) is to get the user name with either Application.User.UserName or HttpContext.Current.User.Identity and then call IsInRole (I believe it is a member of the WindowsPrincipal class).
Save the result into the value of a field and you can then use the standard conditional formatting to lock the fields you don't want the users changing. I also usually conditionally change the look of those readonly fields (grey background fill etc) so the users don't get confused and think they can edit.