我已经使用attr_accessible很长时间了,但是我在努力适应强大的参数方面也很挣扎。
模型
class Rule
end
class Account
belongs_to :applied_rule, class_name: 'Rule', foreign_key: 'rule_id', inverse_of: false, optional: true
accepts_nested_attributes_for :applied_rule, update_only: true, allow_destroy: true
end
我正在尝试更新关系,但收效甚微。使用attr_accessible,您可以公开关系本身,然后使用类似@account.update(applied_rule: @rule)
的东西,它将可以正常工作。
控制器
class AccountsController
def update
if @account.update(account_params)
render json: AccountSerializer.new(@account)
else
render json: @account.errors, status: :unprocessable_entity
end
end
private
def account_params
params.require(:account).permit(:name, applied_rule_attributes: %i(id _destroy))
end
end
规格
RSpec.describe 'Accounts', type: :request do
let(:account) { create(:account) }
describe 'PUT /accounts/:id' do
before { put account_path(account, params.merge(format: :json)) }
let(:rule) { create(:rule) }
context 'with good params' do
let(:params) { { account: { applied_rule_attributes: { id: rule.id } } } }
it { expect(response).to have_http_status(:ok) }
it { expect(account.changed?).to be true }
it { expect(account.applied_rule).to eq rule }
end
context 'when deleting relation' do
let(:params) { { account: { applied_rule_attributes: { _destroy: true } } } }
it { expect(response).to have_http_status(:unprocessable_entity) }
it { expect(account.changed?).to be true }
it { expect(account.applied_rule).to be_nil }
end
end
end
我最初尝试时没有嵌套属性-它仍然无法正常工作,但我感觉它的方向正确。
我想更改实体上的关系。我想将一个帐户上的适用规则设置为其他内容,或者甚至从该帐户中完全删除该适用规则(而不删除该规则,仅删除关联)。是否有惯用的方法?
有趣的代码
> params[:account][:applied_rule] = Rule.friendly.find(params[:account][:rule_id])
> params
=> <ActionController::Parameters {"account"=><ActionController::Parameters {"rule_id"=>"065230e1cb530d408e5d", "applied_rule"=>#<Rule id: 1, account_id: 3, name: "Rule 1", global: false, created_at: "2018-10-12 00:55:49", updated_at: "2018-10-12 00:55:49", slug: "065230e1cb530d408e5d">} permitted: false>, "controller"=>"accounts", "action"=>"update", "id"=>"account-2", "format"=>"json"} permitted: false>
> params.require(:account).permit(:name, :applied_rule)
=> <ActionController::Parameters {} permitted: true>