I'm working on an API in Rails and have hit a wall. I'm missing something stupid I imagine, but I can't see it.
https://gist.github.com/3989396
I can not get associations passed in the item.json to create an association. I thought that Rails would hook these up.
The relations for the accounts need to be fixed like so:
item.rb:
belongs_to :expense_account, class_name: "Account"
belongs_to :income_account, class_name: "Account"
account.rb:
has_many :items, inverse_of: :expense_account
has_many :items, inverse_of: :income_account
Related
My Rails application has users and tasks created by users. Users can also create a task and assign another user to it. I am not quite sure how to build associations here.
I know since a task is created by a user, I can have an association as below,
class User
has_many :tasks, dependent: :destroy, foreign_key: :user_id
end
class Task
belongs_to :user
end
I also want to add an association for creator in the Task model but I am not sure how to do it since a creator will also be an instance of the User class and I already have a belongs_to association with User
I tried to add an association for creator in Task model in the following way but it didn't work.
has_one :user, foreign_key: :creator_id, class_name: "User"
Since you've already defined the belongs_to :user method, the method #task.user is already taken by that association. You can't use the same name for a different method, so you'll have to use a different name for that association.
The association name doesn't have to be the same as the model. You can name the creator association something else, like "creator":
has_one :creator, foreign_key: 'creator_id', class_name: "User"
Since the task has a foreign key for the creator, you should be able to use belongs_to for both associations:
class Task
belongs_to :user
belongs_to :creator, foreign_key: 'creator_id', class_name: 'User'
end
Here's a discussion about the difference between has_one and belongs_to: What's the difference between belongs_to and has_one?
Either way way you can do:
#task.user # the User who is assigned the task
#task.creator # the User who created the task
Before ask that, I must say that I really searched the web trying to find the answer, but I didn't found any that solved my problem. Answers like that doesn't solve my problem, because I don't want specify source_type, I want a generic thing - you'll understand.
Okay, let's go. I'm using a "many-to-many polymorphic" relationship in my project, but I can't get it to work. Before try to use polymorphic, this was just a "many-to-many" relationship and worked very well, so I want keep the structure, just adding polymorphic.
Structure:
Many-to-many: A user and visitor has many subject, and vice versa. We assume that user and visitor are followers and subject is followed.
Relationship table: This objects have a relationship table called "psrelations" (person-subject relations). This table stores the many-to-many relationship.
Models:
psrelations.rb:
attr_accessible :followed_id, :follower_type, :follower_id
belongs_to :follower, polymorphic: true
belongs_to :followed, class_name: "Subject"
user.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
visitor.rb:
has_many :psrelations, as: :follower, dependent: :destroy
has_many :followed_subjects, through: :psrelations, source: :followed
subject.rb
has_many :psrelations, as: :followed, dependent: :destroy
has_many :followers, through: :psrelations, source: :follower
I want that "followers" return all "visitors" and "users", not just one or other, like specifying source_type.
Everything appears to be okay, but when I try to self.followers.include?(person) (where person can be either user or visitor), I got:
Cannot have a has_many :through association 'Subject#followers' on the polymorphic object 'Follower#follower'.
What am I doing wrong?
I have created 3 models for a small system. The intent here is to handle users, companies and their relationships. I anticipate to do a lot of lookups over the intersections and also want to have strict controls over the joins available, in that a user can only belong to one company, but company can have many users. I feel the best way to represent this is with the below. I would like some feedback on this preposition. So far my tests have worked fine validating my thesis and some small implementation efforts have gone fine, but when I look through a list of users to find their company I somehow run into issues and I have a feeling it is related to the has_one relationship, but not sure. Again thanks for constructive feedback.
class User < ActiveRecord::Base
has_one :companyrelationship, foreign_key: "user_id"
has_one :company, :through => :companyrelationship, dependent: :destroy
class Company < ActiveRecord::Base
has_many :companyrelationships
has_many :users, :through => :companyrelationships
class CompanyRelationship < ActiveRecord::Base
belongs_to :company
belongs_to :user
validates :user_id, presence: true, uniqueness: true
validates :company_id, presence: true
I do see one thing that I'm pretty sure is an error and won't work. I can also try to add a couple points of constructive criticism.
The error is that the CamelCase model name is converted to underscorey (sorry, I can't remember the term for that right now) case. All your references to companyrelationship should add an underscore. You can override the convention by setting the :class_name attribute, but I don't think that's what you wanted.
Another issue I see which isn't technically wrong, but is almost certainly not what you want is that the dependent: :destroy would delete the Company when you deleted a User. (Actually, I'm not sure dependent: :destroy works in a through: relationship.) I assume what you wanted was just to delete the CompanyRelationship. You can read the section on Dependent associations at this link:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Next point is that the default foreign_key is the model + _id so you don't need to specify it in this case.
My last point is purely a style preference. I like doing my validations by validation type. You're doing them by variable. They are functionally equivalent, so feel to take it with a grain of salt. (I'm pretty sure user and user_id are equivalent, but feel free to stick to user_id if you're more comfortable with it.)
If it were completely up to me, I would code it this way:
class User < ActiveRecord::Base
has_one :company_relationship, dependent: :destroy
has_one :company, through: :company_relationship
class Company < ActiveRecord::Base
has_many :company_relationships
has_many :users, through: :company_relationships
class CompanyRelationship < ActiveRecord::Base
belongs_to :company
belongs_to :user
validates_presence_of :user, :company
validates_uniqueness_of :user
I hope that helps you get further.
I have a model:
class Merchant < ActiveRecord::Base
belongs_to :billing_address, class_name: Address, dependent: :destroy
belongs_to :other_address1, class_name: Address, dependent: :destroy
belongs_to :other_address2, class_name: Address, dependent: :destroy
belongs_to :other_address3, class_name: Address, dependent: :destroy
belongs_to :other_address4, class_name: Address, dependent: :destroy
...
end
Address has no associations.
When I do this:
merchant.billing_address.destroy
In the database, the address record is gone, but merchants.billing_address_id keeps a bogus value. This is mysql, so no referential integrity.
What am I doing wrong?
NOTE: I realize this might be better modeled as a has_one association. I might have to go there, but I prefer not to.
UPDATE: Added a little more code to show the multiple Address associations.
If you want merchant.billing_address to be null after you destroy the billing address, then you need to use :dependent => :nullify in the Address model.
Ref http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
It turns out that ActiveRecord does not support one-sided belongs_to associations, unlike other ORMs I've worked with. But you can hack it yourself like so:
before_save :remove_ids_for_nil_associations
def remove_ids_for_nil_associations
self.billing_address_id = nil if is_getting_destroyed? self.billing_address
...
end
def is_getting_destroyed?(ref)
ref.present? && ref.destroyed?
end
In a Rails 3.2 app I need to set up two associations between the same two models.
For example
class User
has_many :events
has_many :attendances
has_many :attended_events, through: :attendances
end
class Event
belongs_to :event_organizer, class_name: "User"
has_many :attendances
has_many :attendees, through: :attendances, class_name: "User"
end
class Attendance
belongs_to :attended_event, class_name: "Event"
belongs_to :attendee, class_name: "User"
end
This is the first time I've experimented with aliasing class names, and I'm having trouble getting it to work. I'm not sure if the issue lies with how I've defined the associations, or elsewhere.
Do my associations look OK? Have I overlooked something needed to get this to work?
The problem I'm having is that no user ids are being set in the Attendance model. This may be a stupid question, but given my associations above, should the field name be :user_id or :event_organizer_id?
Really appreciate any suggestions on this. Thanks!
foreign_key to be specified in User and Event
class User
has_many :events
has_many :attendances, foreign_key: :attendee_id
has_many :attended_events, through: :attendances
end
class Event
belongs_to :event_organizer, class_name: "User"
# here it should be event_organizer_id
has_many :attendances, foreign_key: :attended_event_id
has_many :attendees, through: :attendances
end
class Attendance
belongs_to :attended_event, class_name: "Event"
# this should have attended_event_id
belongs_to :attendee, class_name: "User"
# this should have attendee_id because of 1st param to belongs_to here is "attendee"
# and same should be added as foreign_key in User model
# same follows for Event too
end