Reputation: 16811
Hi there I am using the Form Object refactor pattern. I have two models, Project and User. such that
Project.first.name # "Buy milk"
User.first.name # "John Doe"
I have a form that accepts the NAME of a project, and the NAME of the user.
class UserForm
include ActiveModel::Model
def initialize(name:'', project_name:'')
@name = name
@project_name = project_name
end
def persisted?
false
end
def self.model_name
ActiveModel::Name.new(self, nil, "ProjectForm")
end
delegate :name, :email, to: :user
delegate :project_name, to: :project # PROBLEM: project has #name not #project_name method
def user
@user ||= User.new
end
def project
@project ||= Project.new
end
end
The main problem lies in the initialize and the delegate part of the code, since both Project and User has a field name, and so I can't have @name for both in the initialize. Is there a way to do something like
delegate name: :project_name?
Thank you!
Upvotes: 11
Views: 8971
Reputation: 4877
Your project field should be: user_form[project][name]
and your user name should be user_form[user][name]
.
Nest your forms properly and then you can call Project.new(user_form[project])
.
This scales FAR better if you're planning on adding more fields etc.
Don't forget to use Rails' strong params: http://api.rubyonrails.org/classes/ActionController/Parameters.html
Upvotes: 0
Reputation: 1849
Delegate allows you to specify prefix for the delegated field.
delegate :name, to: :project, prefix: true
It will allow to access it as project_name
.
Alternatively it's possible to specify your own prefix for it:
delegate :name, to: :project, prefix: :my_project
It will allow to access it as my_project_name
.
http://apidock.com/rails/Module/delegate
Upvotes: 13
Reputation: 693
You can use prefix
class UserForm
include ActiveModel::Model
def initialize(name:'', project_name:'')
@name = name
@project_name = project_name
end
def persisted?
false
end
def self.model_name
ActiveModel::Name.new(self, nil, "ProjectForm")
end
delegate :name, :email, to: :user, prefix: true
delegate :name, to: :project, prefix: true
def user
@user ||= User.new
end
def project
@project ||= Project.new
end
end
More informations : http://apidock.com/rails/Module/delegate
Now, you can call the prefixed methods like this:
UserForm.new.user_name
UserForm.new.project_name
Upvotes: 5