From a person record I need to be able to add/display documents of specific types. Including the conditions for category_id works but at this point I can not assume that the category ids will remain the same as development progresses. This is also an issue with testing where I only create the categories I need.
Is there a way I can dynamically set the category_id, for example something like this:
has_many :personal_documents, :as => :documentable, :conditions => "category_id = #{DocumentCategory.find_by_name('Personal').id}", class_name: 'Document'
Models:
Person < AR::Base
has_many :documents, :as => :documentable
has_many :personal_documents, :as => :documentable, #:conditions => "category_id = 1"
has_many :legal_documents, :as => :documentable, #:conditions => "category_id = 2"
end
Animal < AR::Base
has_many :documents, :as => :documentable
end
Document < AR::Base
belongs_to :person
belongs_to :category
end
Could you simply use seeds with static ids?
Related
I have 3 tables Collections, Tracks and ProductContributors
Association of them is as follows
class Collection < ActiveRecord::Base
has_many :product_contributors, :as => :product
has_many :tracks, :through => Product_contributors, :as=> :product
end
class Track < ActiveRecord::Base
has_many :product_contributors, :as => :product
has_many :collections, :through => Product_contributors, :as => :product
end
class ProductContributor < < ActiveRecord::Base
belongs_to :product, :polymorphic => true
belongs_to :collection
belongs_to :track
end
whenever i hit the url for product contributor i get the following error :
Expected /app/models/track.rb to define TRACK
I've gone through this url but didnt help me in any case. I dont have the autoload issue, all my models are loaded properl
Any help would be highly appreciated..!!
I dare say its because of the typo in your Track class.
has_many :collections, :through => Product_contributors, :as => :product
is not valid. Try:
has_many :collections, :through => :product_contributors, :as => :product
Basically, it is trying to load the Model, but its finding the typo in the association, and it is then not loading, causing it to seem like the class is not there. I assume you will have a similar situation with the Collection class as well.
I'm looking to add a Favorite model to my User and Link models.
Business Logic
Users can have multiple links (that is, they can add multiple links)
Users can favorite multiple links (of their own or other users)
A Link can be favorited by multiple users but have one owner
I'm confused as to how to model this association and how would a user favorite be created once the models are in place?
class User < ActiveRecord::Base
has_many :links
has_many :favorites
end
class Link < ActiveRecord::Base
belongs_to :user
#can be favorited by multiple users
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :link
end
How about the following data model:
class User < ActiveRecord::Base
has_many :links
has_many :favorites, :dependent => :destroy
has_many :favorite_links, :through => :favorites, :source => :link
end
class Link < ActiveRecord::Base
belongs_to :user
has_many :favorites, :dependent => :destroy
has_many :favorited, :through => :favorites, :source => :user
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :link
end
Since User already has an association called links, and Link already has one called users, we cannot use the same name for the has_many :through association (e.g. User has_many :links, :through => :favorites would not work). So, we invent a new association name, and help Rails know what association to load from the intermediary association via the source attribute.
Here's some pseudocode for using this association:
# Some users
user1 = User.create :name => "User1"
user2 = User.create :name => "User2"
# They create some links
link1_1 = user1.links.create :url => "http://link1_1"
link1_2 = user1.links.create :url => "http://link1_2"
link2_1 = user2.links.create :url => "http://link2_1"
link2_2 = user2.links.create :url => "http://link2_2"
# User1 favorites User2's first link
user1.favorites.create :link => link2_1
# User2 favorites both of User1's links
user2.favorites.create :link => link1_1
user2.favorites.create :link => link1_2
user1.links => [link1_1, link1_2]
user1.favorite_links => [link2_1]
user2.links => [link2_1, link2_2]
user2.favorite_links => [link1_1, link1_2]
link1_1.favorited => [user2]
link2_1.destroy
user1.favorite_links => []
user2.links => [link2_2]
I think I'm going crazy.
Let's say I have 3 models: Address, Warehouse, Category:
class Address < ActiveRecord::Base
belongs_to :category
belongs_to :addressable, :polymorphic => true
scope :billing_addresses , where(:categories => {:name => 'billing'}).joins(:category)
scope :shipping_addresses , where(:categories => {:name => 'shipping'}).joins(:category)
end
class Category < ActiveRecord::Base
has_many :addresses
has_many :subcategories, :class_name => "Category", :foreign_key => "category_id"
belongs_to :category, :class_name => "Category"
end
class Warehouse < ActiveRecord::Base
has_many :addresses, :as => :addressable
end
Address is polymorphic, because eventually I'll be using it to store addresses for clients, people, employees etc. Also each address can be of a certain type: billing, shipping, work, home, etc.
I'm trying to pull some information on a page.
#some_warehouse = Warehouse.first
Then in my view:
%b= #some_warehouse.name
%b= #some_warehouse.billing_address.address_line_1
Etc.
I end up doing a lookup for each line of information.
I tried to do things like
Warehouse.includes(:addresses).where(:name => "Ware1")
Warehouse.joins(:addresses).where(:name => "Ware1")
And various variations of that.
No matter what I don' I can't get rails to preload all the tables. What am I doing wrong?
Here are revised models, that do appropriate joins in sql and reduce number of quesries from 16 to 8, one for each piece of info, instead of multiples ones that also do lookup categories, etc.:
class Address < ActiveRecord::Base
belongs_to :category
belongs_to :addressable, :polymorphic => true
scope :billing_addresses , where(:categories => {:name => 'billing'}).includes(:category)
scope :shipping_addresses , where(:categories => {:name => 'shipping'}).includes(:category)
end
class Warehouse < ActiveRecord::Base
has_many :addresses, :as => :addressable, :include => :category, :dependent => :destroy
def billing_address
self.addresses.billing_addresses.first
end
def shipping_address
self.addresses.shipping_addresses.first
end
end
class Category < ActiveRecord::Base
has_many :addresses
has_many :subcategories, :class_name => "Category", :foreign_key => "category_id"
belongs_to :category, :class_name => "Category"
end
Sleep helps. Also not forgetting to reload console from time to time :-)
Maybe you want to use preload_associations?
What is the recommended approach for finding multiple, unique associated models for a subset of another model? As an example, for a subset of users, determine unique artist models they have favorited.
One approach is to grab the users from the database, then iterate them all quering for favorites and building a unique array, but this seems rather inefficient and slow.
class User < ActiveRecord::Base
has_many :favorites
end
class Artist < ActiveRecord::Base
has_many :favorites
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :artist
end
#users = User.find_by_age(26)
# then determine unique favorited artists for this subset of users.
The has_many association has a option called uniq for this requirement:
class User < ActiveRecord::Base
has_many :favorites
has_many :artists, :through => :favorites, :uniq => true
end
class Artist < ActiveRecord::Base
has_many :favorites
has_many :users, :through => :favorites, :uniq => true
end
class Favorite < ActiveRecord::Base
belongs_to :user
belongs_to :artist
end
Usage:
# if you are expecting an array of users, then use find_all instead of find_
#users = User.find_all_by_age(26, :include => :artists)
#users.each do |user|
user.artists # unique artists
end
Edit 1
I have updated the answer based on user's comment.
Solution 1- :group
Artist.all(:joins => :users, :group => :id,
:conditions => ["users.age = ?", 26])
Solution 2- SELECT DISTINCT
Artist.all(:joins => :users, :select => "DISTINCT artists.*",
:conditions => ["users.age = ?", 26]))
Having set up my polymorphic relationship like so:
class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
belongs_to :user
end
class Wine < ActiveRecord::Base
has_many :reviews, :as => :reviewable
end
class Beer < ActiveRecord::Base
has_many :reviews, :as => :reviewable
end
I can do Wine.last.reviews and Beer.find(3).reviews etc...
What I'm strugling to do is go in the other direction, i.e. Lets say I want to find the last 10 reviews for Wine and the last 10 reviews for Beer.
The easiest way to do this is probably to add a named scope to your Review model that specifies the reviewable_type column.
Like so:
class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
belongs_to :user
named_scope :for_wines, :conditions => { :reviewable_type => 'Wine' }
named_scope :for_beers, :conditions => { :reviewable_type => 'Beer' }
end
That way you have the flexibility of scoping when finding your results...
Review.for_wines.approved.all
Review.for_beers.active.find(:all, :order => 'created_at')
etc