Rails外键是嵌套形式的nil

时间:2009-12-14 00:12:35

标签: ruby-on-rails associations

我有几个模型(网站和服务器)通过has_many:through彼此相关。他们也都属于:用户。在我的站点/新视图中,我创建了一个新站点,并使用嵌套的form.fields_for:servers创建了一个新服务器。一切都按预期工作,除了最终创建的服务器没有填充user_id。我如何确保它?

我的sites_controller new和create方法:

 def new
    @user = current_user
    @site = @user.sites.build
    @servers = @user.servers.all

    # let there be one server linked
    @site.site_servers.build

    # @user.servers.build if @user.servers.empty?
    @site.servers.build( :user_id => current_user.id ) if @site.servers.empty?

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @site }
    end
  end

  def create
    @site = current_user.sites.build(params[:site])

    respond_to do |format|
      if @site.save
        flash[:notice] = 'Site was successfully created.'
        format.html { redirect_to(@site) }
        format.xml  { render :xml => @site, :status => :created, :location => @site }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @site.errors, :status => :unprocessable_entity }
      end
    end
  end

如果您注意到注释行,那些是我尝试过的不起作用的东西。

型号:

class User < ActiveRecord::Base
  acts_as_authentic

  has_many :sites
  has_many :servers
end

class Site < ActiveRecord::Base

  belongs_to :user

  has_many :site_servers
  has_many :servers, :through => :site_servers

  accepts_nested_attributes_for :site_servers, :allow_destroy => true
  accepts_nested_attributes_for :servers, :allow_destroy => true

  validates_presence_of :name, :on => :create, :message => "Name is required"
end

class Server < ActiveRecord::Base
  attr_encrypted :password, :key => '393b79433f616f445f652a752d', :attribute => 'crypted_password'

  belongs_to :user

  has_many :site_servers
  has_many :sites, :through => :site_servers

  validates_presence_of :url, :on => :create, :message => "URL is required."
  validates_presence_of :username, :on => :create, :message => "Username is required."
  validates_presence_of :password, :on => :create, :message => "Password is required."


  def name
    username + "@" + url
  end

  def to_s
    name
  end

end

class SiteServer < ActiveRecord::Base
  belongs_to :site
  belongs_to :server

  has_one :user, :through => :site
end

这是我的架构:

ActiveRecord::Schema.define(:version => 20091203045550) do

  create_table "servers", :force => true do |t|
    t.string   "url"
    t.string   "username"
    t.string   "crypted_password"
    t.integer  "port"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "site_servers", :force => true do |t|
    t.integer  "site_id"
    t.integer  "server_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "sites", :force => true do |t|
    t.string   "name"
    t.string   "url"
    t.string   "path"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "users", :force => true do |t|
    t.string   "username"
    t.string   "email"
    t.string   "crypted_password"
    t.string   "password_salt"
    t.string   "persistence_token"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

2 个答案:

答案 0 :(得分:2)

服务器表单中的user_id是否有隐藏字段?

<%= f.hidden_field :user_id %>

如果没有,即使您设法正确设置,该值也不会被传回。如果您向表单添加隐藏字段,那么您已注释掉的行将起作用。

@site.servers.build(:user_id => current_user.id) if @site.servers.empty?

我实际上喜欢在create方法中更好地设置用户ID的想法,因为否则你会引入某人制作他们自己的表单提交和在其他人的用户id下创建事物的可能性。我不知道安全性在您的应用中是否是一个大问题,但我从不相信从表单发送的用户ID。

答案 1 :(得分:1)

我猜这个问题出在你的create行动中。新操作只是构建Ruby对象 - 您需要确保在create action中有类似的构建代码:

def create
  @site = current_user.sites.build(params[:site])
  @site.save
end