I'm using a Polymorphic relation with multiple tables. Object Window has ChartWindow, PluginWindow or PortletWindow. I used a class_eval (relate_to_details) technique to define detail tables so that each object can have it's own table with distinct attributes.
PluginWindowDetail is the detail table for PluginWindow. PluginWindow has a plugin_id (plugin_window_details.plugin_id) So, I defined a has_one association in PluginWindow ( has_one :plugin_window_detail, :dependent => :delete) because I want the Window to be deleted with the Plugin is deleted.
However, I realized that this isn't getting me what I want. Deleting the PluginWindowDetail won't delete the PluginWindow.. and since I'm using the class_eval technique instead of a regular ActiveRecord association, I'm not sure how I can do this without coding it myself (which maybe I should)
Anyways.. gists with code are here https://gist.github.com/3206666 . Any help would be appreciated.
I think the simpler way to do it is to use the before_destroy callback. It will be more flexible.
Related
What is the exact purpose of associations? I understand what the relationships mean and when to use each type for example:
belongs_to, has_many, has_one , has_and_belongs_to_many, ect
but i dont quite understand what purpose they serve in terms of how the connect things within rails. Any input would be appreciated. Thanks!
What you're calling "associations" I would call "macros". That is, the belongs_to, has_many etc. macros are simply class methods being called on your ActiveRecord objects which, when called, define a bunch of functionality based on the association name.
So, what you're asking is: What functionality do these macro methods define? The answer for that lies within the Rails documentation for each of these methods:
has_many
belongs_to
has_one
And, even more, you should read the overall documentation on ActiveRecord::Associations::ClassMethods.
But, in short, these macros define methods with names based on the association names you pass into them. So, for example:
belongs_to :my_object
Will define, as a greatly-simplified example:
def my_object
MyObject.find_by_id(my_object_id)
end
So it's basically like metaprogramming your objects to have the methods needed to find the other, associated objects, update their collections, and so on.
As I learned update_only doesn't work for has_many association.
I am updating nested attributes and it creates new children each time and don't delete old children. What would be the good way to delete them automatically on each update (to mimic :update_only behavior which works for has_one)?
I know about :allow_destroy. However, I don't have children id's to let rails know what should be destroyed.
P.S. I asked this question originally back in 2012 and back then I found a hacky solution to override assign_nested_attributes_for_collection_association. I wonder whether anything was introduced in Rails to solve this problem. It looks like very common straightforward case. I wonder why there is a built-in solution for it.
The best approach which I found is to override method assign_nested_attributes_for_collection_association on the object, check association type in there. if it's has_many then do destroy_all on this association.
Such code can be generalized and moved to a module for further reuse.
It looks like there is a better solution in town mentioned in these two questions:
Rails 4 has_many nested_attributes to replace all
Rails replace collection intead of adding to it from a has_many nested attributes form
The solution is
def foo_attributes=(*attrs)
self.foo.clear
super(*attrs)
end
Here is my situation. I have model called Account. An account can have one or more contracts. The problem is that i'm dealing with a legacy application and each account's contracts are stored in a different database.
Example:
Account 1's contract are in account1_db.contracts.
Account 2's contract are in account2_db.contracts.
The database name is a field stored in accounts table.
How can i make rails association work with this?
This is a legacy PHP application and i simply can't change it to store everything in one table. I need to make it work somehow.
I tried this, but it didn't worked:
has_many :contracts, :conditions => [lambda{ Contract.set_table_name(self.database + '.contracts'); return '1' }]
Any ideas?
Why isn't database migration an option?
You're approaching this the wrong way. You want the two systems in your integration to be loosely coupled. By trying to get the two associated, you're creating an array of interdependencies that will later come around to backstab you. The approach you are trying creates tight coupling and reduces cohesion.
But, to directly answer your question, see below. Once again, I don't recommend implementing what I say below, but it would technically be a solution.
The first thing is that rails associations work only with foreign key. In fact, all database associations work this way. There isn't a ActiveRecord method of association without foreign keys as it defies what it means to associate two objects.
So you're not going to get it done with a has_many association. Instead, I would just manually create a function on your Contract model that simulates a has_many association.
class Account
memoize :contracts
def contracts
# Load from other database in here
end
def contracts=
# Push to other database in here
end
end
I'm porting some functionality to Rails, and I'm working with an existing table which is for comments.
Basically, there are two types of comments - profile comments (photo_id column is null) and photo comments (photo_id column is set to photo's ID)
I got single table inheritance working just fine by adding a type field to the table, but I'm wondering if there's a way to get my single table inheritance working without the type field. According to the Rails API documentation, "If you don‘t have a type column defined in your table, single-table inheritance won‘t be triggered. In that case, it‘ll work just like normal subclasses with no special magic for differentiating between them or reloading the right type with find."
I'm wondering if there's a way that I can customize my models to determine type based on photo_id being nil or having an integer value, rather than using the database column (which I'd rather not add if I don't have to.) Any ideas?
If comments models doesn't differ much, I wouldn't bother with single table inheritance at all. Just add:
# to Comment model
belongs_to :photo
belongs_to :profile
# to Profile model
has_many :comments
# to Photo model
has_many :comments
Then:
#photo.comments # will return comments associated with photos
#profile.comments # will return comments associated with profiles
There may be problem if you had both photo_id and profile_id set (I suppose it may happen when you comment a photo that is associated with profile), so you can change in Profile model:
has_many :comments, :conditions => "photo_id is not null"
Another approach (I think better) it to you polymorphic associations but you will need to modify you sql tables.
I suspect you cannot do this trivially. However, one possibility is to trick active record into using a view rather than a table, and write some database functions to set this magic attribute based on which id is set.
However, in the end, I suspect it would be far, far easier to just add the column.
Trying to do a select field for an admin interface.
What I have is not a traditional many-to-many relationship, but I imagine the principles are the same. I have an "Event" model and an "EventRelation" model...every Event can have many sub-events, and one primary event...so EventRelation has primary_event_id and sub_event_id fields.
How would I make a select field that would allow me to specify a primary_event for any given Event?
The relevant model code:
class Event 'primary_event_id', :class_name=>'EventRelation'
has_one :primary_event_relation, :foreign_key=>'sub_event_id', :class_name=>'EventRelation'
has_one :primary_event, :through=>:primary_event_relation, :foreign_key=>"primary_event_id"
has_many :sub_events, :through=>:sub_event_relations, :foreign_key=>"sub_event_id"
end
class EventRelation 'Event', :foreign_key=>"primary_event_id"
belongs_to :sub_event, :class_name=>'Event', :foreign_key=>"sub_event_id"
end
I would use a plugin like Formtastic to accomplish this because it has support for various forms of ActiveRecord associations built into a solid alternative form handler. Just make sure you do an appropriate query with the most efficient join or include options for you model so that your view doesn't cause unnecessary database queries as it works through the associations.
As James says, Formtastic is a great way to go for this. And there are two great railscasts on how to use it.