I made some classes that represents my messages logic:
Message - representation of THE message :)
MessageBoxBase - base class for all 3 kind of messagebox
MessageInbox - representing inbox
MessageOutbox - representing outbox
MessageCustombox - user defined message box
MessageBoxItem - message item in any messagebox with such data as IsReaded etc.
MessageBoxCollection - Collection of messageboxes - Inbox, Outbox and List of CustomBoxes - only that 3 properties.
Finally in my agregate root User have MessageboxCollection, and I can use it somewhat like that:
myUser.MessageBoxes.Inbox.Add(...)
myUser.MessageBoxes.Outbox.Items....
I dont have any DB structure right now and I'm open on sugestion, but I was thinking about something like that:
MessageInInbox - UserId,MessageId, IsReaded etc.
MessageInOutBox - Same as in Inbox
MessageInCustomBox - UserId,MessageId, CustomBoxId and so on
CustomBox - BoxId, UserId, BoxName etc.
Message - plain message row, subject, content, author etc.
One I'm sure is that I don't want to create in DB row for each Inbox/Outbox for each user like it is in CustomBox case (something like unnecessary dictionary for inboxes and outboxes per user).
And in that point I have a problem - how the hell to map that ? :)
Have any suggestions? Maybe my domain is crappy? I'm waiting for yours response :)
There is a more simple solution that is that you only have two database tables called messages and boxes.
Messages - (Id, IsRead, Subject, Message, Sender, UserId, BoxId)
Boxes - (Id, Name, UserId)
This solution now allows a user to have several custom boxes and he should always have the defaults created for him. And the Object model can be User has a list of Boxes and each box has a list of messages.
Related
I'm developing an API in Rails in which exists users and messages tables. Also users have a gender (gender_id), belong to a country (country_id) and also have a civil status (civil_status_id) and the messages are created by admins.
So up to here I have this model.
Now I have to develop the following requirement
An admin should be able to create a message targeted to users depending on its attributes (country, gender or civil status). Also, the admin should be able to declare a message as a global message, in this case "all" users should receive it, but exceptions should also be allowed. For example, in the case where an admin want to send a message to users from all countries, except people from Russia and China.
The thing is I'm no Rails/SQL expert, but I want to make this efficiently so that if tomorrow the app has ten thousand or a hundred thousand users the server responds quickly.
So I was thinking the following
First create 3 many-to-many relationships (countries_messages, genders_messages and civil_statuses_messages). The record of these tables represent the relations between the messages and the countries, civil_statuses and genders.
Then create a form where an admin can create a message, where by means of several select boxes, he should be able to choose the attributes of the users to whom he wants to reach. The form for creating a message should also have a checkbox to determine if the message is global, if its marked then I would consider that the selected countries, genders and civil statuses would be the categories that the administrator wants to exclude, i.e. if an admin want to send a message to all the people in the system except for people who are from Canada he should mark the global option and select the country Canada in the select box (obviously this would be stated in the view).
Now up to here I have this model.
In what I do have doubts is which way is more efficient to return the messages that corresponds to a user.
Method 1
When an admin specifies that a message is global, except for those from country with id 3 then I could add to countries_messages records like (country_id: 1, message_id: 2), (country_id: 2, message_id: 2), (country_id: 4, message_id: 2), ..., etc. i.e. forming a relation with every country except the country with id 2.
Then retriveng the messages that the current user should read like the following:
global_messages = Message.where(global: true).ids
country_messages = current_user.country.messages.ids
gender_messages = current_user.gender.messages.ids
civil_status_messages = current_user.current_status.messages.ids
#messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages)
Method 2
Other way could be forming a relation of that message with the excluded country, i.e. if I make a message exclusively for people from country with id 2 then I should add the record (country_id: 2, message_id: 2) in countries_messages, but in the contrary case if I made a message to every country except the country with id 2 then I should also add the record (country_id: 2, message_id: 2) to countries_messages.
In this case I can know if a message is excluded for males and people from Argentina, for example, if the message is global AND it's associated with the country and gender record that represents Argentina and males.
Then the retriveng of the messages that the current user should read would be like this:
global_messages = Message.where(global: true).ids
country_messages = current_user.country.messages
gender_messages = current_user.gender.messages
civil_status_messages = current_user.current_status.messages
excluded_country_messages_ids = country_messages.where(global: true).ids
excluded_gender_messages_ids = gender_messages.where(global: true).ids
excluded_civil_status_messages_ids = civil_status_messages.where(global: true).ids
#messages = Message.find(global_messages + country_messages + gender_messages + civil_status_messages - excluded_country_messages_ids - excluded_gender_messages_ids - excluded_civil_status_messages_ids)
There could be more ways to do the same, so I want to receive recommendations or if you see that I could make improvements to do the same then tell me. If there is something you do not understand ask.
Depending on your database choice, you may want to consider storing the message "attributes" (country, gender, ...) in a jsonb column on your messages table. It could also include a user_ids attribute to simplify things. The queries might look a little funny, but you can move a lot into scopes to clear things up in your code and even add indexes to speed things up.
Here is a great article on using jsonb with indexes in Rails with postgresql.
Another alternative you could do is make a UserMessage join table with a polymorphic reference that could associate the different attributes to a message and user:
class UserMessage < ApplicationRecord
belongs_to :user
belongs_to :message
belongs_to :messageable_type # e.g. "Country"
belongs_to :messageable_id # e.g. some Country id
end
I'm new in OOP and I just started learning it. Its too complicated to determine the functionality of classes. Let's take an example:
We have an Address-book and an user want to add a new contact to it.
In this scenario we have 2 classes:
User: that determine the user that logged in.
Contact: A contact object that consists of Name, Address, Phone Number, etc
And the questions:
Who have to save a new contact?User class or Contact Class
If we try to check the user's permission before doing anything where is the best place for it?
Is it OK that these classes have a access to database?(Is it better to create 3rd class for doing query stuffs?)
Thanks for any good idea ;)
Usable distribution of "responsibility" is an OOP design and architecture decision with no single simple correct answer. For discussion refer to Stack Overflow question What is the single most influential book every programmer should read?
You'll learn the pros/cons by coding (using someone's design or creating your own design which does not work well).
However there are some useful/frequent distributions of responsibility already known as http://en.wikipedia.org/wiki/Software_design_pattern
In my opinion the only fixed fact is that each class/function/structure should have its responsibility clearly defined/documented - since the very first lines of code - and "do one thing and do it well"
Contacts are user specific. Thus every user object (class instance) should contain its own contacts object which is a container of contact (other user) objects, comprising in turn of name, address, phone etc.
class User {
String name;
String phone;
String address;
Contacts contacts;
....
}
class Contacts {
List<User> items;
}
The Contacts class should have the implementation of saving a new contact, which needs to be called from a User method, something like the following.
User u;
Contacts c = u.getContacts();
c.addContact(name, address, phone);
User's permissions should be checked in the User class.
The methods of these classes should interface with the database. For this each class method can open a new connection to a database and execute SQL queries. Example method of User cass:
User getContact(String name) {
Connection conn = getConnection();
....
PreparedStatement ps = con.prepareStatement("select * from Contacts where name = ?");
...
return userRcd;
}
1) Save new contact must the separate class, which working directly with database
2) Best place to check user permission - in user class of course
3) See the item 1:)
I recommend you get strong knowledge about SOLID principles, it's basics for good design.
This is more of a design pattern / document design question than a technical one...
I want to display a activity feed on my website which will list all the latest happenings users have been doing on my site...here are some of the activities i would like to display:
New media uploaded (Bob has uploaded a new track)
Comments on a profile (Paul has commented on Bob's profile)
Comments on media (Steve has commented on Paul's track 'my track name')
Status updates (Steve can write any status update he wishes)
Each activity will need to have it's own set of data, such as the new media uploaded activity I would like to include details about the media such as image, title, description etc).
This activity will mostly be used as a global feed so it's the same for all users, although I need the option for users to only show feed items from users they are following (like twitter).
I think I have 2 options:
1) Pull in all the data Ad-Hoc with an index so the information is always up to date, even if a user alters his media title name...i'm not sure how well this will scale though??
2) Have an ActivityFeed document which contains a Sub-Document such as NewMediaUploadActivity (shown below).
ActivityFeed
- DateTime
- AccountId
- ActivityType
- Activity (this is a polymorphic object)
NewMediaUploadActivity : Activity
- MediaTitle
- MediaDescription
- GenreName
StatusUpdateActivity : Activity
- StatusText
ProfileCommentActivity : Activity
- CommentText
- ProfileAccountId
- ProfileUsername
Etc...
If anybody has any experience, or any input on the best way to do this in RavenDB I would be grateful, my live website built with SQL Server currently does what I need using a slightly modified option 2.
Paul
I would model this as:
public class ActivityTracking<TActivity>
{
public string[] AffectedUsers {get;set;}
public TActivity Activity {get;set;}
}
You can have different activities (not required to be in an inheritance hierarchy) that are "attached" to different users.
For example, Bob commenting on Jane's photo would show up in both streams.
You then can just query for activities for that user.
I'm working on implementing a class for managing user permissions on my website.
For example: employees can view customer records but nothing else, employers can view customers as well as manage employees, and admins can do both those things as well as manage employers.
So far, what I've got is this:
I've stored a list of permissions, e.g addCustomer, delCustomer, etc. Each permission is linked to a list of the user roles which are allowed to do that action.
I've got a simple permissions class built. I'm using it something like this:
if ($permissions->can('addCustomer'))
echo " Add Customer ";
else
echo 'Not allowed to add customers';
However the tricky part is that in some places, I need to be more specific. For example: a customer has got the permission: readMsgs which allows him to read the messages between himself and an employee. However, if he has that permission, then he can simply change the url from:
site.com/messages/read/100
to
site.com/messages/read/101
And read message # 101 as well, which might be between another customer and employee. A customer shouldn't be able to read anyone's messages except himself.
Similarly, a customer has got the editCustomer permission, which allows him to edit his own profile by going to:
site.com/customers/99
(where 99 is his customer id)
But if he goes to
site.com/customers/100
He should not be allowed to access that page.
How can I solve this problem? Ideally I'd like to be able to pass on an id to the permissions class. E.g:
if (! $permissions->can('readMsg', $msgId))
echo 'not allowed';
if (! $permissions->can('editCustomer', $requestedCustomerId))
echo 'not allowed';
Any ideas how I'd have to restructure my class structure to allow the above kind of thing?
I would be more granular in my taxonomy of permissions (e.g., "readOwnMsgs" vs. "readAnyMsg"). This would elaborate your permission-checking code (e.g., site.com/messages/read/### goes something along the lines of "proceed if canReadAnyMsg or if canReadOwnMsg and message author is current user"), suggesting that this logic should be encapsulated in separate classes broken down by resource type or whatever other circumstances might have an effect on contextual information required to make such decisions.
I would have a message class with a canRead(User) function. This would check the user's permissions and say "Oh, I'm a message from a manager to an employee. Unless the user is the reciepient of the message, they can't read it." or just as easily "I'm a message from a manager to an employee. The user is a manager, so he can read it."
I'm typing it out in English because I suck a php (which appears to be the language of choice.)
I'm trying to get the recipient addresses within an IPM.DistList that is stored in a public folder (of type contacts) in Exchange 2003.
The typeName of the object is a Message (with a parent object being a Messages collection) and the messageType is "IPM.DistList".
I can find documentation about IPM.DistListItems. DistListItems documentation lists no parent possibilities in MSDN.
We have an Exchange 2003 info store with Public Folders. Within those Public Folders is a [sub]folder (that holds items of type "Contact") that has distribution lists (IPM.DistList's) that have contact entries, members of the list essentially.
I need to get the addresses of the members of the lists in the Public Folder sub-folder.
Well, it's been over a year, but I feel some obligation to answer this question now that I've found it. The answer was, I think, that no documentation exists on this secret bit of Exchange, but was able to iterate through the list of addresses within each ipm.distlist by something like this:
for a = 0 to list.count-1
emladdress = list(a)(a).value
next
I don't know why "(a)(a)" works, but you have to have both of them there. And I don't actually remember if it was a zero-based index, so that's a guess. Good luck, and hopefully you can migrate your users off Exchange and into google apps. Seriously!