Question

I have privacy settings for users to set. Privacy settings can be as such:

  • Do not show my updates on the public timeline
  • Do not show my email address
  • Do not show my birth date

I thought of having privacy settings embedded in the User collection.

class User
  include Mongoid::Document
  include Mongoid::Timestamps

  embeds_many :privacies
  ...
end

class Privacy
  include Mongoid::Document

  field :title, :type => String
  field :description, :type => String
  field :is_active, :type => Boolean

  embedded_in :user, :inverse_of => :privacies
  ...
end

My form looks like:

<%= form_for(@user, :url => user_path(@user)) do |f| %>
  <ul>
    ...
    <% @user.notifications.each do |notification| %>
      <li>
        <%= check_box_tag 'user[notifications][]', notification.id, notification.is_active %>
        <%= label_tag notification.description %>
      </li>
    <% end %>

    <li class="clearfix">
      <%= image_submit_tag('update.png', :class => 'submit') %>
    </li>
  </ul>
<% end %>

When the form submits. It has the following params:

{"utf8"=>"✓", "_method"=>"put", 
"authenticity_token"=>"FQvGlJ8p+SPX8MIQqMjS04tHVLQ4jEl31tpAoKwGYDE=", "user"=>{"city_id"=>"", 
"notifications"=>["4ce3c66872357e0a95000011", "4ce3c66872357e0a95000012"]}, "action"=>"update", 
"controller"=>"users", "id"=>"1234"}

As you can see from above. Its submitting the notification ids as an array: "notifications"=>["4ce3c66872357e0a95000011", "4ce3c66872357e0a95000012"]}

In my Users controller, update method. I have:

def update
  @user = User.where(:id => params[:id]).first

  # Unset all notifications for user
  @user.notifications.each do |notification|
    notification.update_attributes!(:is_active => false)
  end

  # Based on the form, set notifications
  params[:user][:notifications].each do |notification|
    @user.notifications.find(notification).update_attributes!(:is_active => true)
    # @user.notifications.first.update_attributes!(:is_active => false)
  end

  # Remove the notifications from params
  params[:user][:notifications] = []

  respond_to do |format|
    if @user.update_attributes(params[:user])
    ...
  end
end

My update method looks a bit messy, because:

1) I am resetting all check boxes by setting :is_active to false.

2) After, I am looking through the params for all notification ids and setting each one's :is_active to true.

3) Finally, I remove the notifications array from params, otherwise my form doesn't not save properly.

Is there a better / cleaner way to get this to work with Mongoid? Or perhaps, is there a better approach to designing this? I was thinking of using many-to-many instead of embedded.

What are your thoughts?

After,

Was it helpful?

Solution

Looks fine. You could clean it up a little bit but it won't make much difference.

I.e.

# loop and set these to false
user.notifications.not_in(:id => params[:user][:notifications])

# loop and set these to true
user.notifications.any_in(:id => params[:user][:notifications])
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top