rails: has_many with 2 relations fields - ruby-on-rails

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"

Related

Ruby on Rails how to distinguish multiple relationships between same models

So I have the following models
User, Course, Order, Line_item
User (seller) has_many :courses (as the instructor, uploading them)
On the other hand...
User (buyer): has_many :orders
Order: has many :line_items
line_item: belongs_to :course
So I want a list of all courses purchased by a buyer, can I at this point use #user.courses to do so? How can I distinguish between buyer.courses and seller.courses?
Any help is appreciated. Thanks!
You need to use self-referential association for this.
#cousre.rb
Class Course < ActiveRecord::Base
belongs_to :sellar, :class_name => 'User', :foreign_key => 'sellar_id'
end
#order.rb
Class Order < ActiveRecord::Base
belongs_to :buyer, :class_name => 'User', :foreign_key => 'buyer_id'
end

how to setup two user_id columns in one model in rails?

I have two models
class User
has_many :disputes
end
class Dispute
belongs_to :user
end
So Dispute has :user_id, but my problem is that a Dispute has 2 sides - the claimant and the indicted, both of which are users.
I tried to solve this problem by creating two columns: :claimant_id and :indicted_id, and passing arguments like #dispute.claimant_id = current_user.id, but after that I can't use a relationship tricks like #dispute.user.name or #user.disputes with my :claimant_id and :indicted_id.
Is there any way to set up two :user_id (like a claimant and an indicted) in one model and still maintain the relationships between Dispute and User models?
You can go the route of having :claimant_id and :indicted_id on your users table, but in your class def you need
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
Reference: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to
I think this is a duplicate of Ruby on Rails Double Association
For your case use class_name as the second parameter to your belongs_to function and a hash with foreign_key and the id column name (as pointed out by #devkaoru), like so:
class Dispute < ActiveRecord::Base
belongs_to :claimant, class_name: 'User', :foreign_key => :claimant_id
belongs_to :indicted, class_name: 'User', :foreign_key => :indicted_id
end
I think that should do it up right.
Disclaimer: This is an untested solution

Rails isn't using my `foreign_key` in a belongs_to association

I have two models, AssetEvent and Subsystem, and a join model between them AssetEventSubsystem. They look like this:
RehabEvent < AssetEvent
has_many :asset_event_subsystems
has_many :subsystems, :through => :asset_event_subsystems
AssetEventSubsystem
belongs_to :rehab_event, :class_name => 'AssetEvent', :foreign_key => "asset_event_id"
belongs_to :subsystem
Subsystem
belongs_to :asset_type
When I try to run RehabEvent.new.asset_event_subsystems.build, I get back a ActiveRecord::UnknownAttributeError: unknown attribute: rehab_event_id, which is confusing, because I thought that should have been taken care of by the foreign_key option in the join model.
How do I make rails use the column in my database (asset_event_id) instead of the default?
Looks like u need that: ?
RehabEvent < AssetEvent
has_many :asset_event_subsystems
has_many :subsystems, :through => :asset_event_subsystems,
:foreign_key => "asset_event_id"
AssetEventSubsystem
belongs_to :rehab_event, :class_name => 'AssetEvent', :foreign_key => "asset_event_id"
belongs_to :subsystem
Subsystem
has_many :asset_event_subsystems
has_many :rehab_events, :through => :asset_event_subsystems
belongs_to :asset_type
And btw, i dont know your project, but can you use just has_and_belongs_to_many ?
You need to define the foreign_key on your has_many association as well as your belongs_to:
has_many :asset_event_subsystems, foreign_key: 'asset_event_id'

How to "order by" using has_many through?

I have two tables with a join table between them:
Parent: Pages
Child: Things
Join: Grids
In my models they are set up with a many to many relationship (has_many through):
class Page < ActiveRecord::Base
belongs_to :books
has_many :grids
has_many :things, :through => :grids
end
class Thing < ActiveRecord::Base
has_many :grids
has_many :pages, :through => :grids
end
class Grid < ActiveRecord::Base
belongs_to :page
belongs_to :thing
end
Now I want to be able to sort "things" using an ordering id from grid, called number, how can I do that ?
Thanks!
you need the ":include(s)" option in your find method, and then "order_by()" ...
you would use something like this:
Thing.where(...some condition or all..., :include => :grid ).order_by(grid.number)
See:
http://guides.rubyonrails.org/active_record_querying.html
http://m.onkey.org/active-record-query-interface
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

acts_as_list with has_and_belongs_to_many relationship

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.

Resources