Rails conditional scope - ruby-on-rails

i wrote this scope for my User model but it isn't working because of the 'or'.
How can i do ?
scope :offline, ->{ where((online: false).or(name: 'Undefined')) }
Thanks

Try this
scope :offline, lambda { where( "online = ? OR name = ?", false, 'undefined') }

Related

Rails 4 scope with argument

Upgrading Rails 3.2. to Rails 4. I have the following scope:
# Rails 3.2
scope :by_post_status, lambda { |post_status| where("post_status = ?", post_status) }
scope :published, by_post_status("public")
scope :draft, by_post_status("draft")
# Rails 4.1.0
scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) }
But I couldn't find out how to do the 2nd and 3rd lines. How can I create another scope from the first scope?
Very simple, just same lambda without arguments:
scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) }
scope :published, -> { by_post_status("public") }
scope :draft, -> { by_post_status("draft") }
or more shorted:
%i[published draft].each do |type|
scope type, -> { by_post_status(type.to_s) }
end
From the Rails edge docs
"Rails 4.0 requires that scopes use a callable object such as a Proc or lambda:"
scope :active, where(active: true)
# becomes
scope :active, -> { where active: true }
With this in mind, you can easily rewrite you code as such:
scope :by_post_status, lambda { |post_status| where('post_status = ?', post_status) }
scope :published, lambda { by_post_status("public") }
scope :draft, lambda { by_post_status("draft") }
In the event that you have many different statuses that you wish to support and find this to be cumbersome, the following may suit you:
post_statuses = %I[public draft private published ...]
scope :by_post_status, -> (post_status) { where('post_status = ?', post_status) }
post_statuses.each {|s| scope s, -> {by_post_status(s.to_s)} }

Issue with merging AR queries

I've been trying all different ways of combining to queries but I'm not having any luck at all. It's either returning one or the other depending on what query I put first. I want it so that it takes all the entries of for_group_with_account and all the entries of for_task_with_account and make one list. It's not the conditions that I want combined but the results of each of them combined. Hope that makes sense.
Here's the scopes in my tickets model:
scope :for_group_with_account, lambda { |account| joins(:group => :accounts).where("accounts.id = ?", account.id) }
scope :for_task_with_account, lambda { |account| joins(:tasks => :account).where("accounts.id = ?", account.id) }
scope :for_account, lambda { |account| for_task_with_account(account).merge(for_group_with_account(account)) }
For the last scope where I combine the scopes I've also tried:
scope :for_account, lambda { |account| for_task_with_account(account) + for_group_with_account(account) }
scope :for_account, lambda { |account| for_task_with_account(account) & for_group_with_account(account) }
scope :for_account, lambda { |account| for_task_with_account(account) && for_group_with_account(account) }
Still none of these are actually taking the two listings and combining them. Very very frustrating. Is there something I'm doing wrong?
Thanks.
scope :for_account, lambda { |account| for_task_with_account(account).for_group_with_account(account) }

Rails 3.1.3 unscoped scope

I've seen a lot of posts regarding this, but none seem to solve my problem. I have a default_scope on a model like so:
default_scope where(:is_active => true).order('LOWER(table.name)');
I have other (normal) scopes, and I want to create an inactive scope using unscoped. I would like to define it as a scope, but it only works when defined as a class method:
# works
def self.inactive
unscoped { where(:is_active => false) }
end
# none of these work
scope :inactive, unscoped { where(:is_active => false) }
scope :inactive, with_exclusive_scope { where(:is_active => true) }
scope :inactive, unscoped.where(:is_active => false)
scope :inactive, lambda { unscoped { where(:is_active => false) } }
scope :inactive, unscoped { lambda { where(:is_active => false) } }
unscoped do
scope :inactive, where(:is_active => false)
end
Is there a way that I missed, or do I have to use a class method to define this scope?
There does not seem to be a way to do this. I opened an issue on the rails repo on github...
Try this
scope :inactive, lambda { unscoped.where(:is_active => false) }

Pass arguments in scope

Can someone provide an example on how to use
scope
and parameters?
For example:
class Permission < ActiveRecord::Base
scope :default_permissions, :conditions => { :is_default => true }
end
I have this code that returns the default_permissions and I want to convert it to return the default permissions for a given user (user_id)
Thanks
new syntax (ruby 1.9+), that will prevent errors even if you don't supply the user -
scope :default_permissions_for, ->(user = nil) { ... }
Use lambda scopes:
scope :default_permissions_for, lambda{|user| { :conditions => { :user_id => user.id, :is_default => true } }
Be careful because not passing a parameter to a lambda when it expects one will raise an exception.

Ruby on Rails: named scope with lambda and an array

named_scope :all_public, lambda { |users|
{ :conditions => ["visibility = ? || (visibility = ? && user_id = ?)", Shared::PUBLIC, Shared::PRIVATE, users] }
}
That works nice for one user, but is there a way to modify it to work where users is an array of user ids?
Something like this and then just pass a single element array for the single ID case
named_scope :all_public, lambda { |users|
{ :conditions => ["visibility = ? OR (visibility = ? AND user_id IN (?))", Shared::PUBLIC, Shared::PRIVATE, users.join(',')] }
}

Resources