Require scope in activeadmin resource - ruby-on-rails

I am using activeadmin and need to figure out how to require a scope to only show records pertaining to the current user.
I also have other scopes that users can select, but those scopes need to be "pre-scoped" so to speak so that only records belonging to that user are available at any given time.
I hope this makes sense. I'm fairly new to all of this, so i'm not real sure where to start. Thanks in advance for any help.

Did you try scoping with scope_to :current_user ?
AA has some examples with docs . Here they are
http://activeadmin.info/docs/2-resource-customization.html#scoping_the_queries
current_user is helper method to get currently logged in user (currend_admin_user is default I think)
code from AA initializer
# This setting changes the method which Active Admin calls
# to return the currently logged in user.
config.current_user_method = :current_user
If you had some kind of metod in your model that use your logged in user you can do something like that
controller do
def scoped_collection
Post.some_method(current_user)
#or for example Post.select(current_user.visible_posts_columns) ... etc
end
end

Related

Testing a Rails ApplicationController method with rspec

Just having trouble figuring out how to test an action that utilizes a private ApplicationController method. To explain:
A User has and belongs to many Organisations (through Roles), and vice versa. An Organisation has a bunch of related entities, but in the app a user is only dealing with a single Organisation at a time, so for all of my controller methods I want to scope with a current organisation. So in my ApplicationController:
private
# Returns the organisation that is being operated on in this session.
def current_org
# Get the org id from the session. If it doesn't exist, or that org is no longer operable by the current user,
# find an appropriate one and return that.
if (!session[:current_organisation_id] || !current_user.organisations.where(['organisations.id = ?', session[:current_organisation_id]]).first)
# If an org doesn't exist for this user, all hope is lost, just go to the home page
redirect_to '/' if (!current_user.organisations.first)
# Otherwise set the session with the new org
session[:current_organisation_id] = current_user.organisations.first.id;
end
# Return the current org!
current_user.organisations.first
end
First things first, I don't know if this is the best way to scope. I'd love some elegant default_scope thing, but with the use of session variables this seems problematic. Anyway, the above let's me do this in controllers:
class HousesController < ApplicationController
def index
#houses = current_org.houses
end
end
So now I want to use rspec to test my controllers. How can I make sure the current_org method can be called and returns one of the factory_girl Organisation models so that I can write the spec. I'm just confused at how best to bring the factory, spec, action and AppControlled method together.

Rails devise user function

How do I execute a particular function after a user has signed up.
(I wanted to add to one of my associations, I already have it coded in a non-devise rails but now I need it here)
Device has provided helper action 'after_sign_in_path_for' you can override it within your application controller.
def after_sign_in_path_for(resource_or_scope)
.... #write your customize code or call any method
end
For sign up it would look like:
def after_sign_up_path_for(resource_or_scope)
if resource_or_scope.is_a? User # and perhaps other conditions
#... do something, go somewhere
else
super
end
end
Ofc. Assuming that your Devise user model is called User.
You can use the after_create callback in your User model.
The following guide has tons of examples: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

method_missing and association_proxy in rails

So, here's my problem. I currently am building a simple authentication system for a rails site. I have 3 classes for this: Person, Session, and Role. In my Person model I have defined method_missing to dynamically capture roles according to this guide.
In my application_controller I have some logic to deal with logins and log-outs, the result of which gives me the currently logged in user via:
#user = #application_session.person
Where #application_session is the current session
Now in one of my controllers, I don't want anyone to be able to do anything unless they are an admin, so I included:
before_filter #user.is_an_admin?
This raises a NoMethodError, even though I have method_missing defined in my model. I tried defining is_an_admin?, having it always return true as a test, and that works.
According to this question, I think the problem might have something to do with proxy associations. When I run:
puts #user.proxy_owner
I get a session object, since each user (Person) can have many sessions, and I got my user (Person) from the current session.
I am very confused why #user.is_an_admin? is not calling the method_missing method in my Person controller. Please let me know if you need more information or code snippets.
I am using Rails 3 on Ruby 1.9
I'd consider a method_missing an overkill for such task.
Now, if you have Session class, which belongs_to User, then you can have this:
class Session
belongs_to :user, :extend => PermissionMixin
end
class User
include PermissionMixin
end
module PermissionMixin
def admin?
if cond
true
else
false
end
end
end
P.S. Check cancan, perhaps it'll suit your needs better.
I use a similar permissions check in my system to check the User > Role > Permissions association:
User.current_user.can_sysadmin?
In my controllers I have to instead use:
User.current_user.send('can_sysadmin?')
This may work for you as well.
I have solved this by moving the method_missing method to my application_controller.rb. I change the logic of the method a little to check for a user, and if found, dynamically check the role. If things were not kosher, I had the method redirect to root_url or return true if the user matched the requested roles.
Finally, in my reports controller, I used before_filter :is_an_admin? and got my desired results. However, I am still unclear as to why method_missing had to be defined in my application controller as opposed to directly in the Person (aka #user) model?

how to proper cache a variable in rails

Hi I have a rails App which displays always the company name on each page.
Since a logged in user can have multiple companies she belongs to.
User and companies are stored in the db.
I use authlogic for the user management.
Now I do not want to hit the database on every postback or page change
What would be best practise to chache/store the company until the logged in users changes or the user selects a different company? Something like global instance vars for a given user.
I started with this in my application_controller
def current_company
return #current_company if defined?(#current_company)
#current_company = Account.includes(:users).where(:users =>current_company)
end
and I realized that I am still hitting the db...
Is the session the recommended way or what would be best practice for this...
Thanks for the help in advance
||= way:
def current_company
#current_company ||= Account.includes(:users).where(:users =>current_company)
end
memoize way:
def current_company
Account.includes(:users).where(:users =>current_company)
end
memoize :current_company
Differences between this method and normal memoization with ||=
http://apidock.com/rails/ActiveSupport/memoize#447-Differences-between-normal-or-assign-operator
#tadman, you are right but from my point of view depends how complex its the method that you are trying to "cache". For simple cases I prefer ||=
I think this is what you're looking for
https://github.com/nkallen/cache-money

How to apply permissions

I'm wondering how to implement some permission logic in a Rails 2.3.8 app.
For example, a user can only edit tasks the user created (aka "owns").
Should I do something like this:
user.can_edit_task(task)
or this:
task.can_be_edited_by?(user)
#Method needs to be passed in a user object (from controller). But then how
#can I access the current user in a "before_save" filter as below :
.
def User
before_save: check_permissions!
def check_permissions
#this way?
raise some_exception if task.can_be_edited_by?(user)
#or this way?
raise some_exception if self.can_edit_task?(task)
end
end
Any tips on how to go about this?
Please try to adopt some of existing plugins like cancan
It will save your life.

Resources