2011-06-05 41 views
1

我有我的rails應用程序中由CanCan定義的各種角色。我最近實現了jQuery UI自動完成,它運行良好。問題是,當我提交表單時,模型中發生的find_by_name可以找到不屬於current_user的記錄。我在我的觀點如下:jquery ui自動完成,rails3和CanCan模型訪問問題

<strong><%= f.label :inventory_name, "Material" %></strong> 
<%= f.text_field :inventory_name, :class => "inputbox" %><br> 

我的jQuery的樣子:

jQuery("input[id$=_inventory_name]").autocomplete({ 
    source: '/ajax/inventory', 
    minLength: 2 
}); 

然後,我有一個Ajax控制器,做正確的事:

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 

但我的模型不:

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將返回它找到的第一個匹配,而不管其擁有者是誰。理想情況下,我想改變:

inventory = Inventory.find_by_name(name) 

inventory = Inventory.accessible_by(current_ability).find_by_name(name) 

但違反MVC的原則,不提模型必須current_ability,CURRENT_USER或類似的訪問權限。所以我的問題是,如何將這個邏輯移入我的控制器,在那裏我可以訪問這些東西?我似乎無法左右它:(

回答

1

我最終需要既之前和之後過濾:

after_filter :save_new_project_inventory, :only => [:create] 
before_filter :update_project_inventory, :only => [:create, :update] 

...

private 
def save_new_project_inventory 
    # do this in an after filter so that 
    # we will have a project.id 
    @project_inventories.each { |key, value| 
    value[:project_id] = @project.id 
    ProjectInventory.create!(value) 
    } 
end 

def update_project_inventory 
    @project_inventories = {} 
    params[:project][:project_inventories_attributes].each { |key, value| 
    if value[:_destroy] != "false" 
     project_inventory = ProjectInventory.find(value[:id]) 
     project_inventory.delete 
    else 
     if value[:id] 
     project_inventory = ProjectInventory.find(value[:id]) 
     project_inventory.inventory_id = inventory_name(value[:inventory_name]) 
     project_inventory.save 
     else 
     if @project.nil? 
      # can't save here because we need a project.id that we 
      # won't have until after we save, so finish up in the 
      # after filter 
      @project_inventories[key] = { 
      :inventory_id => inventory_name(value[:inventory_name]) 
      } 
     else 
      project_inventory = ProjectInventory.new 
      project_inventory.inventory_id = inventory_name(value[:inventory_name]) 
      project_inventory.project_id = params[:id] 
      project_inventory.save 
     end 
     end 
    end 
    } 
    params[:project].delete(:project_inventories_attributes) 
end 

def inventory_name(name) 
    inventories = Inventory.accessible_by(current_ability) 
    inventory = inventories.find_by_name(name) 
    if inventory 
    inventory.id.to_s 
    end 
end 

我不知道這是否是做的最好的方式,但它工作

1

我認爲,所有你需要做的是讓你創建和更新操作在控制器檢查Inventory.accessible_by(current_ability)來包裝我的頭。

0

我知道這是舊的,但我有完全相同的問題,直到現在被困住了。我最終爲其他人尋找了一個更簡單的解決方案。

在我的示例中,current_user創建一個作業,該作業需要分配給它的客戶(一個也屬於當前用戶)。 jQuery UI自動完成用於搜索客戶,當然,我只希望屬於當前用戶的客戶可分配給正在創建的作業,這與原始問題非常相似。我的最終解決方案是簡單地將user_id的隱藏字段添加到新作業表單,並在調用新操作時填充user_id。

JobsController 
def new 
    @job = current_user.jobs.new(user_id: current_user.id) 
end 

這樣的模型,我們可以用搶的self.user_id USER_ID(取中值的隱藏字段),然後用它作爲我們查找搜索條件的一部分。爲了便於閱讀,我已將self.user_id分配給變量'user'。

JobModel 
def customer_name=(fullname) 
    user = self.user_id 
    self.customer = Customer.find_by(fullname: fullname, user_id: user) 
end 

就這麼簡單,現在除非兩個搜索詞(在這種情況下:全名),和user_ID的是在客戶模式匹配,沒有結果返回,並要求用戶再次嘗試,甚至如果具有相同全名的記錄存在於具有不同user_id的Customer模型中,則不會被返回。

希望這會有所幫助。

編輯:請記住將user_id添加到允許的參數。