How do I create two relations in one document - ruby

I am using mongomapper and I am saving association using the following method:
class Task
include MongoMapper::Document
key :user_id, ObjectId #also works without this line
belongs_to :user
def self.add(user)
a = self.new
a.user_id = user
a.save
end
And in the User model I have added: many :Tasks
Now, I would like to save two users (in the html form I select 2 users from the Users collection), without using the array, I want to save them separately:
class Task
include MongoMapper::Document
key :from_user_id, ObjectId # user1 links to the Users model
key :to_user_id, ObjectId # user2 links to the Users model
How od I do that?

MongoMapper has similar options as ActiveRecord when it comes to specifying keys and class names. You'd do something like:
class Task
include MongoMapper::Document
key :to_user_id, ObjectId
key :from_user_id, ObjectId
belongs_to :from_user, class_name: 'User', foreign_key: :from_user_id
belongs_to :to_user, class_name: 'User', foreign_key: :to_user_id
end

Related

Is there a difference between has_one on one model vs belongs_to on the other?

I understand that a belongs_to puts the foreign key on the declaring model, and a has_one puts it on the other model. Does that mean there is no difference in this example?
class Category
belongs_to :blog
end
class Blog
end
class Blog
has_one :category
end
class Category
end
The only thing I can see is that the second example's nomenclature makes a little more sense.
Yes.
belongs_to expects the foreign key to be on its table whereas has_one expects it to be on the other:
# here the Category table will need to have a blog_id field
class Category
belongs_to :blog
end
# the blog table won't need anything
class Blog
has_one :category
end
has_one under the hood is similar to has_many except it adds a LIMIT 1 clause to the sql statement when you query the table.
The difference lies in the database, as you've noted. The model with the belongs_to reference must contain the foreign key for the association. When using has_one, it will expect to find a foreign key on the associated model.

1 user model with student,tutor role + different profile for student, tutor?

How to correctly setup a User model with 2 roles, and have 2 separate profile models for each of the roles? Im confused on how to implement. Currently im using this but it fails:
models/user.rb
# id :integer ( only important columns noted to save space)
# profile_id :integer
# profile_type :string(255)
belongs_to :profile, :polymorphic => true
models/profile_student.rb:
# user_id :integer
has_one :user, as: :profile, dependent: :destroy
models/profile_tutor.rb:
# user_id :integer
has_one :user, as: :profile, dependent: :destroy
How to correctly get the profile for a user??
for example using devise.
#user = current_user.profile
I would try having two types of users: student and tutor. In order to do this, in your user table, have a column called type and put in a validation that ensures it is either student or tutor:
validates :type, :inclusion => {:in => ['student', 'tutor']}
Then create a Student model and a Tutor model. In rails, 'type' is a special kind of attribute in which rails will know that it is referring to other models. Then, in order to make profiles, you have two options. You can either say that both a student and a tutor has_one :profile, or you can separate the types of profiles.
For example, you can do:
class Student < User
has_one :profile
end
class Tutor < User
has_one :profile
end
If both profiles have similar types of information, that may work for you. However, if a tutor and student have considerably different profiles, try something like this:
class Student < User
has_one :student_profile
end
class Tutor < User
has_one :tutor_profile
end
and then create a separate model for each type of profile.
By using this 'type' column, you can make it so that students and tutors inherit all the methods and properties of users, but can also have their own distinct properties and methods.

User relation to group and company MongoMapper

I have need to create a system where a user can login with a user account where a user is a member of a group like admin or editor. Also a user is a member of a company. in both cases of groups and company's they can have multiple users but user can be only a member of one company and multiple groups.
The relations that i can get out of this is that a group has many users, company has many users, user has one company, user has many groups.
but my problem then how do i create this with ruby and mongoMapper? i have look at the documentation and other sources but did not find a good solution or explanation on how to use or set this up.
If anyone have a better way of doing it also welcome.
these are the current classes i have written.
class User
include MongoMapper::Document
key :username, String
key :password, String
key :name, String
belongs_to :group
belongs_to :company
end
class Group
include MongoMapper::Document
key :group_id, Integer
key :name, String
key :accesLevel, Integer
many :user
end
class Company
include MongoMapper::Document
key :name, String
many :user
end
After some more google searching i have found a solution.
first i made the user class look like this:
class User
include MongoMapper::Document
key :username, String
key :password, String
key :name, String
key :companyID
key :groupID
timestamps!
end
then the group and company class like this:
class Company
include MongoMapper::Document
key :name, String
timestamps!
end
class Group
include MongoMapper::Document
key :name, String
key :accesLevel, Integer
timestamps!
end
With these classes in place i changed my controller to first create a company and then a group these could also be loaded but for the ease of testing it was not necessary to do this so that i didn't need to write the code for this.
company = Company.new
company.name = "comp"
group = Group.new
group.name = "admin"
user = User.new
user.name = "user1"
user.username = "user1"
user.password = "passuser1"
user.groupID = group.id
user.companyID = company.id
db_config = YAML::load(File.open('./dbconfig.yml'))
MongoMapper.connection = Mongo::Connection.new(db_config['hostname'])
MongoMapper.database = db_config['name']
company.save
group.save
user.save

Multiple has_one association to one polymorphic model

I have two models, Address and User:
class Address < ActiveRecord::Base
belongs_to :resource, polymorphic: true
end
class User < ActiveRecord::Base
has_one :contact_address, class_name: "Address", as: :resource
has_one :billing_address, class_name: "Address", as: :resource
end
Problem is if I create billing_address for User it will be automatically set as contact_address, since the addresses table doesn't specify a different resource_type (both are User).
Can you give me some advice on how I should set up my models?
Thanks
I would say a billing address is more to do with an order than a person. For example, on one order I might want you to bill me at work, another at home.
Also, a person can have many addresses, but an address can also have many people. It is a network, not a hierarchy. The classic representation:
PARTY
id
type
name
PARTY_ADDRESS
id
party_id
address_id
type {home, work}
ADDRESS
id
suite
...
ORDER
id
date
customer_party_address_id
bill_to_party_address_id
ORDER_ITEM
id
order_id
product_id
price
quantity
ship_to_party_address_id
I choose easy way, added another foreign_key for addresses table. After that:
has_one :contact_address, class_name: "Address", as: :resource, foreign_key: :foreign_key
Single table inheritance can help you out. To get this to work you have to add a type column to the locations table through a migration (as you do with all Single Table Inheritance models).
class Address < ActiveRecord::Base
belongs_to :resource, polymorphic: true
end
class ContactAddress < Address
end
class BillingAddress < Address
end
class User < ActiveRecord::Base
has_one :contact_address, as: :resource
has_one :billing_address, as: :resource
end
For what it's worth, the belongs_to relationship name (:resource) is a bit weird. Maybe :addressable would make more sense?

Ruby on Rails: Associations when a user likes a song

I'm trying to figure out the best way to setup my database and models for the following scenario.
A user can like an infinite number of songs.
A song can be liked once by an infinite number of users.
I have these tables:
songs, users, likes etc... Following RoR conventions.
The table named likes has these foreign keys: user_id, song_id. And also a field named 'time' to save a timestamp when the song was liked.
I'm not sure of how to do this, I would like to be able to use code like this in my controllers:
User.find(1).likes.all
This should not return from the likes table, but join the songs table and output all the songs that the user likes.
What are the best practises to achieve this in Ruby on Rails following their conventions?
Unless you need to act specifically on the likes table data, the model itself is probably not necessary. The relationship is easy:
class User < ActiveRecord::Base
has_and_belongs_to_many :songs
end
class Song < ActiveRecord::Base
has_and_belongs_to_many :users
end
This will join through the currently non-existent song_users table. But since you want it to join through likes you can change each one to this:
has_and_belongs_to_many :songs, :join_table => 'likes'
If you want to be able to call User.find(1).likes and get songs, then change the user's version to this:
class User < ActiveRecord::Base
has_and_belongs_to_many :likes, :join_table => 'likes', :class_name => 'Song'
end
And you could change the songs version to something like this:
class Song < ActiveRecord::Base
has_and_belongs_to_many :liked_by, :join_table => 'likes', :class_name => 'User'
end
This will give you Song.find(1).liked_by.all and give you the users (You could keep it to users if you wanted using the first version)
More details on habtm relationships can be found here: http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
Edit to add
If you want to act on the join table for whatever reason (you find yourself needing methods specifically on the join), you can include the model by doing it this way:
class User < ActiveRecord::Base
has_many :songs, :through => :likes
has_many :likes
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :song
end
class Song < ActiveRecord::Base
has_many :users, :through => :likes
has_many :likes
end
This will let you do User.find(1).songs.all, but User.find(1).likes.all will give you the join data

Resources