views:

30

answers:

1

Easy part:

I have model with protected attribute and I have action which can be accessed only by admin, how to force assigning all attributes, so I don't need to do something like this:

@post = Post.find(params[:id])
if params[:post].is_a?(Hash) && params[:post][:published]
  @post.published = params[:post].delete(:published) # delete is to skip warning about protected attribute assignment in update_attributes
end
if @order.update_attributes(params[:post])
  …

Harder part:

I have model with a lot of protected attributes and multiple types of users, some of them could assign only unprotected attributes, some can change only part of protected attributes and some can change all attributes. How to write small readable code in this case without reinventing the wheel?

A: 

Well, I can think of two ways for you to do it. First, in the controller: This assumes that you have a method permitted_to? that checks if the user is allowed to change that attribute

if params[:post]
  params[:post].each_pair do |key, value|
    @post.send("#{key.to_s}=", value) if @current_user.permitted_to?(:update_attribute, :post, key.to_sym)
  end
  @post.save
end

Another way, which is probably not the best one, since you will change the properties of the class, which means that it will affect all the instances of the model.

anyway, assuming that you are using attr_accessible to limit the attributes:

Within your model, do this:

 accessible_attributes = self.class.inheritable_attributes.delete(:attr_accessible)

And also restoring it after might be a good idea.

 self.class.inheritable_attributes.delete(:attr_accessible) = accessible_attributes

This works the same way with attr_protected and attr_readonly

And for the second part. I'd assume that you have an array for each user type with the attributes which they can change.

For instance:

 self.class.inheritable_attributes[:attr_accessible] = 
      Set.new(@current_user.allowed_attributes(:post))

or

 self.class.inheritable_attributes[:attr_protected] = 
      Set.new(@current_user.restricted_attributes(:post))

where allowed_attributes returns an array like ['parent_id', 'published', 'title']

Jimmy Stenke