ruby on rails 3 scope extensions and includes - ruby

I am experimenting with scope extensions and was wondering if I could do something like this.
class User
has_many :tasks
belongs_to :klass
scope :users_in_klass, lambda {|k| where(:klass_id => k)} do
def current_task_report
includes(:tasks)
users = []
each {|u|
user = {
:name => u.full_name,
:id => u.id,
:tasks => u.tasks
}
users << user
}
users
end
end
And call it like this
u = User.users_in_klass(6899)
u.current_task_report
The problem I'm having is that it's ignoring the includes on the tasks for eager loading.
User Load (0.5ms) SELECT `users`.* FROM `users` WHERE (`users`.`klass_id` = 6899)
Task Load (0.4ms) SELECT `tasks`.* FROM `tasks` WHERE (`tasks`.user_id = 46539)
Task Load (0.2ms) SELECT `tasks`.* FROM `tasks` WHERE (`tasks`.user_id = 46909)
Task Load (0.2ms) SELECT `tasks`.* FROM `tasks` WHERE (`tasks`.user_id = 46910)
Is what I'm am doing correct?
On a side note, Is there a better place to put the current_task_report method?
Cheers,
Tim

I think you need to move the includes statement into your lambda
class User
has_many :tasks
belongs_to :klass
scope :users_in_klass, lambda {|k| includes(:tasks).where(:klass_id => k)} do
def current_task_report
users = []
each {|u|
user = {
:name => u.full_name,
:id => u.id,
:tasks => u.tasks
}
users << user
}
users
end
end

What about adding this association to your Klass:
class Klass < ActiveRecord::Base
has_many :users
has_many :tasks, :through => :users
end
Then getting the current task report would look something like this:
Klass.find(6899).tasks
I am assuming Rails will be smart enough to automatically do an "IN" statement in the resulting query.

Related

ActiveRecord get all + associated details

I am trying to retrieve a list of all tasks, where each task has a developer and reviewer. I am able to retrieve the list but it contains developer_id and reviewer_id. How do I retrieve a list containing developer name and retriever name?
class Person < ActiveRecord::Base
end
class Unread_Object < ActiveRecord::Base
belongs_to :person
end
class Developer < Person
has_many :tasks
end
class Reviewer < Person
has_many :tasks
has_many :unread_objects
end
class Task < ActiveRecord::Base
belongs_to :developer
belongs_to :reviewer
has_many :documents
after_save :add_task_to_unread_objects
protected
def add_task_to_unread_objects
Person.find_each do |person|
Unread_Object.create(
:person_id => person.id,
:internal_object_id => self.internal_object_id,
:unread_cause => 'Create')
end
end
end
Things I have tried.
get '/taskslist' do
#Task.includes([:developer, :reviewer]).all.to_json
#Task.joins(:developer,:reviewer).select("tasks.*, people.*").to_json #works somewhat but only shows one name
#Task.includes(:reviewer.name,:developer.name).all.to_json #"undefined method `name' for :reviewer:Symbol"
#Task.find(:all, :include => {:people => :name}).to_json #Couldn't find all Tasks with 'id': (all, {:include=>{:people=>:name}})
end
I hope to get Tasks json with nested json for developer, reviewer and other objects.
This question is follow up of this.
After some searching found as_json(include: <association>)
So this works
Task.includes(:developer,:reviewer).all.as_json(include: [:developer,:reviewer]).to_json
But other alternatives need to be seen.

merge ActiveRecord::Relation with ActiveRecord::Associations

I have 2 models
class User < ActiveRecord::Base
has_many :games
def created_games
Game.where(created_by: self.id)
end
end
class Game < ActiveRecord::Base
belongs_to :user
end
u = User.take
joined_games = u.games
created_games = u.created_games
the variable joined_games is a instance of ActiveRecord::Associations, and created_games is an instance of ActiveRecord::Relation.
Is there any way I can join joined_games and created_games together?
Try adding a scope in User model
scope :joined_games, where(user_id: self.id, created_by: self.id)

activerecord without Rails: get related records

I'm trying to use a relationship between tables,
the primary key in both tables has the same name adm_id
(i know, i know, but have no control over the db)
I use activerecord without Rails in JRuby.
When i get the related records (the emails) i get the error below.
Could somoene help me out ?
require 'java'
require 'activerecord-jdbc-adapter'
require "C:/jruby-1.7.4/bin/ojdbc14.jar"
Java::OracleJdbcDriver::OracleDriver
ActiveRecord::Base.establish_connection(
:adapter => 'jdbc',
:driver => 'oracle.jdbc.driver.OracleDriver',
:url => 'jdbc:oracle:thin:#xxxxxx:xxxx:xxx',
:username=>'xxx',
:password=>'xxx'
)
class Adm < ActiveRecord::Base
self.table_name = 'scheme1.db_all'
self.primary_key = 'adm_id'
has_many :emails
end
class Email < ActiveRecord::Base
self.table_name = 'scheme2.db_email'
self.primary_key = 'adm_id'
belongs_to :adm, :foreign_key => 'adm_id'
end
lid = Adm.where(adm_id: 99999999).take(1) #ok
email = Email.where(adm_id: 99999999).take(1) #ok
p lid.emails
#error: NoMethodError: undefined method `emails' for #<Array:0x19bc716>
If you just want a single record, don't pass any arguments to take:
lid = Adm.where(adm_id: 3441029).take
email = Email.where(adm_id: 3441029).take
p lid.emails
If any argument is supplied to take, even if it's 1, an array of results is returned.

rails: how do I build an active-relation scope to traverse many tables?

I have these tables and relationships:
user has_many projects
project has_many tasks
task has_many actions
I would like to build a scope that allows me to select all of the current users actions, regardless of what project or task they belong to.
Thanks
I don't think scopes are necessary for this if you use the nested_has_many_through plugin.
class User < ActiveRecord::Base
has_many :projects
has_many :tasks, :through => :projects
has_many :actions, :through => :tasks
end
class Project < ActiveRecord::Base
has_many :tasks
has_many :actions, :through => :tasks
end
User.first.actions
I found something that works.
In the Actions model:
def self.owned_by (user)
joins("join tasks on actions.task_id = tasks.id").
joins("join projects on tasks.list_id = projects.id").
where("projects.user_id = ?" , user.id)
end
From the console:
u=User.find(1)
Action.owned_by(u).count
=> 521 # which is correct
I'm mot sure if its the best way to do it as I'm a bit new to sql. I get the feeling it could be made more concise.
EDIT Slightly better
Action.joins(:task => [{:project => :user }]).where(:projects => {:user_id => user.id })

ActiveRecord :through to set default values on through table

I would like to set a default value in a has_many through association.
Lets say I have three models:
People
Friends
Dogs
A person can request that a dog becomes their friend.
So a person would create an association where friends has an active column = false.
User
has_many :friends
has_many :dogs, :through => :friends
Now when I assign a dog to a user
User.find(1).dogs << dog
The friends table has null in the active column.
My friends model is defined as
Friend
def initialize(args = {})
super(args)
active = false
end
yet this does not work because the friend object is never created. Do I have to manually create one?
To set default values of a model; In the model I do this
before_save :default_values
private
def default_values
self.status = :active unless self.status
end
Not sure if this is the correct approach though.
With the following code you'll create a new friend with active = false
class User < ActiveRecord::Base
has_many :friends, :conditions => "active = false"
has_many :dogs, :through => :friends
end
#user = User.new
#user.friends.create #or #user.friends.build

Resources