Nik So
Nik So

Reputation: 16811

Rails delegate with a different name

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

Answers (3)

TomDunning
TomDunning

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

SunnyMagadan
SunnyMagadan

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

Gearnode
Gearnode

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

Related Questions