The way to implement User Email Preferences? - ruby-on-rails

I want to implement a feature which lets every user decide the kind of emails he/she will receive. So far, I can only see the user receiving emails when he/she receives a friendship request and when he/she receives a new message. The way I plan to implement this is as follows:
Each User has_one EmailPreference
EmailPreferences table will have 2 columns: Friendship (Boolean) and Message (Boolean).
By default, they will be true. So the User will receive emails for both new messages and new requests received.
The user can go to the Edit action and update the values as per his choice.
I plan on using an if statement which will check if #user.emailpreference.message? or #user.emailpreference.friendship? before the send email method.
I'd like to know if this is the best way to go about it.

A couple considerations - I'd question whether you want to do the has_one or simply add the columns to the user. I also tend to use dates instead of booleans, so you can see when the boolean was set. For naming, consider something other than 'friendship' and 'message'. If it is an attribute on the user, I'd consider something like 'subscribed_to_friendships' and 'subscribed_to_messages'.
The reason I avoid has_one's in general is to make very simple queries and reduce the need for maintenance. It's likely you'll be getting all users that should receive a message and looping through them, I prefer to avoid the joins and keep it simple. I also don't really like how false and null are the same on the child. This will help you avoid deleting/adding preference records, especially if the default is true and you're going to create preferences for most users by default.

I see one issue in the approach is that if tomorrow you have more type as preference , means when somebody joins than also you want to send the email , in that case you have to add one more column. Why do not you normalize it further and use more table to store the Preference type
Id Name
1 Friendship
2 Message
Id User Id Flag
1 1 TRUE
2 1 False
It means user 1 is opted for Friendship but not for Message. Now you can easily add any new preference.

the approach by https://stackoverflow.com/users/177489/swards is for me , the best option because that has_one queries can be a mess later.
add columns to user model and gg!

Related

Rails | Handling Users / Admin / Call Center Panel

I have a rails app and within I have User model. I added admin:boolean column to user table and :default => false.
Now I would like to create a call center panel on the system to be able to handle user requests by phone etc. I am wondering should I create another table like user or is it ok to add a boolean field to user table.
I know I can handle it with adding column. I will add a namespace as call_center to controller, routes etc. but my question is, which option is the most effective and sustainable one?
The way I've seen this handled is exactly as you describe, with a boolean (is admin true) or with a number in cases where there are more than two user types. Wordpress, forum software, Mediawiki, etc. need to allow for several user types which have varying degrees of access.
This is typically done the way you've done it, by adding a column to the user table that holds this number. For example, admins could be 0, moderators 1, regular users 2, etc. The number doesn't matter as long as your system makes sense to you. With your boolean, you can easily check to see if a user is an admin or not, and thus enable the admin to do things other users cannot. In doing so, you simply have to set this column up so the default is false, so when new users sign up they are not put in as admins. In short, I don't think you need another table.

Ruby on Rails: Polymorphic/Object-agnostic conditions on Trigger setups?

*I'm not really sure what concept this problem would go under - would this be considered polymorphic associations?
I want to create a system where users can set up triggers so that after a certain event happens, another event happens.
For example, I want the user to be able to define a trigger action as:
"This [Email, Document] must be sent to all users after they [Sign up, read email A, sign document B]."
As you can see within the brackets "[]", the conditions can be tied to various objects and actions.
My thought was to create a model TriggerCondition and storing columns
:object_id, :assigned_to, :activated_when
but the object_id(Email, Document) can be different models.
Would adding a column :object_type that can be either email or document be the best solution? Or is there a more sophisticated way of designing so that I can pass in an object and it will automatically know what I'm referring to?
Regarding the :activated_when condition, I'm completely unsure how I would store and check for condition. Would I be able to use a syntax similar to "Email#marked_as_read(A)?"
I'm trying to use Rails Observers to trigger the action
http://api.rubyonrails.org/v3.2.13/classes/ActiveRecord/Observer.html
Rails is built to handle polymorphic associations just like this.

A few intermediate Rails3 Questions

I'm building an app called "CourseWork to dig into rails/develop my skills and I have a question about how to structure it. Users have a resource called "CourseGrading" that is able to create categories and belongs to "Course". Each "category" should have a name, a percentage out of 100 and a course_id. I need to add these percentages together and alert users if the total isn't 100 while still saving.
Then the user's generated "categories" should populate an enum_string specific to that user in a resource called "CourseAssignment" which has a name, description, category and finalgrade.
Can anyone give hints or resources for how best to accomplish this? Thanks
You probably want to take a look at Active Record Callbacks. These will allow you to insert some code to be run when creating/validating/updating/deleting models.
You should probably make use of the ActiveRecord validations.
Check out this guide that explains how to write your own custom validator. Your custom validator would run when the form gets submitted, and in it, you would grab the percentage params and do your check. If it's not what you expect, you can just add an error to the form and the validation process will just kick the user back to the form page and display the error.

Rails private message system

Hey,
I'm trying to implement a message system as used in social networks. The problem I'm facing is first about the database structure and second how to implement it in rails.
My first idea is I'm using 3 tables:
messages: id|subject|text|created_at
receivers: id|message_id|read:boolean
creators: id|message_id|read:boolean
now I'm wondering how to implement following features:
1.) a user can delete his message. but as both want to read the message, how to make sure the message is only deleted when both users have deleted it.
2.) how do I implement a reply? or actually how do I find the corresponding creator?
3.) how to find out whether a mail was read by the receiver?
another idea is:
creator_messages: id|creator_id|receiver_id|subject|text|read|created_at
receiver_messages: same as creator_messages
this distinguishes between the users, so they can delete individually their messages. but how do i find out, whether the mail was read or not?
my third approach was basicly my second but only one table messages and then displaying this to the user.
1. the message is deleted as soon as one of the user deletes it.
2. actually how do I represent the relationships as has_many and belongs to?
I thought it would work like this:
model User
:has_many :send_messages, :class_name=>"messages", :foreign_key=>"creator_id"
:has_many :received_messages, :class_name=>"messages", :foreign_key=>"receiver_id"
end
model Messages
belongs_to :user
end
but somehow I didn't get it to work. guess I'm missing something basic here.
Hope someone can help me =) thanks a lot
ok, if i understand it correctly the messages would have maximum of 1 receiver and 1 sender.
In that case i would do the following:
I would create just a messages model, this would have the extra fields
- receiver_read
- receiver_deleted
- sender_deleted
Now you can add hooks to the model like "after_save", "after_create" in here you can check if the receiver_read has just been set to true via for example with the receiver_read_changed? method, if this is true you can notify the sender or do something else with it.
With this after_save hook you can also check that if the sender_deleted is just set to true and the receiver_deleted is already true you delete the whole message.
When you have multiple receivers I would create a join model for the receivers and have the sender_deleted and sender_id in the message model.
In the join model i would add the columns receiver_id, read and deleted.
Now i would use the before_save method on the messages and the join models to check if the message needs to be deleted or if the sender has to be notified of the message that has been read.
The solution might be:
1) I would create a deleted(_at) flag in the receivers table as well, if you really want to hard-remove the messages from the database if all of the receivers deleted it you could setup a cronjob or something.
2) have a creator_id in the messages model instead of a creators table, i mean how can multiple people create the same message?
3) I don't really get this one, i guess you set the "read" flag on the receivers table to "true" when that user opens up the message, after this you can make a scope in the users model like "scope :read, where(:read, true)" and also a scope unread.
I hope this is what you mean.

Ruby on Rails - Optional Associations?

I would like to allow users to write comments on a site. If they are registered users their username is displayed with the comment, otherwise allow them to type in a name which is displayed instead.
I was going to create a default anonymous user in the database and link every non-registered comment to that user. Would there be a better way to do it?
Any advice appreciated.
Thanks.
The problem with creating an anonymous user is then you need to check if a comment was made by a "real" user, or an anonymous one when displaying the name, so that introduces complexity. Plus, if you have a way of viewing their profile page, which may include posting history, you'd need to exclude the anonymous user with an exception.
Generally it's better to have a column on your comments which represents the user's visible name, and just show that if provided, or the registered user's name otherwise. For instance, your view helper might look like this:
class Comment < ActiveRecord::Base
belongs_to :user
def user_name
self.anonymous_name or (self.user and self.user.name) or 'Anonymous'
end
end
This will display the contents of the anonymous_name field of the Comment record, or the user's name if a user is assigned, or 'Anonymous' as a last-ditch effort to show something.
Sometimes it's advantageous to actually de-normalize a lot of the database when dealing with large numbers of comments so you don't have to load in the user table via a join simply to display a name. Populating this field with the user's name, even if they're not anonymous, may help with this, though it does mean these values need to be updated when a username changes, presuming that's even possible.
I think you can make user_id on your comment model nullable since you want to allow non registered users to add comments as well. As far as adding names for the non registered users are concerned, there are two options for that
option 1. Add a column on Comment model and name it like anonymous_user where you will store names of non registered users
option 2. Create a another model AnonymousCommentor with name and comment_id attributes.
If you are going to use anonymous users for other things as well apart from comment in your application then you can make it polymorphic and use a suitable name like AnonymousUser instead of AnonymousCommentor

Resources