I have various roles defined by CanCan in my rails application. I recently implemented jQuery UI autocomplete and it works well. The problem is that when I submit the form, the find_by_name that occurs in the model can find records that do not belong to the current_user. I have the following in my view:
<strong><%= f.label :inventory_name, "Material" %></strong>
<%= f.text_field :inventory_name, :class => "inputbox" %><br>
And my jQuery looks like:
jQuery("input[id$=_inventory_name]").autocomplete({
source: '/ajax/inventory',
minLength: 2
});
Then I have an ajax controller that does the right thing:
def inventory
inventory = Inventory.accessible_by(current_ability)
if params[:term]
like= "%".concat(params[:term].concat("%"))
names = inventory.where("name LIKE ?", like)
else
names = inventory
end
list = names.map {|u| Hash[ :id => u.id, :label => u.name, :name => u.name]}
render :json => list
end
But my model does not:
def inventory_name=(name)
inventory = Inventory.find_by_name(name)
if inventory
self.inventory_id = inventory.id
else
errors[:inventory_name] << "Invalid name entered"
end
end
def inventory_name
Inventory.find(inventory_id).name if inventory_id
end
find_by_name will return the first match it finds regardless of who owns it. Ideally I’d like to change:
inventory = Inventory.find_by_name(name)
to
inventory = Inventory.accessible_by(current_ability).find_by_name(name)
But that violates the principles of MVC not to mention the model has no access to current_ability, current_user or the like. So my question is, how to I move this logic into my controller where I have access to these things? I can’t seem to wrap my head around it 🙁
I ended up needing both a before and after filter:
…
I’m not sure if it is the best way to do it, but it works.