2011-01-14 173 views
0

我目前有一個Rails應用程序,可以讓用戶拖放網頁的某些元素,並根據用戶的選擇更新應用程序。這是在Rails助手和AJAX的幫助下完成的。但是我一直在Ruby中遇到一個「NoMethodError」。Ruby中沒有方法錯誤

NoMethodError in ProjectsController#member_change 

undefined method `symbolize_keys' for nil:NilClass 

這裏是被調用的方法。我的痕跡說,錯誤發生在這一行:

before = u.functions_for(r.authorizable_id) 
       u.roles << r unless u.roles.include? r 
       u.save 
       flag_changed = true 
       after = u.functions_for(r.authorizable_id) 

,這裏是被調用的函數

def member_change 
    flag_changed = false 
    params['u'] =~ /role_(\d+)_user_(\d+)/ 
    drag_role_id = $1 
    user_id = $2 
    params['r'] =~ /role_(\d+)/ 
    drop_role_id = $1 
    if u=User.find(user_id) 
     if r=Role.find(drop_role_id) 
     if drag_role_id.to_i !=0 and old_r=Role.find(drag_role_id) 
      if drag_role_id == drop_role_id #fom A to A => nothing happen 
      flash.now[:warning] = _('No Operation...') 
      elsif r.authorizable_id == old_r.authorizable_id #the same project? 
      old_r.users.delete(u) 
      unless old_r.valid? 
       flash.now[:warning] = _('Group "Admin" CAN NOT be EMPTY.') 
       old_r.users << u #TODO: better recovery 
       member_edit #if flag_changed 
       render :action => :member_edit, :layout => 'module_with_flash' 
       return 
      end 
      old_r.save 
      r.users << u unless r.users.include? u 
      r.save 
      flag_changed = true 
      before = u.functions_for(r.authorizable_id) 
      after = u.functions_for(r.authorizable_id) 
      added = after - before 
      removed = before - after 
      added.each do |f| 
       ApplicationController::send_msg(:function,:create, 
               {:function_name => f.name, 
               :user_id => u.id, 
               :project_id => r.authorizable_id 
               }) 
      end 
      removed.each do |f| 
       ApplicationController::send_msg(:function,:delete, 
               {:function_name => f.name, 
               :user_id => u.id, 
               :project_id => r.authorizable_id 
               }) 
      end 
      flash.now[:notice] = _('Move User to Group') + " #{ r.name }" 
      else 
      flash.now[:warning] = 
       _('You can\'t move User between Groups that belong to different Projects.') 
      end 
     else 
      before = u.functions_for(r.authorizable_id) 
      u.roles << r unless u.roles.include? r 
      u.save 
      flag_changed = true 
      after = u.functions_for(r.authorizable_id) 
      added = after - before 
      added.each do |f| 
      ApplicationController::send_msg(:function,:create, 
              {:function_name => f.name, 
               :user_id => u.id, 
               :project_id => r.authorizable_id 
              }) 
      end 
      flash.now[:notice] = _('Add User into Group') + " #{ r.name }" 
     end 
     else 
     flash.now[:warn] = _('Group doesn\'t exist!') + ": #{ r.name }" 
     end 
    else 
     flash.now[:warning] = _('User doesn\'t exist!') + ": #{ u.login }" 
    end 
    member_edit #if flag_changed 
    render :action => :member_edit, :layout => 'module_with_flash' 
    end 

和JavaScript用來調用函數

jQuery('#RemoveThisMember').droppable({accept:'.RolesUsersSelection', drop:function(ev,ui){ 
    if (confirm("This will remove User from this Group, are you sure?")) 
    {jQuery.ajax({data:'u=' + encodeURIComponent(jQuery(ui.draggable).attr('id')), success:function(request){jQuery('#module_content').html(request);}, type:'post', url:'/of/projects/11/member_delete'});} 
    }, hoverClass:'ProjectRoleDropDelete_active'}) 

任何想法?

謝謝,

回答

0

重構時間!可能進入大約五分之一的方法。

我懷疑functions_for方法是原因,你能否粘貼它的定義?

與此同時,一些一般性建議:

  • 給你的變量的全名 - user代替u
  • 你不需要保留一個flag_changed var,檢查user.changed? (也是user._new_record?)。
  • 你應該有你的路由設置,這樣你就不需要正則表達params對象。
  • 您應該幾乎不會有超過幾個級別的條件 - 重構爲外部方法。
  • 這幾乎可以肯定是用ApplicationController :: send_msg方法(logging?)來做任何事情的更好方法。如果您不能使用現有項目,請在ApplicationController中將其設爲幫助程序方法。

我懷疑你最近是否已經從低一級的語言轉換過來?你會發現擁抱紅寶石約定會爲你節省很多時間和代碼。

只是好奇,_方法做什麼?

希望這是有幫助的。

+0

哈哈不幸的是,這不是我的選擇。 – TheRealVayne 2011-01-14 09:26:59