activerecord without Rails: get related records - ruby

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.

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.

Rails get related items through two different relationships

I have a "two middleman" model setup as shown below:
User
has_many :comments
has_many :ratings
Comment
belongs_to :user
belongs_to :movie
Rating
belongs_to :user
belongs_to :movie
Movie
has_many :comments
has_many :ratings
Whats the best way to get all Movies that a User is associated with (either commented on or rated)?
I'd like to be able to call User.get_movies(user_id) and get back an ActiveRecord::Relation object so that it's chainable (i.e. User.get_movies(user_id).limit(3).order(...)). This returns a regular old array, and I suspect I'm hitting the database way more than I need to be.
def self.get_movies(user_id)
user = self.where(:id => user_id).includes({:comments => :movie}, {:ratings => :movie})
movies = []
user.comments.each do |comment|
movies.push(comment.movie)
end
user.ratings.each do |rating|
movies.push(rating.movie)
end
movies.uniq!
end
def movies
Movie.includes(:ratings, :comments).where("`ratings`.user_id = ? OR `comments`.user_id = ?", self.id, self.id)
end
Untested, but I'm pretty sure using a joins instead of includes also works.

How do I convert Rails 2 hash merge to Rails 3?

How do I convert the following Rails 2 code to Rails 3 scope, I'm trying to remove .merge(:conditions) and move entirely to Rails 3 activerecord scope.
class Customer < ActiveRecord::Base
def self.find_invoice_by_customer(customer_address, opts={})
invoice = Customer.find(opts.merge(:conditions => {:address => customer_address }))
end
end
Customer.find_invoice_by_customer(#address, :condition => ["customer_name = ?", #customer.name])
You could use scopes and the new finder methods to chain them:
class Customer < ActiveRecord::Base
scope :by_address, lambda {|address| {:conditions => {:address => address }}
end
Customer.by_address(#address).where("customer_name = ?", #customer.name)
Does this help ? I recommend you have a look at the documentation and the Railscast about Active Record.

ruby on rails 3 scope extensions and includes

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.

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