the new and create actions will now build the resource with attributes based on ability conditions hash - closes #114

This commit is contained in:
Ryan Bates 2010-09-03 11:53:47 -07:00
parent 1be5bf7a57
commit a744377ac9
5 changed files with 41 additions and 4 deletions

View File

@ -206,6 +206,14 @@ module CanCan
message.blank? ? nil : message
end
def attributes_for(action, subject)
attributes = {}
relevant_can_definitions(action, subject).map do |can_definition|
attributes.merge!(can_definition.new_attributes) if can_definition.base_behavior
end
attributes
end
private
def unauthorized_message_keys(action, subject)

View File

@ -67,6 +67,14 @@ module CanCan
hash
end
def new_attributes
attributes = {}
@conditions.each do |key, value|
attributes[key] = value unless [Array, Range, Hash].include? value.class
end
attributes
end
private
def subject_class?(subject)

View File

@ -51,7 +51,15 @@ module CanCan
def build_resource
method_name = @options[:singleton] ? "build_#{name}" : "new"
resource_base.send(*[method_name, @params[name]].compact)
resource = resource_base.send(*[method_name, @params[name]].compact)
initial_attributes.each do |name, value|
resource.send("#{name}=", value)
end
resource
end
def initial_attributes
@controller.current_ability.attributes_for(@params[:action].to_sym, resource_class)
end
def find_resource

View File

@ -257,6 +257,14 @@ describe CanCan::Ability do
@ability.can?(:read, 123 => Range).should be_true
end
it "should have initial attributes based on hash conditions of 'new' action" do
@ability.can :manage, Range, :foo => "foo", :hash => {:skip => "hashes"}
@ability.can :create, Range, :bar => 123, :array => %w[skip arrays]
@ability.can :new, Range, :baz => "baz", :range => 1..3
@ability.cannot :new, Range, :ignore => "me"
@ability.attributes_for(:new, Range).should == {:foo => "foo", :bar => 123, :baz => "baz"}
end
describe "unauthorized message" do
after(:each) do
I18n.backend = nil

View File

@ -5,6 +5,7 @@ describe CanCan::ControllerResource do
@params = HashWithIndifferentAccess.new(:controller => "abilities")
@controller = Object.new # simple stub for now
stub(@controller).params { @params }
stub(@controller).current_ability.stub!.attributes_for { {} }
end
it "should load the resource into an instance variable if params[:id] is specified" do
@ -47,12 +48,16 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@ability).should == :some_resource
end
it "should build a new resource with no arguments if attribute hash isn't specified" do
it "should build a new resource with attributes from current ability" do
@params[:controller] = "people"
@params[:action] = "new"
mock(Ability).new { :some_resource }
person = Object.new
mock(Person).new { person }
mock(person).name = "foobar"
stub(@controller).current_ability.stub!.attributes_for(:new, Person) { {:name => "foobar"} }
resource = CanCan::ControllerResource.new(@controller)
resource.load_resource
@controller.instance_variable_get(:@ability).should == :some_resource
@controller.instance_variable_get(:@person).should == person
end
it "should not build a resource when on index action" do