rails auditor gem - audits.user_id may not be NULL - ruby-on-rails

I'm using the auditor gem to track changes in my models, and I find it quite annoying that whenever I'm trying to work from console I get this error (I guess user_id is taken from current_user and it's not associated).
I'm trying to create some objects for development, and just have to do it from the dbconsole every time..
I use 'audit(:create, :update, :destroy)' and not 'audit!'.
Does anyone knows if I can suppress these errors or disable the user_id null check? (I don't care that if in production I run console and create an object, I'll have a NULL there).
Many thanks,
Zach

I had the same issue. Problem was that I didn't have any attr_accessible declared. Read this: https://github.com/collectiveidea/audited#gotchas
edit:
Also, I had to define a method for current_user:
def current_user
User.find_by_username 'root'
end

Why don't you just set current_user to a user object before your audit work?
current_user = User.first
...your other code here

Related

Ruby on Rails - Active Admin: Conflict with a Global Variable

On Rails 4 with the latest version of Active Admin (using Ransack). I have an Award model that I made available globally in my application_controller.rb:
before_action :set_awards
private
def set_awards
#awards = Award.all
end
This is so I could have a global navigation dropdown listing all awards (on the public side). I think this is conflicting with Active Admin. When I went to the Awards index page, I got the following error message:
Collection is not a paginated scope. Set collection.page(params[:page]).per(10) before calling :paginated_collection.
I am not sure what this means exactly but since this is the only model this happens to, I'm guessing it has something to do with my code in the app controller. I think my problem is similar to this question:
Rails 3.2 ActiveAdmin 'Collection is not a paginated scope.' error
...I would prefer not to change the model's label and the metasearch code provided doesn't work because (I think) Active Admin now uses Ransack. Thanks for any help.
I have had the same problem and it was a variable name i was declaring at the application controller that was conflicting with the ActiveAdmin.
I have a model called Post and in my applicationController i had a method like this:
def load_posts
#posts = Post.all
end
It returned me the error you mention, so i fixed it changing the variable name to:
def load_posts
#post_list = Post.all
end
Hope it helps.
May be you overwrited a local variable #awards in ApplicationController, but Active Admins is inheriting from the application controller.
Just rename your variable and it will run.

Rails: activeadmin overriding create action

I have an activeadmin resource which has a belongs_to :user relationship.
When I create a new Instance of the model in active admin, I want to associate the currently logged in user as the user who created the instance (pretty standard stuff I'd imagine).
So... I got it working with:
controller do
def create
#item = Item.new(params[:item])
#item.user = current_curator
super
end
end
However ;) I'm just wondering how this works? I just hoped that assigning the #item variable the user and then calling super would work (and it does). I also started looking through the gem but couldn't see how it was actually working.
Any pointers would be great. I'm assuming this is something that InheritedResources gives you?
Thanks!
I ran into a similar situation where I didn't really need to completely override the create method. I really only wanted to inject properties before save, and only on create; very similar to your example. After reading through the ActiveAdmin source, I determined that I could use before_create to do what I needed:
ActiveAdmin.register Product do
before_create do |product|
product.creator = current_user
end
end
Another option:
def create
params[:item].merge!({ user_id: current_curator.id })
create!
end
You are right active admin use InheritedResources, all other tools you can see on the end of the page.
As per the AA source code this worked for me:
controller do
def call_before_create(offer)
end
end

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?

Deleting all records in a database table

How do I delete all records in one of my database tables in a Ruby on Rails app?
If you are looking for a way to it without SQL you should be able to use delete_all.
Post.delete_all
or with a criteria
Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')"
See here for more information.
The records are deleted without loading them first which makes it very fast but will break functionality like counter cache that depends on rails code to be executed upon deletion.
To delete via SQL
Item.delete_all # accepts optional conditions
To delete by calling each model's destroy method (expensive but ensures callbacks are called)
Item.destroy_all # accepts optional conditions
All here
if you want to completely empty the database and not just delete a model or models attached to it you can do:
rake db:purge
you can also do it on the test database
rake db:test:purge
If you mean delete every instance of all models, I would use
ActiveRecord::Base.connection.tables.map(&:classify)
.map{|name| name.constantize if Object.const_defined?(name)}
.compact.each(&:delete_all)
BlogPost.find_each(&:destroy)
If your model is called BlogPost, it would be:
BlogPost.all.map(&:destroy)
More recent answer in the case you want to delete every entries in every tables:
def reset
Rails.application.eager_load!
ActiveRecord::Base.descendants.each { |c| c.delete_all unless c == ActiveRecord::SchemaMigration }
end
More information about the eager_load here.
After calling it, we can access to all of the descendants of ActiveRecord::Base and we can apply a delete_all on all the models.
Note that we make sure not to clear the SchemaMigration table.
If you have model with relations, you need to destroy models that are related as well.
The fastest way to achieve this:-
Want to delete all data from the table
Post.delete_all
Want to delete specific data from the table, then the right way to do it is
Post.where(YOUR CONDITIONS).delete_all
# this above solution is working in Rails 5.2.1, delete_all don't expect any parameter
# you can let me know if this works in different versions.
# In the older version, you might need to do something like this:-
Post.delete_all "Your Conditions"
This way worked for me, added this route below in routes.rb
get 'del_all', to: 'items#del_all' # del_all is my custom action and items is it's controller
def del_all #action in ItemsController
if Item.any?
Item.destroy_all
redirect_to items_url, notice: "Items were destroyed."
else
redirect_to items_url, notice: "No item found here."
end
end
According to documentation:
2.5 Singular Resources - Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the >profile of the currently logged in user. In this case, you can use a singular >resource to map /profile (rather than /profile/:id) to the show action: get 'profile', to: 'users#show'

Rails3 - Permission Model Before_Save Check?

I have a permission model in my app, that ties (Users, Roles, Projects) together.
What I'm looking to learn how to do is prevent a user for removing himself for their project...
Can you give me feedback on the following?
class Permission < ActiveRecord::Base
.
.
.
#admin_lock makes sure the user who created the project, is always the admin
before_save :admin_lock
def before_save
#Get the Project Object
project = Find(self.project_id)
if project.creator_id == current_user.id
# SOME HOW ABORT OR SEND BACK Not Allowed?
else
#continue, do nothing
end
end
end
Is that look like the right approach?
Also, I'm not sure how to do the following two things above:
How to abort prevent the save, and send back an error msg?
Get the devise, current_user.id in the model, that doesn't seem possible, so how do Rails gurus do stuff like the above?
Thanks for reading through
How to abort prevent the save, and send back an error msg?
return false during the callback chain tells activemodel to stop (similar to how adding errors to the model during a validation tells it to stop at that point)
self.errors.add_to_base "msg" will add an error to the model, which can then be rendered on the view.
Get the devise, current_user.id in the model, that doesn't seem possible, so how do Rails gurus do stuff like the above?
Models shouldn't really know about things like the current request, if at all possible, you should be locking things down at the controller/action level.
EDIT:
So, the role of controllers is to deal with everything involved in getting the correct information together based on the request, and passing it to the view (which becomes the response). People often say "make your models fat and your controllers skinny", but that could be said of any system that embraces object oriented design -- your logic should be in objects when possible.
That being said, the whole point of controllers is to deal with routing the right things to the right places, and authentication is definitely a concern of routing.
You could easily move the line comparing creator_id to user id in the action, and react based on that.
Now, sometimes you genuinely need that stuff in the model and there is no way around it. That becomes a problem, because you need to fight rails to get it there. One way would be to attr_accessor a current_user field on your model, and pass that in on initialize. Another would be to remove the fields from the params hash that a user is not allowed to change in the action. Neither is really that nice though.
Agreed with Matt that you should try to use the controller for the redirect. The model should have the logic to determine if the redirect is appropriate. Maybe something like
class ProjectsController < ApplicationController
def update
redirect_to(projects_url, :alert => "You can't remove yourself from this project.") and return if Role.unauthorized_action?(:update, params[:project])
#project = Project.find(params[:id])
if #project.update_attributes(params[:project])
...
end
class Role
def self.unauthorized_action?(action, params)
# your logic here
end
You should check out CanCan for some ideas.
In permission model take one field project_creater as boolean
In project modelbefore_create :set_project_ownership
def set_project_ownership
self.permissions.build(user_id: User.current.id, project_creater: true)
end
In project controllerbefore_filter :set_current_user
In Application controllerdef set_current_user
User.current = current_user
end

Resources