AR joined class in parent class - ruby-on-rails

i have Author entity which belongs_to User. User has_many posts. Please advice how can i show recent_posts on Author entity from User.
class User < ActiveRecord::Base
has_many :posts, :foreign_key => "author_id"
end
class Post < ActiveRecord::Base
attr_accessible :title, :content
belongs_to :author, :class_name => "User"
end
class Author < ActiveRecord::Base
belongs_to :user
has_many :recent_posts, :through => :user,
:class_name => "Post",
:limit => 3,
:order => "updated_at desc"
end
How recent_post should be done? Raw sql?

You want the :source option to has_many, which you use to specify the association on the other model, like so:
has_many :recent_posts, :through => :user, :source => :posts, :limit => 3, :order => 'updated_at desc'

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 !

has_many :through with a foreign key?

I've read multiple questions about this, but have yet to find an answer that works for my situation.
I have 3 models: Apps, AppsGenres and Genres
Here are the pertinent fields from each of those:
Apps
application_id
AppsGenres
genre_id
application_id
Genres
genre_id
The key here is that I'm not using the id field from those models.
I need to associate the tables based on those application_id and genre_id fields.
Here's what I've currently got, but it's not getting me the query I need:
class Genre < ActiveRecord::Base
has_many :apps_genres, :primary_key => :application_id, :foreign_key => :application_id
has_many :apps, :through => :apps_genres
end
class AppsGenre < ActiveRecord::Base
belongs_to :app, :foreign_key => :application_id
belongs_to :genre, :foreign_key => :application_id, :primary_key => :application_id
end
class App < ActiveRecord::Base
has_many :apps_genres, :foreign_key => :application_id, :primary_key => :application_id
has_many :genres, :through => :apps_genres
end
For reference, here is the query I ultimately need:
#apps = Genre.find_by_genre_id(6000).apps
SELECT "apps".* FROM "apps"
INNER JOIN "apps_genres"
ON "apps"."application_id" = "apps_genres"."application_id"
WHERE "apps_genres"."genre_id" = 6000
UPDATED Try this:
class App < ActiveRecord::Base
has_many :apps_genres, :foreign_key => :application_id
has_many :genres, :through => :apps_genres
end
class AppsGenre < ActiveRecord::Base
belongs_to :genre, :foreign_key => :genre_id, :primary_key => :genre_id
belongs_to :app, :foreign_key => :application_id, :primary_key => :application_id
end
class Genre < ActiveRecord::Base
has_many :apps_genres, :foreign_key => :genre_id
has_many :apps, :through => :apps_genres
end
With query:
App.find(1).genres
It generates:
SELECT `genres`.* FROM `genres` INNER JOIN `apps_genres` ON `genres`.`genre_id` = `apps_genres`.`genre_id` WHERE `apps_genres`.`application_id` = 1
And query:
Genre.find(1).apps
generates:
SELECT `apps`.* FROM `apps` INNER JOIN `apps_genres` ON `apps`.`application_id` = `apps_genres`.`application_id` WHERE `apps_genres`.`genre_id` = 1

Rails: delete polymorphic STI has_many through association fails

I have a model called User which has many "taxonomies" associated through a Classification model. One of these taxonomies is a model called Topic (inheriting from Taxonomy). My model User is also called a "classifiable".
EDIT: Added more models to clarify the problem
class User < ActiveRecord::Base
has_many :classifications, :as => :classifiable, :foreign_key => :classifiable_id
has_many :topics, :through => :classifications, :source => :taxonomy, :source_type => "Topic"
end
class Taxonomy < ActiveRecord::Base
end
class Topic < Taxonomy
has_many :classifications, :as => :taxonomy, :foreign_key => :taxonomy_id, :source_type => "Topic"
has_many :professionals, :through => :classifications, :source => :classifiable, :source_type => "User", :conditions => {:is_a_professional => true}
has_many :questions, :through => :classifications, :source => :classifiable, :source_type => "Question"
has_many :guides, :through => :classifications, :source => :classifiable, :source_type => "Guide"
end
class Classification < ActiveRecord::Base
attr_accessible :classifiable, :classifiable_id, :classifiable_type,
:taxonomy, :taxonomy_id, :taxonomy_type
belongs_to :classifiable, :polymorphic => true
belongs_to :taxonomy, :polymorphic => true
end
Everything works well except when I want to delete an association.
user = User.find(12) # any user
topic = user.topics.last # any of his topics
user.topics.delete(topic)
The SQL ActiveRecord runs is the following:
DELETE FROM "classifications" WHERE "classifications"."classifiable_id" = 12 AND "classifications"."classifiable_type" = 'User' AND "classifications"."taxonomy_id" = 34 AND "classifications"."taxonomy_type" = 'Taxonomy'
Clearly, the taxonomy_type is wrong, it should be 'Topic' and not 'Taxonomy'.
Since I am using polymorphic associations and STI, I had to config ActiveRecord as such:
ActiveRecord::Base.store_base_sti_class = false
However, it does not seem to trigger on collection.delete. Is this a bug with rails?

Ruby on Rails has_many_through with validation and logic to ensure only one record in the join table which is updated as required

I have the Course model which has a number of has many through associations with the User model with join table CourseUser. The join table has an attribute type_str which specifies which role the user takes on. I have added validation to ensure that only one record is present in the join table for each course, user pair. The problem is ensuring that this record is updated if it is already present, rather than adding a new one which of course makes validation fail.
User class:
class User < ActiveRecord::Base
...
has_many :courses_enrolled_on, :through => :course_enrollees, :source => :course, :conditions => { :course_users => { :type_str => "enrollee" } }
has_many :course_users
has_many :courses, :through => :course_users, :source => :course, :readonly => true
end
Course class
class Course < ActiveRecord::Base
has_many :course_enrollees, :conditions => { :type_str => "enrollee" }, :class_name => CourseUser
has_many :enrollees, :through => :course_enrollees, :source => :user
has_many :course_users
has_many :users, :through => :course_users, :source => :user, :readonly => true
end
Course class:
class CourseUser < ActiveRecord::Base
belongs_to :course
belongs_to :user
validates_uniqueness_of :course_id, :scope => :user_id
end

Polymorphic associations in Rails 3

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?

Resources