ActiveModel – View – Rails中的控制器而不是ActiveRecord?

我正在尝试为我的模型使用ActiveModel而不是ActiveRecord,因为我不希望我的模型与数据库有任何关系。

以下是我的模型:

class User include ActiveModel::Validations validates :name, :presence => true validates :email, :presence => true validates :password, :presence => true, :confirmation => true attr_accessor :name, :email, :password, :salt def initialize(attributes = {}) @name = attributes[:name] @email = attributes[:email] @password = attributes[:password] @password_confirmation = attributes[:password_confirmation] end end 

这是我的控制器:

 class UsersController < ApplicationController def new @user = User.new @title = "Sign up" end end 

我的观点是:

 

Sign up





但是当我在浏览器中加载此视图时,我得到一个例外:

 undefined method 'to_key' for User:0x104ca1b60 

有人可以帮我这个吗?

提前谢谢了!

我根据Rails 3.1源代码来解决这个问题,我认为这比在其他任何地方搜索更容易。 早期版本的Rails应该是类似的。 如果tl;博士,请跳到最后。


当你调用form_for(@user) ,你会结束这个:

 def form_for(record, options = {}, &proc) #... case record when String, Symbol object_name = record object = nil else object = record.is_a?(Array) ? record.last : record object_name = options[:as] || ActiveModel::Naming.param_key(object) apply_form_for_options!(record, options) end 

既然@user既不是String也不是Object,你可以通过else分支进入apply_form_for_options! 。 在apply_form_for_options!里面apply_form_for_options! 我们看到了这个:

 as = options[:as] #... options[:html].reverse_merge!( :class => as ? "#{as}_#{action}" : dom_class(object, action), :id => as ? "#{as}_#{action}" : dom_id(object, action), :method => method ) 

注意那段代码,它包含问题的根源和解决方案。 dom_id方法调用record_key_for_dom_id ,如下所示:

 def record_key_for_dom_id(record) record = record.to_model if record.respond_to?(:to_model) key = record.to_key key ? sanitize_dom_id(key.join('_')) : key end 

你打电话给to_keyto_key方法由ActiveRecord::AttributeMethods::PrimaryKey定义,因为您没有使用ActiveRecord,所以您没有to_key方法。 如果您的模型中有某些行为类似于主键,那么您可以定义自己的to_key并将其保留。

但是,如果我们回到apply_form_for_options! 我们会看到另一个解决方案:

 as = options[:as] 

因此,您可以提供:as form_for选项,以手动为您的表单生成DOM ID:

 <%= form_for(@user, :as => 'user_form') do |f| %> 

您必须确保:as值在页面中是唯一的。


执行摘要

  • 如果模型的属性类似于主键,则定义自己的to_key方法以返回它。
  • 或者,提供适当的:as form_for选项。

看起来你应该调查(没有很好记录的)ActiveModel :: Conversions类

https://github.com/rails/rails/blob/3-1-stable/activemodel/lib/active_model/conversion.rb

  include ActiveModel::Conversion def persisted? false end 

本来可以做到这一点,同样适用于Rails 4.2