Rails, how to create a scope where a habtm is populated? - ruby-on-rails-3

I have user accounts that has a HABTM relationship to companies. Users can also have zero companies. I would like to write a scope where I only get users that belong to one or more companies. How can I accomplish this?
example model:
class User < ActiveRecord::Base
has_and_belongs_to_many :companies
scope :independent, # ????
end

For no companies:
scope :independent, -> { where(:companies => []) }
for one or more companies:
scope :independent, -> { where("companies <> []") }

Related

Rails admin gem, polymorphic association

How to get the queried data having polymorphic association
I have an 3 models
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class Employee < ApplicationRecord
has_many :pictures, as: :imageable
end
class Product < ApplicationRecord
has_many :pictures, as: :imageable
end```
Employee and Product have column **is_active**.
In rails admin dropdown. I want to display the data where employee and product is **is_active = true.**
Have tried multiple ways to achieve this.
Please let me know if there is any solution?
You can write a custom scope in picture model as below
scope :list_active(imageable_type), -> {
where(imageable_type: imageable_type)
.joins("INNER JOIN #{imageable_type.pluralize} ON
{#imageable_type.pluralize}.id = imageable_id AND
imageable_type = '#{imageable_type}'")
.where('#{imageable_type.pluralize}.is_active = ?', true)
}
Then you can simply list and use the response.
E.g result = []
result << Image.list_active('Employee')
result << Image.list_active('Product')

Rails query records based on attribute of a certain association

I have a three tier model relationship defined like this:
class User < ActiveRecord::Base
has_many :orders
scope :with_key, ->(key) { joins(:orders).merge( Order.with_key(key) ) }
end
class Order < ActiveRecord::Base
belongs_to :user
has_many :tags
scope :with_key, ->(key) { joins(:tags).merge( Tag.with_key(key) ) }
end
class Tag < ActiveRecord::Base
belongs_to :order
attr_accessible :key
scope :with_key, ->(key) { where(key: key) }
end
Basically a user has many orders and each order has many tags. Tags have a field for key. The scope with_key allows me to merge-chain several joins as to allow
User.with_key("some_key") #=> All users whose orders have a tag with "some_key" as key
This is not what I need, however.
How do I find all users whose last order's tags have "some_key" as the key?

Many to many relationship with ability to set a state (active)

I have a fully working (for some time now) many-to-many relationship in my Rails application.
Instructors has many Schools (through SchoolsToInstructorsAssociations)
Schools has many Instructors (through SchoolsToInstructorsAssociations)
At this time, I would like the ability to have an "active state" in addition to simply adding or removing an Instructor from a School or a School from an Instructor.
I want an Instructor to be set as inactive before being removed completely at a later point (or reactivated).
My first thought was to add an 'active' boolean to the relationship model (SchoolsToInstructorsAssociations), but there's no simple way to access this attribute to update or query it).
My second thought was to simply create another relationship model with the 'active' attribute, but it's redundant and something extra I have to track.
Maybe a custom many-to-many module? Create a SchoolsToInstructorsAssociations controller?
class Instructor < ActiveRecord::Base
has_many :schools_to_instructors_association
has_many :schools, :through => :schools_to_instructors_association
end
class School < ActiveRecord::Base
has_many :schools_to_instructors_association
has_many :instructors, :through => :schools_to_instructors_association
end
class SchoolsToInstructorsAssociation < ActiveRecord::Base
belongs_to :user
belongs_to :school
end
I also plan to create a history record each time an instructors 'active' state changes or an instructor is removed or added to a school. Not asking how to do this, but wondering if it could be used to track an instructors 'active' state.
class SchoolsController < ApplicationController
def instructors_index
#school = School.find(params[:id])
instructors = find_instructors
#active_instructors = instructors[0]
#inactive_instructors = instructors[1]
respond_to do |format|
format.html # index.html.erb
format.json { render json: #schools }
end
end
private
def find_instructors
active = []; inactive = []
#school.instructors.each do |s|
if SchoolsToInstructorsAssociationRecord.where(user_id: s, school_id: #school)[0].active?
active << s
else
inactive << s
end
return [active, inactive]
end
end
end
class SchoolsToInstructorsAssociationRecord < ActiveRecord::Base
default_scope order('created_at DESC')
attr_accessor :user_id, :school_id, schools_to_instructors_association_id, :active
end
Sounds like you can accomplish what you're trying to do with scopes. Add a boolean column for 'active' as you described for the 'Instructor' class, then you can add scopes for it:
class Instructor < ActiveRecord::Base
...
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
...
end
Then for a given School, you can get the active (or inactive) instructors for that school:
#school.instructors.active
=> SELECT "instructors".* FROM "instructors" WHERE "instructors"."school_id" = <id> AND "instructors"."active" = 't'
If you wanted to do some operations on all the inactive instructors (like destroy them, as an example), you could do:
Instructor.inactive.map(&:destroy)
And you can of course write whatever custom methods you want for the Instructor or School classes.

Trying to create a scope in rails 3 for has habtm relationship

I'm trying to do a basic search on an active record but am having trouble because of the has_and_belongs_to_many relationship. Below are the records and scopes I've created.
Class Section << ActiveRecord::Base
has_and_belongs_to_many :teachers
attr_accessible :department, :class_size
scope :department_scope, lambda { |dept| where("department = ?", dept) }
scope :teacher_fname_scope, lambda { |n| joins(:teachers) & Teacher.has_first_name(n) }
end
Class Teacher << ActiveRecord::Base
has_and_belongs_to_many :sections
attr_accessible :first_name, :last_name
scope :has_first_name, lambda { |fname| where("first_name = ?", fname) }
end
In Rails 3.2 I'm creating a basic search for my Sections model. Suppose I want to do a search for all Sections with a Teacher with a given first_name.
I've tried it using the scopes above, but all I'm getting back from *Section.teacher_fname_scope* is an empty array.
(I'm actually going to have multiple fields, to let the user also search on Section fields like department and class_size so I'll probably create multiple scopes and ultimately chain them together, e.g. the above search by also limited by department and class_size, but my understanding is the scopes are orthogonal so this won't matter to the question above.)
Thanks for any help.
It looks like the winning scope is:
Class Section << ActiveRecord::Base
scope :teacher_fname_scope, lambda { |n| joins(:teachers).("teachers.first_name = ?", n) }
end
This makes sense but I don't see why the original didn't work, given what Ryan Bates talks about in http://railscasts.com/episodes/215-advanced-queries-in-rails-3?view=asciicast
This is an old question, but since I fell here, I'll leave an answer for whoever hits this question:
class Teacher < ActiveRecord::Base
scope :by_name, ->(name) { where(first_name: name) }
end
class Section < ActiveRecord::Base
has_and_belongs_to_many :teachers
scope :by_teacher_name, ->(name) {
joins(:teachers).merge(Teacher.by_name(name))
}
end

Help doing a dynamic sort?

I have a notifications table which contains different types of notifications for different events.
Inside the table is a notifications_type:string column that contains the type of notification, i.e. "foo" or "bar" or "oof"
I want the user to be able to select what notifications they want to display, so there are checkboxes below the result that correspond to prefs_display_foo:boolean, prefs_display_bar:boolean in the User model.
What is an elegant way for me to set the :conditions in the find to properly display the sorted results? Also, currently I have it as a method in the User model, but how would I do it as a has_many :notifications, :conditions => .....
You could try this
leave the has_many without any conditions and then create a named_scope to handle the preferences, this code is untested
class User
has_many :notifications
def notification_preferences
list = []
list << 'Foo' if prefs_display_foo
list << 'Bar' if prefs_display_bar
# etc...
return list
end
end
class Notification
belongs_to :user
named_scope :preferred,
lambda { |preferences| {
:conditions => ["notifications_type IN (?)", preferences]
}
}
end
# ...
user = User.find(1)
notifications = user.notifications.preferred(user.notification_preferences)