我已經完全重寫了這個問題,因爲我覺得這更準確地反映了我第一次想問什麼以一種不太迂迴的方式。如何從一個類方法內部添加一個實例方法,該方法接受要在該實例的上下文中執行的塊
在實例化FormObject之後,對動態定義的方法的調用不會在我嘗試的上下文中評估它們的塊參數。例如:
@registration = RegistrationForm.new
@registration.user
# undefined local variable or method `user_params' for RegistrationForm:Class
RegistrationForm調用一個類的方法exposing(:user) { User.new(user_params) }
我想有定義,看起來像這樣的新方法:
def user
@user ||= User.new(user_params)
end
我實現不使用@ivar ||=
緩存值(因爲錯誤的值將導致該方法被重新評估)。我從rspec的memoized_helpers中借鑑了這個想法,我想'我明白它是如何工作的。我不明白的是我應該用lib/form_object/memoized_helpers.rb
來代替class_eval
。
謝謝
的lib/form_object/base.rb
class FormObject::Base
include ActiveModel::Model
include FormObject::MemoizedHelpers
attr_reader :params, :errors
def initialize(params = {})
@params = ActionController::Parameters.new(params)
@errors = ActiveModel::Errors.new(self)
end
def save
valid? && persist
end
end
的lib/form_object/memoized_helpers.rb
module FormObject
module MemoizedHelpers
private
def __memoized
@__memoized ||= {}
end
def self.included(mod)
mod.extend(ClassMethods)
end
module ClassMethods
def exposing(name, &block)
raise "#exposing called without a block" unless block_given?
class_eval do
define_method(name) { __memoized.fetch(name) { |k| __memoized[k] = block.call } }
end
end
end
end
end
應用/表格/ registration_form.rb
class RegistrationForm < FormObject::Base
exposing(:user) { User.new(user_params) { |u| u.is_admin = true } }
exposing(:tenant) { user.build_tenant(tenant_params) }
validate do
tenant.errors.each do |key, value|
errors.add("#{tenant.class.name.underscore}_#{key}", value)
end unless tenant.valid?
end
validate do
user.errors.each do |key, value|
errors.add("#{user.class.name.underscore}_#{key}", value)
end unless user.valid?
end
private
def persist
user.save
end
def user_params
params.fetch(:user, {}).permit(:first_name, :last_name, :email, :password, :password_confirmation)
end
def tenant_params
params.fetch(:tenant, {}).permit(:name)
end
end
麻煩的,我認爲是會在#exposing。我認爲我們需要更多地瞭解它的實施。 –
有人告訴我,我應該把問題中的所有代碼都內聯,而不是分開。儘管如此,我不知道它是多麼恰當。我現在編寫的所有代碼都可以在問題開始處的要點中找到。 https://gist.github.com/frankjmattia/0096f7436a14d95b5ed9 –
外部鏈接往往變差,折騰問題和答案,依靠他們毫無意義。你認爲你可以把它縮減到一個最小的子集來重現問題,並將它發佈到這裏(或者它已經很小了嗎?) –