Rails - Help needed to create a New Model - ruby-on-rails

class Person
has_many :owned_groups, :class_name => "Group", :foreign_key => :owner_id
has_many :owned_group_memberships, :through => :owned_groups,
:source => :group_memberships
has_many :group_memberships, :foreign_key => "member_id"
has_many :groups, :through => :group_memberships
end
class GroupMembership
belongs_to :member, :class_name => 'Person'
belongs_to :group
end
class Group
belongs_to :owner, :class_name => "Person"
has_many :group_memberships
has_many :members, :through => :group_memberships
end
I want to create the model Message so a Person can post a new message in the group#show page. But for that she/he must be from the Group in question, or the owner, or have a group_membership (be a member) from this group.
How would be the associations of the model Message?

class Message < ActiveRecord::Base
belongs_to :person
belongs_to :group
validate :has_group_permission
def has_group_permission
unless self.person.owned_groups.include?(self.group) || self.person.groups.include?(self.group)
self.errors.add(:base, "you don't have permission to add a message to this group."
end
end
end

Related

Rails polymorphic table that has other kinds of associations

I'm currently modeling a Rails 3.2 app and I need a polymorphic association named "archivable" in a table named "archives". No worries with it, but my "archives" table must also belongs_to a "connections" table. I just want to know if there's any constraints from Rails to do that.
You can see the model here
Another detail, my Connection model has twice user_id as foreign key. A user_id as sender and a user_is as receiver. Possible? I think what I did below won't work...
Here are my models associations.
class User < ActiveRecord::Base
has_many :connections, :foreign_key => :sender
has_many :connections, :foreign_key => :receiver
end
class Connections < ActiveRecord::Base
belongs_to :user
has_many :archives
end
class Archive < ActiveRecord::Base
belongs_to :connection
belongs_to :archivable, :polymorphic => true
end
class Wink < ActiveRecord::Base
has_many :archives, :as => :archivable
end
class Game < ActiveRecord::Base
has_many :archives, :as => :archivable
end
class Message < ActiveRecord::Base
has_many :archives, :as => :archivable
end
Do you see anything wrong or something not doable with Rails?
Thank you guys.
I think you want to do this :
class Connections
belongs_to :sender, :class_name => 'User', :foreign_key => 'sender_id'
belongs_to :receiver, :class_name => 'User', :foreign_key => 'receiver_id'
end
class User
has_many :sended_connections, :class_name => 'Connection', :as => :sender
has_many :received_connections, :class_name => 'Connection', :as => :receiver
end
Important : Don't declare 2 times has_many :connections with the same name !

Rails has_many through with condition, build new

I've got users and organisations with a join model UsersOrganisation. Users may be admins of Organisations - if so the is_admin boolean is true.
If I set the is_admin boolean by hand in the database, Organisations.admins works as I'd expect.
In the console, I can do Organisation.first.users << User.first and it creates an organisations_users entry as I'd expect.
However if I do Organisation.first.admins << User.last it creates a normal user, not an admin, ie the is_admin boolean on the join table is not set correctly.
Is there a good way of doing this other than creating entries in the join table directly?
class User < ActiveRecord::Base
has_many :organisations_users
has_many :organisations, :through => :organisations_users
end
class Organisation < ActiveRecord::Base
has_many :organisations_users
has_many :users, :through => :organisations_users
has_many :admins, :through => :organisations_users, :class_name => "User",
:source => :user,
:conditions => {:organisations_users => {:is_admin => true}}
end
class OrganisationsUser < ActiveRecord::Base
belongs_to :organisation
belongs_to :user
end
You can always override the << method of the association:
has_many :admins do
def <<(user)
user.is_admin = true
self << user
end
end
(Code has not been checked)
there are some twists with the has_many :through and the << operator. But you could overload it like in #Erez answer.
My approach to this is using scopes (I renamed OrganisationsUsers to Memberships):
class User < ActiveRecord::Base
has_many :memberships
has_many :organisations, :through => :memberships
end
class Organisation < ActiveRecord::Base
has_many :memberships
has_many :members, :through => :memberships, :class_name => 'User', :source => :user
# response to comment:
def admins
memberships.admin
end
end
class Memberships < ActiveRecord::Base
belongs_to :organisation
belongs_to :user
scope :admin, where(:is_admin => true)
end
Now I create new admins like this:
Organisation.first.memberships.admin.create(:user => User.first)
What I like about the scopes is that you define the "kind of memberships" in the membership class, and the organisation itself doesn't have to care about the kinds of memberships at all.
Update:
Now you can do
Organisation.first.admins.create(:user => User.first)
You can try below code for organization model.
class Organisation < ActiveRecord::Base
has_many :organisations_users
has_many :organisations_admins, :class_name => "OrganisationsUser", :conditions => { :is_admin => true }
has_many :users, :through => :organisations_users
has_many :admins, :through => :organisations_admins, :source => :user
end

How to set up relations between these two rails models

I have 2 models: User and PrivateMessage which must be associated (as user has many private messages as reciever and sender, private messages belongs to user)
It's my private_messages table structure:
private_messages:
sender_id:integer
reciever_id:integer
title:string
message:text
It's hard for me to understand how can I connect same message for both sender user and reciever user, now my models code looks like:
class User < ActiveRecord:Base
has_many :private_messages
end
and
class PrivateMessage < ActiveRecord::Base
belongs_to :user, :through => :sender_id
belongs_to :user, :through => :reciever_id
end
Is that correct?
You have to rename your associations to tell them apart:
class PrivateMessage < ActiveRecord::Base
belongs_to :sender, :class_name => 'User', :foreign_key => 'sender_id'
belongs_to :receiver, :class_name => 'User', :foreign_key => 'receiver_id'
end
class User < ActiveRecord::Base
has_many :sent_messages, :class_name => 'PrivateMessage', :foreign_key => 'sender_id', :dependent => :destroy
has_many :received_messages, :class_name => 'PrivateMessage', :foreign_key => 'receiver_id', :dependent => :destroy
end

multiple belongs_to relationship to three model

The situation is this way..
class Organization < ActiveRecord::Base
has_many :role_memberships
has_many :roles
has_many :users, :through => :role_memberships, :uniq => true
end
class User
has_many :role_memberships
has_many :organizations, :through => :role_memberships, :uniq => true
has_many :roles, :through => :role_memberships, :uniq => true
end
class RoleMembership < ActiveRecord::Base
belongs_to :organization
belongs_to :role
belongs_to :user
end
class Role < ActiveRecord::Base
belongs_to :organization
has_many :role_memberships
has_many :users, :through => :role_memberships, :uniq => true
end
The QUESTION is how do I populate all the three foreign-keys in rolemembership table..when I do org.users.push(u) this create a record but role_id is left out...
In this case I will probably create RoleMembership object itself, like this:
RoleMembership.create(:organization_id => org.id, :role_id => role.id, :user_id => user.id)

Nested Has Many Through Plugin and Named Scopes

I have a User Model(:name, :password, :email), and Event model(:name, :etc) and Interest model (:name) [>all singular<]
Then I created two join tables -> UsersInterests and EventsInterests; each not containing a primary key and only comprised of the user_id/interest_id and event_id/interest_id respectively. [>plural<]
My Models Use the Nested Has Many Through Plugin
user.rb => has_many :users_interests
has_many :interests, :through => :users_interests
has_many :events_interests, :through => :interests
has_many :events, :through => :events_interests
event.rb => has_many :events_interests
has_many :interests, :through => :events_interests
has_many :users_interests, :through => :interests
has_many :users, :through => :users_interests
interest.rb => has_and_belongs_to_many :users
has_and_belongs_to_many :events
events_interests.rb => belongs_to :interests
belongs_to :events
users_interests.rb => belongs_to :users
belongs_to :interests
Whew..ok So I wanted to created a named_scope of that find all the events that share interest with a particular user. Here is some code someone helped me with.
named_scope :shares_interest_with_users, lambda {|user|
{ :joins => :users_interests,
:conditions => {:users_interests => {:user_id => user}}
}}
When i run from the controller =>
#user = User.find(1)
#events = Event.shares_interest_with_user(#user)
I get the error :
uninitialized constant Event::EventsInterest
Can anyone see what i messed up?
You must have named something wrong along the way. At a glance I'd say you have a file or class named incorrectly. Remember model names MUST always be singular, both in file and class names or else Rails won't make the connection. Another source of your problem is that arguments to belongs_to must also be singular. Even if you had got things right, the HABTM relationship in interests with users would have thrown an error when you ran the named scope.
I was able to solve your error with the following models.
user.rb
class User < ActiveRecord::Base
has_many :users_interests
has_many :interests, :through => :users_interests
has_many :events_interests, :through => :interests
has_many :events, :through => :events_interests
end
users_interest.rb
class UsersInterest < ActiveRecord::Base
belongs_to :user
belongs_to :interest
end
interest.rb
class Interest < ActiveRecord::Base
has_many :users,:through => :users_interests
has_many :users_interests
has_many :events_interests
has_many :events, :through => :events_interests
end
**events_interest.rb
class EventsInterest <ActiveRecord::Base
belongs_to :interest
belongs_to :event
end
event.rb
class Event <ActiveRecord::Base
has_many :events_interests
has_many :interests, :through => :events_interests
has_many :users_interests, :through => :interests
has_many :users, :through => :users_interests
named_scope :shares_interest_with_users, lambda {|user|
{ :joins => :users_interests,
:conditions => {:users_interests => {:user_id => user}}
}
}
end

Resources