Search code examples
ruby-on-railsrubymongodbmongoidembedded-resource

referencing embedded resources mongo mongoid ruby rails


ruby 2.50 rails 5.1.4 gem 'mongoid' gem 'mongoid_paranoia' gem 'mongoid-tree' gem 'mongoid-autoinc' gem 'mongoid-userstamps'

I am having trouble using an embedded resource.

I have an Account model.

class Account
  store_in collection: 'accounts'

  has_many :email_routes, dependent: :destroy
  embeds_many :labels, as: :labelable

  etc..
end

As you can see, each account has many labels.

class Label
  embedded_in :labelable, polymorphic: true
  belongs_to :email_routes

  field :text, type: String
  field :color, type: String
end

The available labels are specified at the account level...

and I have an EmailRoute, which I want to apply some labels to..

class EmailRoute
  belongs_to :account

  field :email_address, type: String
  has_many :labels, as: :labelable, dependent: :nullify

  # field :labels, type: Array, default: []
end

In the email_routes_controller, I have a simple update action..

def update
  selected_labels = params[:labels]

  @email_route.update_attributes!(labels: selected_labels)

  render json: @email_route
end

params[:labels] contains an array of Label objects. When I patch to the controller, I get the following error/message.

Referencing a(n) Label document from the EmailRoute document via a relational association is not allowed since the Label is embedded.

summary:
In order to properly access a(n) Label from EmailRoute the reference would need to go through the root document of Label. In a simple case this would require Mongoid to store an extra foreign key for the root, in more complex cases where Label is multiple levels deep a key would need to be stored for each parent up the hierarchy.

resolution:
Consider not embedding Label, or do the key storage and access in a custom manner in the application code.):"

Is there any way I can work around this? I know there are many articles regarding embedded but none seemed to quite fit this particular case. Any help is greatly appreciated, as I don't want to lose label data and need them to be specified at the account level.

Thanks!

edit Is something like this going to be the only solution? https://www.cookieshq.co.uk/posts/switching-relationships-with-mongoid

edit 2 ... I have managed to get to this point when calling @account.email_routes[0].labels from within the rails console. The strings in the nested array within selector are the labels I meant to add. However, when I render :json @account.email_route, the labels array is returned empty. How do I use the information within the selector?

#<Mongoid::Criteria

selector: {"_id"=>{"$in"=>["Critical Test updates", "Chill", "New", >"Make", "Cool", "1", "2", "3"]}} options: {} class: Label embedded: true>


Solution

  • This getter in the EmailRoute model does the trick

    def labels
        account.labels.where(:_id.in => self[:labels])
    end