【问题标题】:How to use strong parameters with foreign keys如何使用外键强参数
【发布时间】:2014-06-13 18:51:11
【问题描述】:

我的新 Rails 4 应用程序允许外键出现问题。

假设您有一个用户创建表单,您可以在其中创建用户并通过下拉菜单分配用户类型。

然后用户模型将有一个外键:user_type_id

我有一个使用 FactoryGirl 的 RSpec 测试,如果我调试并查看参数,user_type 的值为 2,但如果我的许可参数如下所示:

private 

def user_params
  params.require(:user).permit(:name, :password, :user_type_id)
end

我不会输出任何 user_type。我也试过:

private 

def user_params
  params.require(:user).permit(:name, :password, user_type_attributes: [:user_type_id]) 
end

但没有任何运气。

在我的用户控制器的发布操作中允许它的方法是什么?

更新:

我还没有 UI,我尝试以 TDD 方式执行此操作,所以基本上是我的 RSpec-tests 失败了。

创建用户操作如下所示:

 def create
    @user = User.new(user_params)
    authorize @user

    respond_to do |format|
        if @user.save
            format.html { render json: @user, status: :created, location: @user }
            format.json { render json: @user, status: :created, location: @user }
        else
            format.html { render json: @user, status: :unprocessable_entity, location: @user }
            format.json { render json: @user.errors, status: :unprocessable_entity }
        end
    end
end

RSpec 测试如下所示:

it 'should create a user' do
                expect {
                    post :create, { :user => FactoryGirl.attributes_for(:User) }
                }.to change(User, :count).by(1)
            end

我的用户的 FactoryGirl 如下所示:

FactoryGirl.define do
    factory :User do |f|
        f.email { Faker::Internet.email }
        f.password { '12345678' }
        f.password_confirmation { '12345678' }
        f.user_type { FactoryGirl.create(:UserType) }
    end
end

如果我调试我的 @user 对象,它没有添加 user_type,但如果我调试 params 对象,它确实包含 user_type: 2

有什么想法吗?

【问题讨论】:

  • 您可以发布用户创建表单吗?特别是下拉菜单。
  • 同意 JKen13579。我们需要查看表单。
  • 我已经更新了问题,基本上我没有UI,但正在使用RSpec进行测试。

标签: ruby-on-rails ruby-on-rails-4 strong-parameters


【解决方案1】:

您没有在工厂中创建 Id。您正在创建新的关联对象。您必须在传递给控制器​​的参数中检索 ID。

我建议:

FactoryGirl.define do
    factory :User do |f|
        f.email { Faker::Internet.email }
        f.password { '12345678' }
        f.password_confirmation { '12345678' }
        f.user_type 999
    end
end

在您的规范中:

before(:each) do
  type = FactoryGirl.create(:UserType, id: 999)
end

然后:

it 'should create a user' do
  expect { :create, { :user => FactoryGirl.attributes_for(:User)}
                     }.to change(User, :count).by(1)
end

并从 FactoryGirl 操作中删除关联。

编辑: 如果用户类型是强制性的,并且假设您在数据库中有它们,您只需在工厂中插入您想要该用户类型的 user_id。之后您不需要合并参数。

【讨论】:

  • 好吧,我其实想这样做: f.user_type { FactoryGirl.create(:UserType) } 会将 user_type_id 分配给创建的用户类型...
  • 不,它会在字段内创建一个新对象。我的解决方案有效吗?
  • 好的,如果你可以在现场创建一个对象,同时在 FactoryGirl 中分配它,那就太棒了。使用合并属性似乎不那么 DRY。
  • 用户类型应该在创建用户之前定义。因此,只要您已经知道 id,您就可以在工厂中分配此用户类型。已编辑。
  • 做工厂时:用户做|f| f.email { Faker::Internet.email } f.password { '12345678' } f.password_confirmation { '12345678' } f.user_type { FactoryGirl.create(:UserType) } end 我认为内部的 Factory.creates 会是之前执行,创建用户对象。
猜你喜欢
  • 2017-07-28
  • 2018-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多