Rails Scope Find with Current User

Rails scope find with current user

If you're running this code in a lot of your controllers, you should probably make it a before filter, and define a method to do that in your ApplicationController:

before_filter :set_product, :except => [:destroy, :index]

def set_product
@product = current_user.admin? ? Product.find(params[:id]) : current_user.products.find(params[:id])
end

I don't know what you use to determine if a user is an admin or not (roles), but if you look into CanCan, it has an accessible_by scope that accepts an ability (an object that controls what users can and can't do) and returns records that user has access to based on permissions you write yourself. That is probably really what you want, but ripping out your permissions system and replacing it may or may not be feasible for you.

Ruby on Rails scope test for current user

You can't do this, nor should you. There is no "current" user at the database level.

You need to pass the user object in to a class-level method:

def self.open_for_user(user)
where(:contact_id => user.id)
end

How to create a scope for current_user.following?

There are 2 things you may approach:

  1. Find all users who are following someone

    class User < ActiveRecord::Base
    scope :following_to, -> (user_id) {
    where(
    "id IN ( SELECT followed_id
    FROM relationships
    WHERE follower_id = ?
    )",
    user_id
    )
    }
    end
  2. Find all users who are following anyone, that means they are a follower

    class User < ActiveRecord::Base
    scope :follower, -> {
    where("id IN ( SELECT followed_id FROM relationships)")
    }
    end

Finally, you can use these scope as your expectation:

# Find all users who are following to User (id = 1)
User.following_to(1)

# Find all users who are following someone,
# aka they are a follower
User.follower

default_scope for current_user

I'm not sure why you want to do this at all. The best approach is to use the controller to scope your models. This type of thing doesn't belong to the model.

def index
@albums = current_user.albums
end

If you want to avoid the repetition, create methods to retrieve the object. So instead of this:

def show
@album = current_user.albums.find(params[:id])
end
def edit
@album = current_user.albums.find(params[:id])
end
# etc...

You can do this:

def index
albums
end
def show
album
end
def update
if album.update(album_params)
end
# etc...

private
def albums
@albums ||= current_user.albums
end
def album
@album ||= current_user.albums.find(params[:id)
end

You can even avoid calling the album method from the action by using a before_filter, but this is not a good way. You always tend to forget to add and remove actions from the filter.

before_action :set_album, only: [:show, :edit, :update, :destroy]
def set_album
@album ||= current_user.albums.find(params[:id])
end

Then your instance variables are created in one place. As @wacaw suggested, if this appeals to you, you can take it further and use the decent_exposure gem. Personally, I am happy to stop at the controller and use instance methods in my views.

If you have more complex authorisation needs I suggest you use pundit or cancan, although the latter does not appear to be actively maintained.

There is more on decent_exposure on Rails Casts. If you really fancy this type of scoping, look at this Rails Cast on Multitenancy with Scopes. But that is meant for organisations that have many of users, not a single user.

.current_user not working when using scopes?

One solution is to create a scope in the link that takes an argument user_id and in your controller has_scope with no arguments, and just pass a hash to apply_scopes method to override the supplied values of your scope.

Link Model

scope :of_user,->(user_id){ where(user_id: user_id)}

Link Controller

has_scope :of_user

Just call apply_scopes(Link, of_user: current_user.id).all where of_user is just the applied params for the named scope.

search records by user in the scope

No, you can not call current_user in model. This helper is only available in controllers/views.

You can change the scope to accept an argument:

scope :por_empresa, ->(user) { where(IdEmpresa: user.empresa_id) }

Now you can use it in controller as follows (passing the current_user object as an argument to scope):

Model.por_empresa(current_user)

Of course you can optimize it a bit by passing only user's id:

scope :por_empresa, ->(user_id) { where(IdEmpresa: user_id) } # model
Model.por_empresa(current_user.id) # usage

P.S. it looks like a bad practice to me having non-english words in your code base..

RoR Filter Out Current User with Join, Select and Order

This should do the trick:

@users = ...
@users = @users.where.not(users: {id: current_user.id})

Note that you need to specify name of the table (not the model) when you do the join, otherwise database will have no idea which id column it should look for (users.id vs departments.id).

Before Rails 4

not method is quite a new thing and is not available in Rails 3. (In fact, where method wasn't expecting to be called without arguments, that's why the error you got is unexpected number of arguments (0 for 1)).

Those were dark times when we had to use the following monstrosity to get stuff working:

@users = ...
@users = @users.where('users.id != ?', current_user.id)

Rails ActiveRecord: Find All Users Except Current User

It is possible to do the following in Rails 4 and up:

User.where.not(id: id)

You can wrap it in a nice scope.

scope :all_except, ->(user) { where.not(id: user) }
@users = User.all_except(current_user)

Or use a class method if you prefer:

def self.all_except(user)
where.not(id: user)
end

Both methods will return an AR relation object. This means you can chain method calls:

@users = User.all_except(current_user).paginate

You can exclude any number of users because where() also accepts an array.

@users = User.all_except([1,2,3])

For example:

@users = User.all_except(User.unverified)

And even through other associations:

class Post < ActiveRecord::Base
has_many :comments
has_many :commenters, -> { uniq }, through: :comments
end

@commenters = @post.commenters.all_except(@post.author)

See where.not() in the API Docs.



Related Topics



Leave a reply



Submit