Querying for parent object in Mongoid has_many relationship - mongoid

I have two objects
class User
...
has_many :roles
end
class Role
...
belongs_to :user
end
I can assign roles to users without a problem. However, I want to be able to query for all users that have a particular role. This should be incredibly simple. However, I seem to be incapable of getting results.
I would think something like this should work:
role = Role.first
u = User.first
u.roles << role
u.save
User.in(role_ids: role._id)
However, it returns nothing. The role is successfully assigned to the user, but I can't figure out how to query for all users with specific role. I know it has to be simple, but I am driving myself crazy trying to figure it out.

Nevermind. I should've been using has_and_belongs_to_many instead of "has_many" and "belongs_to" since many users can share a role. Indeed it was a very simple solution, I was just going about it all wrong. Once I changed the relationship to has_and_belongs_to_many, I can just say "role.users" to get a list of all users with that role.

You need use "many to many relationships" between "User" and "Role".
class User
include Mongoid::Document
has_and_belongs_to_many :roles
end
class Role
include Mongoid::Document
has_and_belongs_to_many :users
end
Then you can use "role.users" to get the user list. And if you have any questions, you can read mongoid document:
http://mongoid.org/en/mongoid/docs/relations.html#has_and_belongs_to_many .

Related

Django, relate User with another table

So I got the tables you can see in the image below:
.
What I would like to do is to create a relationship so that each user (of django auth_user) will be enrolled(or able to enrol) to exactly one "course" so that he will be able to see next events for his modules.
Do I have to create another table and place 2 foreign keys or this is a way to do it in 'php' and it's more simple with Django? I was suggested to create 'student' model inheriting from 'User' with extended behavior and one to many relationship on auth. I tried to do that but unfortunately had not results since I'm really new to Django & Python.
If every auth_user (or auth.User) will be or have the opportunity to be enrolled on a course I would create a 'user profile' model that has a 1-to-1 relationship with the django User model. You can store additional User data in this model, including what course they are enrolled on. See https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model for more details but here is an example:
class UserProfile(models.Model):
user = models.OneToOneField('auth.User')
course = models.ForeignKey('courseapp.Course', null=True)
You would probably need to create a signal that gets fired each time an auth.User object is saved, such that if it is the first time that User object has been saved, it automatically creates the UserProfile:
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from yourusersapp.models import UserProfile
def create_user_profile(sender, instance, created, **kwargs):
# Automatically creates a UserProfile on User creation.
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
When you query a User object, you can then reference the User object's profile like:
user_object.userprofile
You could then create a Course object and link the user_object indirectly via its UserProfile to that Course:
course = Course.objects.create(name='course_name', next_field='whatever')
user_profile = user_object.userprofile
userprofile.course = course
userprofile.save()
Now you have a user object with a UserProfile that is linked to only 1 course. Many users can be on the same course, but a user can only be on 1 course. You can also reference all users on a particular course like:
course = Course.objects.get(name='course_name')
course_users = course.userprofile_set.all()
HTH
I think that you can go about this one of two ways.
Extend the User model. 'Student' would probably be a good name for your new model. It would have a OneToOne relationship with 'User', and a ForeignKey relationship with 'Course'. It can store any other information that is applicable to students only. Documentation for how to do that can be found here https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#extending-the-existing-user-model
Create a custom User model that has a ForeignKey relationship with Course. This approach is a bit more complicated, but yields a slightly cleaner end result. Documentation for that is here. https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#substituting-a-custom-user-model
Sorry if it seems like I'm just sending you to the Django docs, but both of those sections are well written and should explain things pretty clearly. If you'd like to post another question with example code we can try and see why your original attempt at extending the User model didn't work. By the way, your "Student" model shouldn't have to inherit from the User model in order to extend it.

Django ownership foreign key to User or UserExtenstion

I'm quite new with Django, and so far I have a pretty basic setup where I attach an extra model to the default User model from (django.contrib.auth.models). In my accounts.models.py I have something in the line of:
class UserExtension(models.Model):
user = models.OneToOneField(User, primary_key=True)
# more code
I also have another model which needs to be specified an owner. My question is: Which is the better (more django-ish, more readable, more efficient, more flexible) way to signify the owner:
class Owned(models.Model):
# code
owner = models.ForeignKey(User)
# more code
or:
class Owned(models.Model)
# code
owner = models.ForeignKey(UserExtension)
# more code
I'll really appreciate if you mention pros and cons of those approaches.
I'd recommend the first option. The user model is the nontrivial model in the sense that an owned object should not be able to exist without a user, but could exist without a UserExtension.
Also consider that in Django 1.5 you are able to create custom user model, eliminating the need for the UserExtension class. See the documentation for more information.
Consider using UserProfile for any per user add-on information. Check out this blog to see how to do it. Then you can be assured that you are creating UserProfile object every time you create the User.
Now whether you FK on User or UserProfile depends logically on what you are doing within Owned. If Owned works with User's data/field, FK on User; if it works with UserProfile's data, FK on UserProfile.

Mongoid save fails silently without embedded_in relation

I have one document embedded in another in Mongoid.
class A < B
include Mongoid::Document
embeds_one :shipping_address, class_name: 'Address'
I have, in my case, omitted the inverse relation:
class Address
# embedded_in :A
Why is it, that although the API works fine and completely as expected:
address = A.address
address.zip = 1234
a.changed? #true
address.save
a.changed? #false
The document is not actually saved?
If i return the embedded_in statement, the save actually works fine.
My understanding of the Mongoid source is not the best so don't kick me too hard mods.
I assume that Mongoid is similar to ActiveRecord in this regard. With ActiveRecord, defining a :has_many does not change the parent object but includes methods for accessing the child. belongs_to on the other hand pulls methods for managing foreign keys.
Looking at the source code for Mongoid it seems that persistence is called from the embedded class to the parent and not the other way around (source). Removing the embedded_in would remove the additional methods for inserting the child into the parent.
Feel free to correct me if I am way off :)
While you can gain a lot when you choose to embed documents in MongoDB, you do give up the ability to query everything outside of the context of the parent. If you want to be able to work with Address documents independently, outside of the context of the parent document, you should link documents with has_many instead of embedding with embeds_many. This comes with it's own set of pros and cons.
If you choose to embed documents, you do specify embedded_in in the model and you access the embedded documents like this:
a = A.new # Parent document
a.addresses # Embedded Address documents
( Documentation Reference )

Rails 3 user activity history data

So this one has me a bit confused, and it may be unjustified but I would like some input regardless.
I have a rails 3.1.3 application with users who can view media files. I want to keep a history of their activities with regards to their media viewing. The goal is to be able to record a history such that I can track it from the user or from the media e.g. get data for user.history() and media.history() to show both all of the media accessed by a user and all of the users who accessed a particular piece of media, along with other data regarding each transaction.
So far the only way I have been able to come up with that reasonably satisfies this is to create a single history object for each transaction, sort of like this:
class history_item
belongs_to: media_object
belongs_to: user
(other transaction-specific data)
end
What concerns me about this is the number of database entries will quickly skyrocket with the typical use of this application. Is there a better way to approach this problem that I have not thought of? I am new to rails and large web application development in general, and I'm not entirely sure about how this sort of thing is normally done.
I would create such a model as a Viewing class as a HABTM model between User and MediaObject. This makes the actual structure more obvious than just having a relation called history. You can of course add methods for User#history and MediaObject#history as well, if you want that exact interface that you described.
class User
has_many :viewings
has_many :viewed_media_objects, :through => :viewings
end
class MediaObject
has_many :viewings
has_many :viewers, :through => :viewings
end
class Viewing
belongs_to :user
belongs_to :media_object
end
When querying these objects, for example given a user = User.first, if you know that you want to iterate over the user's viewed_media_objects in an action, you could use #user = User.include(:viewed_media_objects).find(params[:id]) to make sure rails fetches the related viewings and media objects at the same time as the user. This way, you won't get a whole bunch of database calls.

Elegant way to store anonymous users with nick names in django?

I have a simple Post model in my django app:
class Post(models.Model):
category = models.CharField(max_length=10, choices=choices)
message = models.CharField(max_length=500)
user = models.ForeignKey(User, editable=False)
I'd like to implement the feature of having anonymous users create posts with nick names. Unfortunately django doesn't allow you to save an instance of AnonymousUser as a foreignkey to the Post class.
I was thinking of adding a "dummy" user record into the db that represents the anonymous user(id=0, or some negative number if possible) that would be used for all posts without a user. And if it is present a nullable name field would be used to represent the nickname of the anonymous user.
This solution seems a bit hacky to me. Is there any cleaner more effecient solution?
If you can identify new users by some session information, you could just create normal user accounts, pro forma so to speak - with a flag to identify them as volatile (this may lead to some regular maintenance cleanup).
If, during session lifetime, the user actually want to register, you can reuse the user account on your side and the user can keep all his data on his.
As #slacy commented and #Dominique answered; instead of rolling your own take a look at existing projects, e.g. this:
http://www.stereoplex.com/blog/introducing-django-lazysignup
Not tested , but this can help:
https://github.com/danfairs/django-lazysignup
You can add blank=True and null=True to User ForeignKey and set it to None, if user is anonymous. You just need to store the nickname somewhere.
I am new to Django. A friend told me not to use ForeignKey further stating that using CharField is ok. ForeignKey is slower than CharField, as it has some check for user info.

Resources