I hope someone has already experienced this.
Please help me, how can i solve this problem:
class Article < ActiveRecord::Base
belongs_to :author
belongs_to :publisher
has_one :address, :through => :publisher
end
class Author < ActiveRecord::Base
has_many :articles
has_many :addresses, :through => :articles, :source => :address
end
I try to get "addresses" for "author", and i get this error in console:
ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_one :through for has_many :addresses, :through => :articles. Use :source to specify the source reflection.
but author.articles[0].address works fine.
I hope you give me advice, how can i solve it.
Thanks.
AR does not like sourcing a has_many through a has_one. But you can easily get all the addresses with this method on Author:
def addresses
articles.map {|article| article.address }
end
This solution also worked well for different relation types.
e.g. User.registrations.join_table.periods
but you -can't- apply active_record methods on what is mapped.
e.g. user.periods(:order => :date)
e.g. user.periods.model etc..
thanks
Related
I'm attempting to create a system where my site's users can favorites pages. Those pages have two types, either clubs or sports. So, I have four models, associated as such:
User Model:
class User < ActiveRecord::Base
..
has_many :favorites
has_many :sports, :through => :favorites
has_many :clubs, :through => :favorites
..
end
Favorites Model:
class Favorite < ActiveRecord::Base
..
belongs_to :user
belongs_to :favoritable, :polymorphic => true
end
Club Model:
class Club < ActiveRecord::Base
..
has_many :favorites, :as => :favoritable
has_many :users, :through => :favorites
def to_param
slug
end
end
Sport Model:
class Sport < ActiveRecord::Base
..
def to_param
slug
end
..
has_many :favorites, :as => :favoritable
has_many :users, :through => :favorites
..
end
Essentially, the User has_many sports or clubs through favorites, and the association between favorites, sports, and clubs is polymorphic.
In practice, this is all working exactly the way I want it to, and the whole system I have designed works. However, I'm using Rails_Admin on my site, and I get an error in three places:
When loading the Dashboard (/admin) the first time. If I refresh the page, it works fine.
When loading the User model in Rails_Admin
When loading the Favorites model in Rails_Admin
Here is the error message on /admin/user (gist). All of the errors are similar, referencing ActiveRecord::Reflection::ThroughReflection#foreign_key delegated to source_reflection.foreign_key, but source_reflection is nil:.
Can anyone point me in the right direction so that I can fix this? I've searched all over, and asked other programmers/professionals, but no one could spot the error in my models. Thanks so much!
Alright, well, I finally worked this out, and figured that I'd post the fix just in case it helps someone else out in the future (no one likes finding someone else with the same problem and no posted answer).
As it turns out, with a polymorphic has_many :through, there is a little more configuration needed. My User model should have looked like this:
class User < ActiveRecord::Base
..
has_many :favorites
has_many :sports, :through => :favorites, :source => :favoritable, :source_type => "Sport"
has_many :clubs, :through => :favorites, :source => :favoritable, :source_type => "Club"
..
end
This answer to another question about polymorphic has_many :through associations is what helped me figure this out.
I encountered this error when the code included a has_many for an association that doesn't exist (mid-refactor). So it can also be caused by some general has_many misconfigure. The Ruby/Rails code never cares because the dynamic style of Ruby means the association is only called on demand. But Rails-Admin exhaustively inspects properties, leading to reflection problems.
My needs are very simple: I have a Tip table to receive comments and have comments to receive comments, too.
To retrieve each comment that is stored in the same table (comments), I created another key for the comments on comments: "inverse_comments".
I tried to use one comments table by using self-referntial association. Some resources seem to bring more than one table into the piture which are diffent from my needs. So I came up whth the following modeling for comments:
class Comment < ActiveRecord::Base
belongs_to :tip
belongs_to :user
has_many :mycomments,
:through => :inverse_comments,
:source => :comment
end
Apparently something is missing here but I cannot figure it out.
Could some one enlighten me on this:
what changes I need to do to make the model work?
thanks.
I believe you should use a polymorphic association.
For that you'll need to add a commentable_id and a commentable_type on your comments table. And your models should look like:
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, :polymorphic => true
has_many :comments, :as => :commentable
end
class Tip < ActiveRecord::Base
has_many :comments, :as => :commentable
end
This way you can use
#tip.comments
#comment.comments
I have 3 models:
User
has_many :questions
has_many :corrections
end
Question
has_one :correction
belongs_to :user
end
Correction
belongs_to :user
belongs_to :question
So if user Bob asks a question then user Terry can check it and if its wrong offer a correction.
Lets stay with bob and assume he as kindly corrected 5 other users, i.e and lets assume he has been lucky to get 3 corrections from other users.
I want to be able to do something like this
#bob.corrections_offered => 5 correction objects
#bob.corrections_received => 3 correction objects
the first one is easy as its really just #bob.corrections under the hood. But I dont know how to implement the latter one. Can anyone help?
UPDATE
So I tried using through as suggested like so (Oh and actually the question model above is actually called Sentence in my code. I.e. User => Sentence => Correction. )
has_many :sentences
has_many :corrections_received, :through => :sentences, :class_name => 'Correction'
but got this error in console
ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
Could not find the source
association(s) :Correction in model
Sentence. Try 'has_many
:corrections_received, :through =>
:sentences, :source => '. Is it
one of :language, :correction, :user,
or :checker?
So tried the following
has_many :corrections_received, :through => :sentences, :source => :correction
but got
ActiveRecord::HasManyThroughSourceAssociationMacroError:
Invalid source reflection macro
:has_one for has_many
:corrections_received, :through =>
:sentences. Use :source to specify
the source reflection.
not sure whats going wrong...
You can add a has_many through relationship in your user model like so
class User
#your usual relationships
has_many :corrections_received, :through => :questions, :class_name => 'Correction'
end
Try the following way:
has_many :corrections_received,:class_name=>'Correction',:conditions=>...
Normally, you should be able to do it with :through, but I'm not sure if two user->correction relationships are possible.
In any case, helper method in the model class should be simple enough. Something like this.
def corrections_received
result = Array.new
questions.each do |q|
if q.correction
result.push q.correction
end
end
result
end
Since I'm new to this stuff, corrections are welcome!
Hi I have a relation between 2 models. The models are "Category" and "Page".
I have now the use case that I need 2 Pages/Category. How can I write this?
The fields in Category are "page_id" and "page_en_id".
I'm not sure which is the best solution for this, I only know the belongs_to and has_many solution with foreign key option which makes here no sense for me.
I'm not sure, what you're looking for, but it looks like that:
class Page < ActiveRecord::Base
has_many :categories
has_many :en_categories, :foreign_key => 'page_en_id', :class_name => 'Category'
end
class Category < ActiveRecord::Base
belongs_to :page
end
Ok this is my solution now, thanks guys:
Page
has_one :category
has_one :category_en, :foreign_key => 'page_en_id', :class_name => 'Page'
Category
belongs_to :page
belongs_to :page_en, :class_name => "Page"
I've found an old plugin called acts_as_habtm_list - but it's for Rails 1.0.0.
Is this functionality built in acts_as_list now? I can't seem to find any information on it.
Basically, I have an artists_events table - no model. The relationship is handled through those two models specifying :has_and_belongs_to_many
How can I specify order in this situation?
I'm assuming that you have two models - Artist and Event.
You want to have an habtm relationship between them and you want to be able to define an order of events for each artist.
Here's my solution. I'm writing this code from my head, but similar solution works in my case. I'm pretty sure there is a room for improvement.
I'm using rails acts_as_list plugin.
That's how I would define models:
class Artist < ActiveRecord::Base
has_many :artist_events
has_many :events, :through => :artist_events, :order => 'artist_events.position'
end
class Event < ActiveRecord::Base
has_many :artist_events
has_many :artists, :through => :artist_events, :order => 'artist_events.position'
end
class ArtistEvent < ActiveRecord::Base
default_scope :order => 'position'
belongs_to :artist
belongs_to :event
acts_as_list :scope => :artist
end
As you see you need an additional model ArtistEvent, joining the other two. The artist_events table should have two foreign ids and additional column - position.
Now you can use acts_as_list methods (on ArtistEvent model, unfortunately) but something like
Artist.find(:id).events
should give you a list of events belonging to specific artist in correct order.
Additional update for the accepted answer: for Rails 4 and Rails 5:
has_many :events, -> { order 'artist_events.position ASC' }, through: :artist_events
has_many :artists, -> { order 'artist_events.position ASC' }, through: :artist_events
I trying with self-referencing like that
class Product < ActiveRecord::Base
has_many :cross_sales
has_many :cross_sales_products, :through => :cross_sales, :order => 'cross_sales.position'
end
class CrossSale < ActiveRecord::Base
default_scope :order => 'cross_sales.position'
belongs_to :product
belongs_to :cross_sales_product, :class_name => "Product"
acts_as_list :scope => :product
end
create_table :cross_sales, :force => true, :id => false do |t|
t.integer :product_id, :cross_sales_product_id, :position
end
But the field cross_sales.position is never updated ...
An idea ?
Update: Ok the field 'id' it's necessary in the case of additional model with has_many :through option. It's work well now
In the accepted answer, note that :order => 'artist_events.position' is referencing the table artist_events and not the model.
I ran into this minor hiccup when moving from a habtm association to has_many :through.