开发者

Changing which Rails Validations run depending on current user in deeply nested form

I'm working with a nested form that encompasses a total of 7 models, each with different validations. When simply editing the form, the validations run and display fi开发者_如何学Cne, and data is saved properly. However, I need to have different validations run depending on who is submitting the form (ie, admins can skip some otherwise required fields).

I thought I could get certain validations to be skipped by using attr_accessible :editing_user in my models, then set this within the controller.

class ModelExample < ActiveRecord::Base
  attr_accessible :editing_user
  validates_presence_of :email, :unless => "editing_user == 'admin'"
end

class ModelExamplesController < ActionController::Base
  def create
    @model_example = ModelExample.new(params[:model_example])
    @model_example.editing_user = 'admin'
    @model_example.save
  end
end

I used this basic structure within the nested models, checking to see if I could save properly. This is where the weird behavior starts. For some reason, it looks like ActiveRecord is trying to save nested models multiple times, running validations each time. What makes this odd is I call @model_example.save, which should just return false if it fails. But, the first validation goes through (since editing_user is set), but later validations fail and raise exceptions, so the normal .save methods ends up raising an exception instead of returning.

Does anyone know how to either avoid having ActiveRecord do all extra validations and saves, or how to persist editing_user across those duplicate actions?


ha! just did this yeasterday, well, almost same use case anyway (persist the user). Here is how i solved it (with all credit to my buddy Jason Dew that I copied from):

class User < ActiveRecord::Base

  module ClassMethods
    attr_accessor :current
  end

  extend ClassMethods
end

This code block adds a singleton accessor :current to the User class methods, and can be called as User.current. nicer looking that a method called self.currrent

then in the app controller

before_filter :require_user #=> which in this case goes off and sets the current_user var
before_filter {|c| User.current = current_user}

which passes the app controller to the block and sets the User.current var.

Then in any other model

class MyClass < ActiveRecord::Base
  def log
    "This was done by #{User.current}"
  end
end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜