ruby-on-railsnested-attributeshas-oneactiveview

Managing child relationships with a nested attribute form


What I'm trying to do is the following:

At anyone time a user can have 1 active profile. This active profile must be authorized by an administrator to make sure that it is compliant with the rules and regulations of the site. When a user edits their profile their public profile is unaffected until the administrator signs off their changes. If they make an edit while their profile is in review, their edits are applied to the outstanding profile for review and is pushed to the back of the queue.

My models look something like this:

class Profile < AR:B
    belongs_to :user
end

class User < AR:B
    has_many :profiles do
        def active
            ...
        end
        def latest
        end
    end
    def profile
        self.profiles.active
    end
end

There is one small twist... the user should not be able to edit the profile directly, as the profiles collection is not exposed. Instead they edit their user and the profile fields are shown there.

What's the best way to manage this? Currently I'm using:

accepts_nested_attributes_for :profiles

In the user, but that seems quite hacky. Ideally most of this logic would live in the model, but the other thing I'm flirting with is the use of a presenter.

Any thoughts would be greatly appreciated, let me know if you need more information as a comment and I'll update this post appropriately.


Solution

  • Maybe you should try having two relationships from user to profile. One is the one they can edit through your User interface, and the other is the one that is approved by the administrator.

    It could work something like:

    class User < AB:B
    
    has_one :profile #the user-editable one one
    has_one :active_profile, :class_name=>"profile" #the one shown
    
    end
    

    Each changes on the User profile through the form would then show for the Admin (using and observer or maybe just and "after_save" filter). When it aproves it, the changes are then dumped to the active_profile one, and shown somewhere.

    That way, you can have a clean form interface, and whenever they edit it again, they see the latest (but not approved) profile. You can also order the Queue using the updated_at column to gain the "their edits are applied to the outstanding profile for review and is pushed to the back of the queue" funcionality.