新手问题 关于 Redmine 源码中一个方法的定义与调用....没看懂 T^T

hisoul · 2015年01月07日 · 最后由 hisoul 回复于 2015年01月08日 · 3088 次阅读

问题 1:ruby 的方法参数数量不对不是会报错的吗? 问题 2:方法调用时最后的参数中 :if => 是什么意思?

以下是 safe_attributes 方法的调用

safe_attributes 'status_id',
  'assigned_to_id',
  'fixed_version_id',
  'done_ratio',
  'lock_version',
  'notes',
  :if => lambda {|issue, user| issue.new_statuses_allowed_to(user).any? }

safe_attributes 'notes',
  :if => lambda {|issue, user| user.allowed_to?(:add_issue_notes, issue.project)}

以下是 safe_attributes 方法的定义

# Safely sets attributes
# Should be called from controllers instead of #attributes=
# attr_accessible is too rough because we still want things like
# Issue.new(:project => foo) to work
def safe_attributes=(attrs, user=User.current)
  return unless attrs.is_a?(Hash)

  attrs = attrs.dup

  # Project and Tracker must be set before since new_statuses_allowed_to depends on it.
  if (p = attrs.delete('project_id')) && safe_attribute?('project_id')
    if allowed_target_projects(user).where(:id => p.to_i).exists?
      self.project_id = p
    end
  end

  if (t = attrs.delete('tracker_id')) && safe_attribute?('tracker_id')
    self.tracker_id = t
  end

  if (s = attrs.delete('status_id')) && safe_attribute?('status_id')
    if new_statuses_allowed_to(user).collect(&:id).include?(s.to_i)
      self.status_id = s
    end
  end

  attrs = delete_unsafe_attributes(attrs, user)
  return if attrs.empty?

  unless leaf?
    attrs.reject! {|k,v| %w(priority_id done_ratio start_date due_date estimated_hours).include?(k)}
  end

  if attrs['parent_issue_id'].present?
    s = attrs['parent_issue_id'].to_s
    unless (m = s.match(%r{\A#?(\d+)\z})) && (m[1] == parent_id.to_s || Issue.visible(user).exists?(m[1]))
      @invalid_parent_issue_id = attrs.delete('parent_issue_id')
    end
  end

  if attrs['custom_field_values'].present?
    editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
    # TODO: use #select when ruby1.8 support is dropped
    attrs['custom_field_values'] = attrs['custom_field_values'].reject {|k, v| !editable_custom_field_ids.include?(k.to_s)}
  end

  if attrs['custom_fields'].present?
    editable_custom_field_ids = editable_custom_field_values(user).map {|v| v.custom_field_id.to_s}
    # TODO: use #select when ruby1.8 support is dropped
    attrs['custom_fields'] = attrs['custom_fields'].reject {|c| !editable_custom_field_ids.include?(c['id'].to_s)}
  end

  # mass-assignment security bypass
  assign_attributes attrs, :without_protection => true
end

你调用的是另一个同名方法

def safe_attributes(*args)
  @safe_attributes ||= []
  if args.empty?
    if superclass.include?(Redmine::SafeAttributes)
      @safe_attributes + superclass.safe_attributes 
    else
      @safe_attributes
    end
  else
    options = args.last.is_a?(Hash) ? args.pop : {}
    @safe_attributes << [args, options]
  end
end

#1 楼 @serco 函数定义在别的 rb 文件里面吗?

#2 楼 @hisoul grep 找一下就知道了

#3 楼 @chenge 用 Grep 在整个项目里找了一下 没找到有同名方法......

需要 登录 后方可回复, 如果你还没有账号请 注册新账号