How to resolve 'Remove from your finder: :includes => [:company]' - ruby-on-rails

When I try to write nested relation, I got bellow warning and can't get company data.
Unused Eager Loading detected
User => [:company]
Remove from your finder: :includes => [:company]
I write bellow code.
When I check about sql. it looks like to make relation with user and company.
But this controller result can't get company data.
Do you know how to resolve this issue?
controller/product.rb
def products
Product
.sale_date_between(params[:from], params[:to])
.organization(current_user.company_id)
.order('sale_date DESC')
end
models/product.rb
belongs_to :user
scope :with_user, -> { includes(:user, {user: :company}) }
scope :sale_date_between, ->(from, to) { where('sale_date_date >= ?', from).where('sale_date_date <= ?', to) }
scope :company, ->(id) { with_user.where(users: { company_id: id }) }
models/user.rb
has_many :products
models/company.rb
belongs_to :user, foreign_key: 'company_id'

Related

select specific attributes from array rails

I have post model
class Post < ActiveRecord::Base
acts_as_voteable
end
and Vote model
class Vote < ActiveRecord::Base
scope :for_voter, lambda { |*args| where(["voter_id = ? AND voter_type = ?", args.first.id, args.first.class.name]) }
scope :for_voteable, lambda { |*args| where(["voteable_id = ? AND voteable_type = ?", args.first.id, args.first.class.name]) }
scope :recent, lambda { |*args| where(["created_at > ?", (args.first || 2.weeks.ago)]) }
scope :descending, order("created_at DESC")
belongs_to :voteable, :counter_cache=>true,:polymorphic => true,:touch=>true
belongs_to :voter, :polymorphic => true
attr_accessible :vote, :voter, :voteable
# Comment out the line below to allow multiple votes per user.
validates_uniqueness_of :voteable_id, :scope => [:voteable_type, :voter_type, :voter_id]
end
when I get the post voters with these method
<% #post.voters_who_voted.each do |voter|%>
<%= voter.name %>
<% end %>
I load my database
how can I select only the user name and user id from these array?
update I changed my code I am using thumbs_up gem I pasted less code first to simplify the question
What do you mean by "load database"? If you want to select only id and name columns, then use #post.users.select([:id, :name]).each ...
Or is it about this problem (according to code that you provided)?
UPD.
voters_who_voted loads all voters and returns array https://github.com/bouchard/thumbs_up/blob/master/lib/acts_as_voteable.rb#L113. You have to add own association to Post model:
has_many :voters, :through => :votes, :source => :voter, :source_type => 'User'
It's just example, perhaps voters will clash with already existing method, if any.
Then use it here instead of voters_who_voted
did you try collect method ??
names = #post.users.collect(&:name)
ids = #post.user.collect(&:id)
If you want it to be related you can make a HASH with it. Id's mapped to the names.

Is it possible to assign multiple has_many ":as" polymorphic relation on same field?

Having my db setup like this ("type" is always User although I have different kind of User via STI):
class User
# fields
# :id
# :sender_id, :sender_type
# :recipient_id, :recipient_type
end
Postcard model:
class Postcard < ActiveRecord::Base
belongs_to :owner, :class_name => User
belongs_to :recipient, :class_name => User
end
I'd like to setup the User model something like this:
class User < ActiveRecord::Base
has_many :postcards, :as => [:sender or :recipient] # this is not working
end
So I could say:
user.postcards
Is it possible?
PS: I've also tried this road:
has_many :postcards, :finder_sql => Proc.new { "SELECT * FROM postcards WHERE postcards.owner_id=#{id} OR postcards.recipient_id=#{id}" }
But found myself stuck on scopes as :finder_sql recreates a whole new SQL:
User.postcards.by_status('new').size
As mentioned by joelparkerhenderson I need to think differently my association strategy.
As I'd like to have:
user.postcards
My answer is simply to use scopes in Postcard model:
scope :of_user, lambda { |user| where("recipient_id = ? OR owner_id = ?", user.id, user.id) }
So I can invoke:
Postcard.of_user user
I could even wrap it in User model:
def postcards
Postcard.of_user self
end

Howto split up multiple joins and conditions

I want to display a list of all projects, where a project
has one or more tasks
AND
has one or more clients OR has flag 'can_have_clients = 0'
AND
current_user has assignment on client
My current query is working, but does not look like the right way:
Project.where('id IN (SELECT DISTINCT project_id FROM tasks)')
.where('id IN (SELECT DISTINCT project_id FROM clients WHERE id IN (
SELECT DISTINCT resource_id FROM assignments WHERE resource_type="Client" AND user_id=?))
OR can_have_clients = 0', current_user)
Is it possible to split up more (specially the last where/OR) and does this look like the way to go with rails?
# model
class Project < ActiveRecord::Base
has_many :tasks
has_many :clients
...
class Task < ActiveRecord::Base
belongs_to :project
...
class Client < ActiveRecord::Base
has_many :assignments, :as => :resource
...
Try this:
Project.joins(:tasks).joins( :clients => :assignments).where(
:projects => { :can_have_clients => 0},
:assignments => { :resource_type => "Client", :user_id => current_user}
).select("DISTINCT project.*")
If you want to eager load tasks and clients and assignments:
Project.include(:tasks).include( :clients => :assignments).
where("tasks.id IS NOT NULL AND clients.id IS NOT NULL AND
assignments.id IS NOT NULL").
where(
:projects => { :can_have_clients => 0},
:assignments => { :resource_type => "Client", :user_id => current_user}
)
I think you can use named_scope here to optimize your query in rails format .
And for performance vice you can make the query like :
Project.where('exists (SELECT 1 FROM tasks where tasks.project_id=project.id)')
.where('exists (SELECT 1 FROM clients WHERE exists (
SELECT 1 FROM assignments WHERE assignments.resource_id=clients.id AND resource_type="Client" AND user_id=?))
OR can_have_clients = 0', current_user)
because in is too costly than exists , check it.

Accessing values in a has_many :through join table

I've got users who are members of groups through a membership join table, and one of the attributes of that join table is "administrator". I'm trying to do a check inside of a group's member view, looping through each member to see if they are an administrator.
In the view I tried the following:
for user in #group.users
if user.administrator?
...DO STUFF
end
end
I also tried this in the controller:
#administrators = #group.memberships.find(:all, :conditions => ["administrator = 1"])
But no luck. Any thoughts?
UPDATE - per below, put a method into the user model:
def is_administrator_of(group_id)
Membership.find(:first, :conditions => ['user_id = ? AND group_id = ? AND administrator = ?', self[:id], group_id, true])
end
I think this would be a cleaner way to do this
class Group < ActiveRecord::Base
has_many :memberships
has_many :users, :through => :memberships
has_many :admins, :through => :memberships, :source => :user,
:conditions => ['memberships.administrator = ?', true]
end
You now have a group.admins list
for user in #group.admins
...DO STUFF
end
Although I think you could setup associations to accomplish this I think the easiest way to do it would be to add a method to your User model that allows you to check for each user (this way it would fit in the loop you have provided). I don't know if it will drop right it, may take a few quick changes but you could start with something like:
User Model
def is_administrator_of(group_id)
Membership.find(:first, :conditions => ['user_id = ? AND group_id = ?', self[:id], group_id]).administrator == 1
end

Rails, ActiveRecord: how do I get the results of an association plus some condition?

I have two models, user and group. I also have a joining table groups_users.
I have an association in the group model:
has_many :groups_users
has_many :users, :through=> :groups_users
I would like to add pending_users which would be the same as the users association but contain some conditions. I wish to set it up as an association so that all the conditions are handled in the sql call. I know there's a way to have multiple accessors for the same model, even if the name is not related to what the table names actually are. Is it class_name?
Any help would be appreciated, thanks
Use named_scopes, they're your friend
Have you tried using a named_scope on the Group model?
Because everything is actually a proxy until you actually need the data,
you'll end up with a single query anyway if you do this:
class User < ActiveRecord::Base
named_scope :pending, :conditions => { :status => 'pending' }
and then:
a_group.users.pending
Confirmation
I ran the following code with an existing app of mine:
Feature.find(6).comments.published
It results in this query (ignoring the first query to get feature 6):
SELECT *
FROM `comments`
WHERE (`comments`.feature_id = 6)
AND ((`comments`.`status` = 'published') AND (`comments`.feature_id = 6))
ORDER BY created_at
And here's the relevant model code:
class Feature < ActiveRecord::Base
has_many :comments
class Comment < ActiveRecord::Base
belongs_to :feature
named_scope :published, :conditions => { :status => 'published' }
This should be pretty close - more on has_many.
has_many :pending_users,
:through => :groups_users,
:source => :users,
:conditions => {:pending => true}
:pending is probably called something else - however you determine your pending users. As a side note - usually when you see a user/group model the association is called membership.
In the User model:
named_scope :pending, :include => :groups_users, :conditions => ["group_users.pending = ?", true]
That's if you have a bool column named "pending" in the join table group_users.
Edit:
Btw, with this you can do stuff like:
Group.find(id).users.pending(:conditions => ["insert_sql_where_clause", arguments])

Resources