Join scope in Rails 3 - ruby-on-rails

I'd like to write a Rails 3 scope, on Client, to do the following:
select * from clients c, dependents d
where d.last_name like '%ss%' and c.id = d.client_id;
Dependent model:
class Dependent < ActiveRecord::Base
belongs_to :client
scope :by_last_name, (lambda do |name| { :conditions => ['last_name LIKE ?', "#{name}%"]} end )
Client model:
class Client < ActiveRecord::Base
has_many :dependents, :dependent => :destroy
I have not yet been able to get a scope join to work syntactically. The dependent's last name needs to be passed in as a parameter.
Thanks.

Try this:
class Client < ActiveRecord::Base
scope :by_last_name, lambda { |last_name| includes(:dependents).where("dependents.last_name LIKE ?", "#{last_name}%") }
then call
Client.by_last_name "last_name"
Edit: Changed the code to reflect your problem.
Also find_by_id(1) is the same as find(1) except that it does not throw an error when nothing is found, instead it returns nil.

Try the following:
scope :by_last_name, lambda {|name| where("dependents.last_name like ?", "'%#{name}%'")

Related

joins a scoping model

I did't find doc about that.
I have two models, Token and Connection
class Connection < ActiveRecord::Base
belongs_to :token
scope :failed, -> { where('...') }
end
class Token < ActiveRecord::Base
has_many :connections
end
I know that we can join like this Tokens.joins(:connections) but I'm trying to do something like this Token.joins(:connections => :failed)
Do you think it's possible?
I just found
Token.joins(:connexions).merge(Connection.failed)
you can add default scope on Connection model like
class Connection < ActiveRecord::Base
belongs_to :token
default_scope where(' Your condition ')
end
so Tokens.joins(:connections) will give you only those tokens whose connections match your condition in scope.
you can check this link as well https://apidock.com/rails/ActiveRecord/Base/default_scope/class

Creating a named scope that includes an associated model

The model Organizer has_many events.
Event has attributes begin_day:date and published:boolean.
I have the following query for events that haven't ocurred yet:
#organizer.events.order('begin_day asc').where('begin_day >= ?', Date.today).where(published: true).limit(8)
which I would like to extraxt to a scope such that it's implemented something like this:
#organizer.upcoming_events.limit(8)
How do I do create this scope though that includes an associated model?
Try smth like this:
scope :upcoming_events, -> { joins(:events).where("events.begin_day >= ?", Date.today).where(events: {published: true}).order('events.begin_day asc') }
The has_many and belongs_to helpers automatically create fields and scopes that easily allow you to join two models, in a user defined scope you have to join those models manually. ;)
class Event
belongs_to :organizer
end
class Organizer
has_many :events
scope :upcoming_events, joins(:events).order('begin_day asc').where('begin_day >= ?', Date.today).where(published: true)
# lol007's query
scope :upcoming_events, -> { joins(:events).where("events.begin_day >= ?", Date.today).where(events: {published: true}).order('events.begin_day asc') }
end
end
Reading #TheChamp's reasoning in his answer, it seems like just doing a method pasting in the query part works equally well. Chainable as well.
class Event
belongs_to :organizer
end
class Organizer
has_many :events
def upcoming_events
self.events.order('begin_day asc').where('begin_day >= ?', Date.today).where(published: true)
end
end
end
This works now:
#organizer.upcoming_events.limit(8)

Rails 3 joining a related model with it's default scope

I'm trying to query across models with the following setup
Class Scorecard < AR::Base
default_scope where(:archived => false)
belongs_to :user
has_many :scorecard_metrics
end
Class ScorecardMetric < AR::Base
belongs_to :scorecard
end
Class User < AR::Base
has_many :scorecards
end
I am trying to query from scorecard metrics with a named scope that joins scorecard and I want it to include the default scope for scorecard, my current implementation (which works) looks like this
# on ScorecardMetric
scope :for_user, lambda {
|user| joins(:scorecard).
where("scorecards.user_id = ? and scorecards.archived = ?", user.id, false)
}
This just seems messy to me, is there any way to join and include the default scope of the joined association?
Looks like I found the answer I was looking for, I just did this
scope :for_user, lambda { |user| joins(:scorecard).where('scorecards.user_id = ?', user.id) & Scorecard.scoped }
which is much nicer without the duplicated logic

Combine Scope with current_user

i have a scope like this :
class InventoryItem < ActiveRecord::Base
belongs_to :inventory
belongs_to :game_item
# define custom scopes to get equipped inventory items for user
scope :equipped, where(:is_equipped => 1)
scope :item, lambda { |item_type|
joins(:game_item).
includes(:game_item).
where("game_items.item_type = ?", item_type ).
limit(1)
}
can i get the current_user model that also includes equipped items in one command ? (with includes maybe ?)
Assuming that your inventory belongs to a user, you could include the current_user model using this:
scope :equipped, where(:is_equipped => 1).includes(:inventory => :user)
This tells Rails to include the inventory model and the associated user model for that inventory. If you wanted to do the same for the item scope you could do this:
scope :item, lambda { |item_type|
includes(:game_item).
includes(:inventory => :user).
where("game_items.item_type = ?", item_type ).
limit(1) }

Help with a Join in Rails 3

I have the following models:
class Event < ActiveRecord::Base
has_many :action_items
end
class ActionItem < ActiveRecord::Base
belongs_to :event
belongs_to :action_item_type
end
class ActionItemType < ActiveRecord::Base
has_many :action_items
end
And what I want to do is, for a given event, find all the action items that have an action item type with a name of "foo" (for example). So I think the SQL would go something like this:
SELECT * FROM action_items a
INNER JOIN action_item_types t
ON a.action_item_type_id = t.id
WHERE a.event_id = 1
AND t.name = "foo"
Can anybody help me translate this into a nice active record query? (Rails 3 - Arel)
Thanks!
Well I think I solved it myself. Here's what I did
e = Event.find(1)
e.action_items.joins(:action_item_type).where("action_item_types.name = ?", "foo")
Ehm, why not define
has_many :action_item_types, :through => :action_items
and refer to
e.action_item_types.where(:name => "foo")
?
or (as long as "name" is a unique column name)
e.action_items.joins(:action_item_type).where(:name => "foo")

Resources