Mongoid模型不会通过embeds_one关系持久化has_one

时间:2014-01-30 09:32:41

标签: ruby-on-rails-4 mongoid

我在嵌入基于mongoid4的rails 4 app中遇到了麻烦。在过去的两天里,我一直在寻找答案。所以这是代码。

这是一个教会管理应用程序,具有服务模型,嵌入团队和乐队。每个团队/乐队都有几个角色,例如“总统”,“交流”,指的是用户。

我的模特:

class Service
  include Mongoid::Document
  ...
  embeds_one :team, autobuild: true
  embeds_one :band, autobuild: true
  ...
  accepts_nested_attributes_for :team, :band
end

class Team
  include Mongoid::Document  

  embedded_in :service

  has_one :presidence, :class_name => 'User', autosave: true
  has_one :message, :class_name => 'User', autosave: true
  ...
end

class Band
  include Mongoid::Document
  has_one :lead, :class_name => 'User', autosave: true
  has_one :guitar, :class_name => 'User', autosave: true
  ...
  embedded_in :service
end

class User
  include Mongoid::Document
  embeds_one :profile

  belongs_to :team, :inverse_of => :presidence
  belongs_to :team, :inverse_of => :message

  belongs_to :band, :inverse_of => :lead
  belongs_to :band, :inverse_of => :guitar

  def fullname
    "#{profile.firstname} #{profile.lastname}"
  end

  def self.find_by_talent(talent)
    self.where("profile.talents.name" => talent)
  end
end

服务控制员:

# POST /services
# POST /services.json
def create
  @service = Service.new(service_params)
  respond_to do |format|
    if @service.save
      format.html { redirect_to @service, notice: 'Service was successfully created.' }
      format.json { render action: 'show', status: :created, location: @service }
    else
      format.html { render action: 'new' }
      format.json { render json: @service.errors, status: :unprocessable_entity }
    end
  end
end

...

def service_params
  params.require(:service).permit(:date, :time, :place, :name, :theme, :team => [:id, :precedence, :message ], :band => [:id, :lead, :guitar ])
end

_form.html.erb中的表单:

<%= form_for(@service) do |f| %>
  ...
  <%= f.fields_for @service.team  do |tf| %>
    <%= tf.collection_select :presidence, User.find_by_talent(:presidence), :_id, :fullname, {:include_blank => "select a person"} %>
    <%= tf.collection_select :message, User.find_by_talent(:message), :id, :fullname, {:include_blank => "select a person"} %>
  <% end %>
  <%= f.fields_for @service.band  do |bf| %>
    <%= bf.collection_select :lead, User.find_by_talent(:lead), :id, :fullname, {:include_blank => "select a person"} %>
    <%= bf.collection_select :guitar, User.find_by_talent(:guitar), :id, :fullname, {:include_blank => "select a person"} %>
  <% end %>
  ...
<% end %>

创建服务时,一切似乎运行正常,但这是我在控制台中得到的结果:

2.0.0-p195 :001 > s = Service.last
 => #<Service _id: 52ea18834d61631e7e020000, date: "2014-02-02", time: "10:00", place: "Where it's at", name: "My great name", theme: "The service's theme"> 
2.0.0-p195 :002 > s.team
 => #<Team _id: 52ea18834d61631e7e030000, > 
2.0.0-p195 :003 > s.team.presidence
 => nil 

为什么没有创建s.team.presidence? s.team看起来也很奇怪,结尾逗号......

以下是我的rails日志的内容:

Started POST "/services" for 127.0.0.1 at 2014-01-30 10:16:51 +0100
Processing by ServicesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ph6lbdHC2FbiANn/fGSzHWprenj3fWKXM40Hrsc5+AM=", "service"=>{"date"=>"2014-02-02", "name"=>"My great name", "theme"=>"The service's theme", "time"=>"10:00", "place"=>"Where it's at", "team"=>{"presidence"=>"52ea18324d61631e81010000", "message"=>"52ea18324d61631e81010000"}, "band"=>{"lead"=>"52ea18324d61631e81010000", "guitar"=>"52ea18324d61631e81010000"}}, "commit"=>"Create Service"}
  MOPED: 127.0.0.1:27017 COMMAND      database=admin command={:ismaster=>1} runtime: 0.6610ms
  MOPED: 127.0.0.1:27017 UPDATE       database=service_boot_camp_development collection=users selector={"band_id"=>BSON::ObjectId('52ea18834d61631e7e010000'), "_id"=>{"$nin"=>[]}} update={"$set"=>{"band_id"=>nil}} flags=[:multi]
                         COMMAND      database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 0.5800ms
  MOPED: 127.0.0.1:27017 INSERT       database=service_boot_camp_development collection=services documents=[{"_id"=>BSON::ObjectId('52ea18834d61631e7e020000'), "date"=>"2014-02-02", "time"=>"10:00", "place"=>"Where it's at", "name"=>"My great name", "theme"=>"The service's theme", "team"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e030000')}, "band"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e010000')}}] flags=[]
                         COMMAND      database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 2.7460ms

我想我做错了什么,但我不知道它是在数据库模型中还是在表单中......或其他任何东西......

1 个答案:

答案 0 :(得分:2)

你将无法这样做。创建嵌入文档时,其_id及其所有数据都直接嵌入父文档中。这与关联形成对比,其中具有belongs_to的文档获得指向其关联父文档的外键。在这里,您的User文档每个都有team_idband_id,但是当数据库尝试获取文档时,它无法找到它们,因为您无法直接查询嵌入式文件;你首先需要父文件。有关更多信息,请参阅the Mongoid documentation

另一个潜在问题是您在belongs_to模型中有多个User定义。这也会导致问题,因为对于其中的每一个,Mongoid将尝试创建team_idband_id。您应该单独命名并指定类名;也许像:presiding_team:message_team:lead_band:guitar_band这样的名称等等This answer应该会向您展示它的样子。

我建议将团队和乐队分开引用文档而不是嵌入文档,因为在嵌入文档时,您将无法有效地引用用户。

希望这有帮助。