【问题标题】:Associating Two Models in Rails (user and profile)在 Rails 中关联两个模型(用户和配置文件)
【发布时间】:2009-08-19 09:50:55
【问题描述】:

我是 Rails 新手。我正在构建一个具有用户模型和配置文件模型的应用程序。

我想这样关联这些模型:
- 用户创建帐户后,会自动转到“创建个人资料”页面,并且他创建的个人资料仅与该特定用户相关联。
- 只有拥有个人资料的用户才能对其进行编辑。

我使用 nifty_generators 生成了用户模型。当用户点击提交以创建帐户时,我将他重定向到“新配置文件”视图以创建配置文件。我通过在用户控制器中编辑重定向路径来做到这一点。用户控制器如下所示:

def create
  @user = User.new(params[:user])
  if @user.save
    session[:user_id] = @user.id
    flash[:notice] = "Thank you for signing up! You are now logged in."
    redirect_to new_profile_path
  else
    render :action => 'new'
  end
end

这可以正常工作,但问题是该应用似乎无法识别配置文件已与该特定用户相关联。我能够创建个人资料,但个人资料与用户之间似乎没有关系。

我的个人资料模型列表:belongs_to :user
我的用户模型列表:有 _one :profile

我的 routes.rb 文件列出了以下内容:
map.resources :users, :has_one => :profile
map.resources :profiles

我在配置文件表中有一个 user_id 外键。我的架构如下所示:

create_table "profiles", :force => true do |t|
  t.integer  "user_id"
  t.string   "name"
  t.string   "address1"
  t.string   "address2"
  t.string   "city"
  t.string   "state"
  t.string   "zip"
  t.string   "phone"
  t.string   "email"
  t.string   "website"
  t.text     "description"
  t.string   "category"
  t.datetime "created_at"
  t.datetime "updated_at"
end

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

为了尝试将配置文件连接到用户,我使用以下内容更新了 profiles_controller.rb 文件,我基本上是从 Rails 入门指南推断出来的。我的想法是,在我的应用程序中,配置文件连接到用户的方式与在 Rails 入门应用程序中连接到帖子的方式相同。这是我的配置文件控制器的相关部分。如果有帮助,我可以提供全部内容:

def new
  @user = User.find(params[:user_id])
  @profile = @user.profile.build
end

def create
  @user = User.find(params[:user_id])
  @profile = @user.profile.build(params[:profile])
  if @profile.save
    flash[:notice] = 'Profile was successfully created.'
    redirect_to(@profile)
  else
    flash[:notice] = 'Error.  Something went wrong.'
    render :action => "new"
  end

结束

在对配置文件控制器进行这些更新之后,现在当我在帐户创建屏幕上提交时,我被重定向到一个错误页面,上面写着:

ActiveRecord::RecordNotFound in ProfilesController#new
找不到没有 ID 的用户

这一切似乎都是一个非常简单的 Rails 用例,但我不确定哪些部分是错误的。提前感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails activerecord modeling


    【解决方案1】:

    创建用户时,客户端将重定向到ProfileController 中的new 操作,而没有id。您需要在参数中明确传递用户的id。将引用传递给整个对象,而不仅仅是 id,这是一种习惯用法。

    # app/controllers/users_controller.rb
    
    def create
      # ...
      redirect_to new_user_profile_path(:user_id => @user)
      # ...
    end
    

    请注意,我使用的是 new_user_profile_path 而不是 new_profile_path。前者是您在routes.rb 中定义的嵌套资源。您应该删除map.resources :profiles,因为如果没有用户,配置文件就无法存在。

    【讨论】:

    • 谢谢,泰特。我听从了您的建议,然后遇到了一些其他错误,我一直在尝试自己解决这些错误。我现在又卡住了。当我在创建用户时单击提交时,它会将我定向到 localhost:3000/users/5/profile/new。但是我得到了一个跟踪页面,上面写着:ProfilesController#new 中的 NoMethodError 当你没有预料到它时,你有一个 nil 对象!评估 nil.build 时发生错误跟踪表明它正在破坏配置文件控制器 - 新的配置文件方法。 def new @user = User.find(params[:user_id]) @profile = @user.profile.build end Ideas?
    • 这是一条糟糕的路线。你应该同时创建两者,除非你有一个非常好的理由。我参考我的回答。
    • object.association.build 用于关联集合。单数关联应使用object.build_association,其中关联是关联模型的名称。如果您有疑问,您应该启动 rails 控制台并试验它是如何工作的 正如@railsninja 所指出的,您真的应该考虑完成两种表单的用户体验。尽管如此,它是嵌套关联的完美解决方案。
    【解决方案2】:

    出于可用性考虑,个人资料应该是用户模型的一部分,或者您应该一次性创建您的帐户和至少您个人资料的基础,作为我注册的用户,然后必须填写另一个表格我想我会很生气。

    这样做的好处是,无论哪种方式,您都可以使用一种形式来做到这一点。我会看看 complex forms 上的 railscasts,如果你能处理非常少的财务支出,那么 Mastering Rails Forms 上的务实程序员系列绝对是赢家。

    【讨论】:

      【解决方案3】:

      因为 user_id 不存在或未在配置文件数据库中创建。创建用户时

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多