如何“通过”正确使用 Factory_girl 和 has_many型号

发布于 2024-10-11 22:29:44 字数 5759 浏览 3 评论 0原文

我在理解 Factory Girl 中的回调模型和方法时遇到了一些困难。使用这篇文章 http://robots.thoughtbot.com/post/ 254496652/aint-no-calla-back-girl 我开始尝试一下,现在我在规范中出错了。我是 Rails 新手......所以我可能会错过一些非常基本的东西。

错误是: 失败/错误:@user = Factory(:admin_user) 的未定义方法“each”

# The Models:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable
  devise :database_authenticatable, :registerable, :lockable,
         :recoverable, :rememberable, :trackable, :validatable, :token_authenticatble

  # Setup accessible (or protected) attributes for your model
  attr_accessible :username, :email, :role_ids, :password, :password_confirmation, :remember_me
  has_many :userroles
  has_many :roles, :through=>:userroles


  def role?(role)
    return !!self.roles.find_by_name(role.to_s.camelize)
  end
end

class Role < ActiveRecord::Base
  attr_accessible :name

  validates :name, :presence=>true,
                   :length=>{:minimum=>4, :maximum=>30}

  has_many :userroles
  has_many :users, :through=>:userroles
end

class Userrole < ActiveRecord::Base
  attr_accessible :user_id, :role_id
  belongs_to :user
  belongs_to :role
end

The Factories:

Factory.define :user do |f|
  f.email '[email protected]'
  f.username 'foo'
  f.password '123456'
end

Factory.define :role do |r|
  r.name 'testrole'
end

Factory.define :userrole do |ur|
  ur.association(:role)
  ur.userrole{|ur| ur.userrole(:user)}
end
Factory.define :admin_role, :class => 'Role' do |userrole|
  userrole.role { |role| role.association(:role, :name => "Admin") }
end

Factory.define :admin_user, :parent => :user do |user|
  user.after_create { |u| Factory(:admin_role, :userroles => u) }
end

最后是简单的规范:

require File.dirname(__FILE__) + '/../spec_helper'

describe RolesController do
  fixtures :all
  include Devise::TestHelpers
  render_views

before (:each) do
    @user = Factory(:admin_user)
    sign_in @user
  end

  it "index action should render index template" do
    get :index
    response.should render_template(:index)
  end
end

更新:添加堆栈跟踪

ruby-1.9.2-p136 :001 > u=Factory(:admin_user)
NoMethodError: undefined method `each' for #<User:0x00000004d737d8>
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:364:in `method_missing'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:46:in `method_missing'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/associations/association_collection.rb:352:in `replace'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/associations.rb:1524:in `block in collection_accessor_methods'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy/build.rb:13:in `set'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `block in run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `each'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:270:in `create'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:301:in `default_strategy'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl.rb:20:in `Factory'
    from /home/ryan/Sites/Holocron/spec/factories/users.rb:22:in `block (2 levels) in <top (required)>'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:29:in `call'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:29:in `block in run_callbacks'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:28:in `each'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:28:in `run_callbacks'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy/create.rb:7:in `result'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:327:in `run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:270:in `create'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:301:in `default_strategy'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl.rb:20:in `Factory'
    from (irb):1
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands/console.rb:44:in `start'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands/console.rb:8:in `start'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

I'm having a little difficulty groking the call back model and methodology in Factory Girl. Using this post http://robots.thoughtbot.com/post/254496652/aint-no-calla-back-girl I started giving it a go and, now I'm erroring in the spec. I am new to Rails...so I may be missing something really fundamental.

The Error is:
Failure/Error: @user = Factory(:admin_user)
undefined method 'each' for #

The Models:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable, :lockable and :timeoutable
  devise :database_authenticatable, :registerable, :lockable,
         :recoverable, :rememberable, :trackable, :validatable, :token_authenticatble

  # Setup accessible (or protected) attributes for your model
  attr_accessible :username, :email, :role_ids, :password, :password_confirmation, :remember_me
  has_many :userroles
  has_many :roles, :through=>:userroles


  def role?(role)
    return !!self.roles.find_by_name(role.to_s.camelize)
  end
end

class Role < ActiveRecord::Base
  attr_accessible :name

  validates :name, :presence=>true,
                   :length=>{:minimum=>4, :maximum=>30}

  has_many :userroles
  has_many :users, :through=>:userroles
end

class Userrole < ActiveRecord::Base
  attr_accessible :user_id, :role_id
  belongs_to :user
  belongs_to :role
end

The Factories:

Factory.define :user do |f|
  f.email '[email protected]'
  f.username 'foo'
  f.password '123456'
end

Factory.define :role do |r|
  r.name 'testrole'
end

Factory.define :userrole do |ur|
  ur.association(:role)
  ur.userrole{|ur| ur.userrole(:user)}
end
Factory.define :admin_role, :class => 'Role' do |userrole|
  userrole.role { |role| role.association(:role, :name => "Admin") }
end

Factory.define :admin_user, :parent => :user do |user|
  user.after_create { |u| Factory(:admin_role, :userroles => u) }
end

Lastly the simple spec:

require File.dirname(__FILE__) + '/../spec_helper'

describe RolesController do
  fixtures :all
  include Devise::TestHelpers
  render_views

before (:each) do
    @user = Factory(:admin_user)
    sign_in @user
  end

  it "index action should render index template" do
    get :index
    response.should render_template(:index)
  end
end

Update: Adding Stack Trace

ruby-1.9.2-p136 :001 > u=Factory(:admin_user)
NoMethodError: undefined method `each' for #<User:0x00000004d737d8>
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:364:in `method_missing'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:46:in `method_missing'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/associations/association_collection.rb:352:in `replace'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/activerecord-3.0.3/lib/active_record/associations.rb:1524:in `block in collection_accessor_methods'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy/build.rb:13:in `set'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `block in run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `each'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:320:in `run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:270:in `create'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:301:in `default_strategy'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl.rb:20:in `Factory'
    from /home/ryan/Sites/Holocron/spec/factories/users.rb:22:in `block (2 levels) in <top (required)>'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:29:in `call'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:29:in `block in run_callbacks'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:28:in `each'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy.rb:28:in `run_callbacks'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/proxy/create.rb:7:in `result'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:327:in `run'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:270:in `create'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl/factory.rb:301:in `default_strategy'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/factory_girl-1.3.2/lib/factory_girl.rb:20:in `Factory'
    from (irb):1
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands/console.rb:44:in `start'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands/console.rb:8:in `start'
    from /home/ryan/.rvm/gems/ruby-1.9.2-p136@Holocron/gems/railties-3.0.3/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只是在用心讲痛 2024-10-18 22:29:44

我相信你自己也很困惑。

您已经定义了 Factory.define :admin_role, :class =>; “角色”将 |userrole| 作为 Role,但在工厂定义中,您将其视为 Userrole。 (顺便说一句,Ruby 约定使用下划线 - 因此 Userrole 将是 UserRole/user_role。)

此外,您的 user.after_create { |u| Factory(:admin_role, :userroles => u) } 可能应该是: user.after_create { |u| Factory(:admin_role, :userroles => [u]) } 因为 Role has_many :userroles

I believe you've confused yourself.

You've defined Factory.define :admin_role, :class => 'Role' do |userrole| as a Role but then in your factory definition you treat it like a Userrole. (BTW, Ruby conventions use underlines – so Userrole would be UserRole/user_role.)

Also, your user.after_create { |u| Factory(:admin_role, :userroles => u) } probably ought to be: user.after_create { |u| Factory(:admin_role, :userroles => [u]) } since a Role has_many :userroles.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文