2011-01-14 175 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