has_many :condition multiple models how to use join here? - sql

I have the following model structure:
Model Visitor
class Visitor < ActiveRecord::Base
has_many: triggers
end
Model Trigger
class Trigger < ActiveRecord::Base
belongs_to :visitor, :inverse_of => :triggers
belongs_to :event, :inverse_of => :triggers
end
Model Event
class Event < ActiveRecord::Base
has_many: triggers
end
I am trying to setup a custom association in Visitor model like so:
has_many: triggers_that_pass_some_condition ,:class_name => "Trigger",
:conditions => ["triggers.some_column >= events.some_column"]
The problem is that it doesn't work .. I am guessing I have to do some kind of join to compare columns of two separate models (that are associated with each other)
I have tried
triggers.some_column >= triggers.event.some_column
That does not work either. Anyone has any suggestions? thanks!

Try the following code..
class Trigger < ActiveRecord::Base
belongs_to :event
belongs_to :visitor
end
# Visitors.rb
has_many :triggers_with_condition, -> { includes(:event).where(some_trigger_column >= event.some_event_column)}, class_name: "Trigger"

Make sure you first add the correct association between Visitor and Trigger in your model setup. From there, you can add a custom association as follows:
class Visitor < ActiveRecord::Base
has_many :approved_triggers, -> { includes(:events).where("events.something = ?", true).references(:events) }, class_name: 'Trigger', inverse_of: :visitor
end
class Trigger < ActiveRecord::Base
belongs_to :visitor, inverse_of :triggers
end
Right now your Trigger class holds no association to a Visitor.

Thanks to the clue from Darpa, I eventually settled on this:
has_many :custom_trigger, {:class_name => "Trigger", :include => :event,
:conditions => ["triggers.some_column >= events.another_column"]}

Related

ActiveRocord query with polymorphic associations

I'm trying to get some records from table, but i don't know how to build this query.
I have some models.
class Request < ActiveRecord::Base
has_many :notifications, as: :source
has_many :decisions, dependent: :destroy
end
class Notification < ActiveRecord::Base
belongs_to :source, polymorphic: true
end
class Decision < ActiveRecord::Base
has_many :notifications, as: :source
belongs_to :request
end
So, I need to get all Notifications where source = some_request or source.request = some_request
Isn't it something simple as -
some_request.notifications
# or
some_decision.notifications
and if source is combination of request & decision then
notifications_ids = some_request.notifications.pluck(:id) +
some_decision.notifications.pluck(:id)
Notification.find(notifications_ids)
Your query should be Notification.where(source_id: some_request.id, source_type: 'Request')
Refer Active record association

How can I reference the same model twice and create the association in a multiple select form?

I have two classes (Game and Report) and want to link them with an additional attribute (default = yes or no).
The game should then have default_reports and optional_reports.
The association is then updated by selecting the default and optional reports in a select (multiple) in the games create/edit form.
I have tried using has_many and through as well as polymorphic associations, but nothing seems to fit the use case, where the associated objects are fixed and you only want to manage associations.
class Game < ActiveRecord::Base
has_many :game_reports
has_many :reports, :through => :game_reports
end
class Report < ActiveRecord::Base
has_many :game_reports
has_many :games, :through => :game_reports
end
class GameReport < ActiveRecord::Base
belongs_to :game
belongs_to :report
end
Any help is appreciated!
Thanks
this is just the model. the view and form to create the records is an entirely different matter.
you can always add a conditions option to has_many. I'm assuming you're going to add default to game_reports so change your class to something like.
class Game < ActiveRecord::Base
has_many :game_reports
has_many :reports, :through => :game_reports
has_many :default_reports, through: :game_reports, source: :report, conditions: { game_reports: { default: true } }
end
Rails 4.2+, use a Polymorphic association with scope and specify the foreign_key and foreign_type options.
class GameReport
belongs_to :report, :polymorphic => true
end
class Game
has_many :game_reports, :as => :report, :dependent => :destroy
has_many :reports, -> { where attachable_type: "GameReport"},
class_name: GameReport, foreign_key: :game_report_id,
foreign_type: :game_report_type, dependent: :destroy
end
Other approachs:
Rails Polymorphic Association with multiple associations on the same model

Rails 3 - model issue, foreign key

I have two models, Like and Photo.
class Like < ActiveRecord::Base
belongs_to :photo, :class_name => "DataLike", :foreign_key => "photo_id"
end
class Photo < ActiveRecord::Base
has_many :likes
end
And now I try to execute this query:
query = Like.select(:photo_id).joins(:photo).count
But I am still getting this error:
uninitialized constant Like::DataLike
Could anyone help me, please, what I am doing wrong?
Thank you so much
You don't seem to have a DataLike model, my best guess is that you want to link to the Photo model:
class Like < ActiveRecord::Base
belongs_to :photo, :foreign_key => "photo_id"
end
class Photo < ActiveRecord::Base
has_many :likes
end
If you leave out the :class_name option, the Photo model is inferred. It's used to specify the class of the linked model, in case it is different from the association name.

Two has_may association with Same model Rail 3

Hi im quite beginner in rails. i have a problem suggestion will be appreciated.
i have two model "user" and "asset"
an "asset" is created by a "user" and asset" can be assigned to a "user" schema is
Asset { id,name,creator_id,assigned_to_id,price,...}
User{ id,name,....}
now in Asset model class association are
class Asset < ActiveRecord::Base
{
#validation
belongs_to :creator ,:class_name=>'User'
belongs_to :assigned_to, :class_name=>'User' ,:foreign_key=>'assigned_to_id'
}
and User Model is
class User < ActiveRecord::Base
{
#any validation and other stuff
has_many :assets #did not specify either this association is for creator , or assigned_to user.how can is specify that??
}
now in Asset show view i can obtain creator name with
#asset.creator.name
but can't assigned_to name
#asset.assigned_to.name =>(error is )undefined method `first_name' for nil:NilClas
and
#asset.assigned_to_id.name=>(error is) undefined method `first_name' for 1:Fixnum
any suggestion how can i make double association with same model
ok solution was in my last comment.
Multiple relation with same model
class Asset < ActiveRecord::Base
belongs_to :creator ,:class_name=>'User'
belongs_to :assigned_to, :class_name=>'User'
end
user.rb
class User < ActiveRecord::Base
has_many :created_assets, :foreign_key => 'creator_id', :class_name => 'Asset'
has_many :assigned_assets , :foreign_key => 'assigned_to_id', :class_name => 'Asset'
end

counter_cache has_many_through sql optimisation, reduce number of sql queries

How I can optimise my SQL queries, to ignore situations like this:
Meeting.find(5).users.size => SELECT COUNT(*) FROM ... WHERE ...
User.find(123).meetings.size => SELECT COUNT(*) FROm ... WHERE ...
I have no idea how to use counter_cache here.
Here is my model relation:
class Meeting < ActiveRecord::Base
has_many :meeting_users
has_many :users, :through => meeting_users
end
class User < ActiveRecord::Base
has_many :meeting_users
has_many :meetings, :through => meeting_users
end
class Meeting_user < ActiveRecord::Base
belongs_to :meeting
belongs_to :user
end
What are the most optimal solutions ?
And how implement counter_cache here ?
Starting from Rails3.0.5 and in newer versions, you are now able to set counter cache to the "linker" model, in your case it will be:
class MeetingUser < ActiveRecord::Base
belongs_to :meeting, :counter_cache => :users_count
belongs_to :user, :counter_cache => :meetings_count
end
It's important to explicitly specify count column names, otherwise the columns used will default to meeting_users_count.
As far as I know you can't use counter_cache with through associations, that's why you should manually increment it.
For example (untested):
class MeetingUser < ActiveRecord::Base
...
after_create { |record|
Meeting.increment_counter(:users_count, record.meeting.id)
}
after_destroy { |record|
Meeting.decrement_counter(:users_count, record.meeting.id)
}
end