Updating a document that has both belongs_to and has_many associations

373 views Asked by At

I'm having trouble with my Rails/Mongoid app whenever I'm updating my documents.

I have three collections: owners, vessels and modifications.

class Owner
    include Mongoid::Document
    has_many :vessels
    field :name, type: String
    field :uprn, type: String
end

class Vessel
    include Mongoid::Document   
    belongs_to :owner
    has_many :modifications
    field :name, type: String
    attr_accessor :uprn
end

class Modification
    include Mongoid::Document   
    belongs_to :vessel  
    field :change_description, type: String
end

The idea is that each owner owns several vessels (there's a has_many, belongs_to relationship going on) and that there are several modifications which were done on each vessel (again, has_many, belongs_to relationship).

Creating owners, vessels and changes works just fine. When I try to update an owner, it works. If I try to update a modification, it also works. However, the moment I try to update the vessel that belongs to an owner and has some modifications done on it, I'm getting this error:

NoMethodError in OwnersController#update

undefined method `values' for # Mongoid::Criteria:0xb50d49d0

Here's the code that throws this error. Besides just modifying the data stored in the document, it also checks if the owner's changed (that's where the uprn field comes in) and alters the owner_id accordingly.

def update
    @vessel = Vessel.find(params[:id])
    @owner = Owner.find_by(uprn: params[:vessel][:uprn])
    if @owner.present?
        @vessel.owner_id = @owner.id
        if @vessel.update(vessel_params)
            redirect_to @vessel
        else
            render 'edit'
        end
    else
        @vessel.errors[:base] << "There is no owner with the UPRN entered."
        render 'edit'
    end
end

Note that this only happens when there's a 1-n association between the two. If there's just one modification per vessel (so a has_one, belongs_to association) it works just fine. Same deal if I try to embed - 1-1 embeds update fine, 1-n embeds report the same error. It also works fine if there's just the vessel and its modifications (no association with the owner). The moment vessel is associated with both the owner and its modifications, this thing happens.

I'm using Ruby 1.9.3, Rails 4.2.1, Mongo 2.6.1 and Mongoid 4.0.2.

2

There are 2 answers

0
Nemanja On BEST ANSWER

Apparently the way to fix this is to remove the has_many :vessels from Owner and has_many: modifications from Vessel, so that the resulting code looks like:

class Owner
    include Mongoid::Document
    field :name, type: String
    field :uprn, type: String
end

class Vessel
    include Mongoid::Document   
    belongs_to :owner
    field :name, type: String
    attr_accessor :uprn
end

class Modification
    include Mongoid::Document   
    belongs_to :vessel  
    field :change_description, type: String
end

After removing these two lines, the app works just fine.

1
damianfabian On

The problems it seems to be the field name, if any field include the word "change" the error will appears. Hope this help others.