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
精彩评论