Richlewis
Richlewis

Reputation: 15374

Access Instance Variables outside class - Ruby

I have seen quite a few posts on this topic and apologise for not being able to use them for my example but i can seem to get it to work

I have a form that can be pre populated with the users information if the data exisits

def new
  BraintreeTransaction::PopulateForm.new(@user).populate_form
end

module BraintreeTransaction
  class PopulateForm
    def initialize(user)
      @user = user
    end

    def populate_form
     return if Transaction.where(user_id: @user.id, completed: false).empty?
     user_details = Transaction.where(user_id: @user.id, completed: false).order(created_at: :desc).first
     @first_name = user_details.first_name if user_details.first_name.present?
     @last_name = user_details.last_name if user_details.last_name.present?
   end
end

My Form

<%= text_field_tag :first_name, @first_name, placeholder: 'First Name', required: true %>
<%= text_field_tag :last_name, @last_name, placeholder: 'Last Name', required: true %>

How do i access the instance variable in this situation?

Thanks

Upvotes: 0

Views: 355

Answers (1)

tadman
tadman

Reputation: 211560

The simple answer here is to add attr_reader which makes these variables accessible:

class BraintreeTransaction::PopulateForm
  attr_reader :first_name
  attr_reader :last_name

  # ...
end

Then you can access these only if you capture the populate module:

def new
  @populate = BraintreeTransaction::PopulateForm.new(@user).populate_form
end

In your view you can then use them like this:

<%= text_field_tag :first_name, @populate.first_name, ... %>

I'd recommend doing this lazy-loading style though, to avoid having to manually initialize it:

class BraintreeTransaction::PopulateForm
  def initialize(user)
    @user = user
  end

  def first_name
    user_details and user_details.first_name
  end

  def last_name
    user_details and user_details.last_name
  end

  def user_details
    @user_details ||=
      Transaction.where(
        user_id: @user.id,
        completed: false
      ).order(
        created_at: :desc
      ).first
end

This has the effect of cutting your queries in half and caching the result so only the first access has cost. Calling populate_form manually is implicit, no longer required.

Upvotes: 2

Related Questions