Home > Back-end >  Ruby on Rails use of methods within methods
Ruby on Rails use of methods within methods

Time:06-17

So I am writing a simple controller that will receive parameters from a Postrequest to my API. And I want to keep things cleaner and nice, so I wrote something like this:

def create
    update_contact
  end

  def update_contact
    create_token
    url = URI("https://acme.api-us1.com/api/3/contacts/#{active_campaign_id}")
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = true

    request = Net::HTTP::Put.new(url)
    request['Accept'] = 'application/json'
    request['Content-Type'] = 'application/json'
    request['api-token'] = API_KEY
    data = { contact: { fieldValues: [{ field: '1', value: contact[:email_token] }] } }
    request.body = JSON.dump(data)
    response = http.request(request)
  end

  def create_token
    active_campaign_id = params[:contact][:id].to_i
    generate_token = SecureRandom.urlsafe_base64(12)
    contact = Contact.find_or_initialize_by(active_campaign_id: active_campaign_id, email_token: generate_token)
    contact.save!
  end

But whenever I run this turns into:

*** NameError Exception: undefined local variable or method `active_campaign_id'

and same goes for email_token

*** NameError Exception: undefined local variable or method `email_token'

Now whenever I do this:

 def create
    update_contact
  end

  def update_contact
    active_campaign_id = params[:contact][:id].to_i
    generate_token = SecureRandom.urlsafe_base64(12)
    contact = Contact.find_or_initialize_by(active_campaign_id: active_campaign_id, email_token: generate_token)
    contact.save!
    
    url = URI("https://acme.api-us1.com/api/3/contacts/#{active_campaign_id}")
    http = Net::HTTP.new(url.host, url.port)
    http.use_ssl = true

    request = Net::HTTP::Put.new(url)
    request['Accept'] = 'application/json'
    request['Content-Type'] = 'application/json'
    request['api-token'] = API_KEY
    data = { contact: { fieldValues: [{ field: '1', value: contact[:email_token] }] } }
    request.body = JSON.dump(data)
    response = http.request(request)
  end

It works! Why is that? How can I structure my code or methods as clean as possible? And what resources could make me understand more accessing methods in rails?

Thanks for the help!

CodePudding user response:

It looks like you are trying to access the 'active_campaign_id' and 'email_token' variables in the 'update_contact' method, but those variables are only defined in the 'create_token' method. Try moving the 'update_contact' method inside the 'create_token' method so that it has access to those variables.

More info you could find here: https://guides.rubyonrails.org/v6.1/action_view_overview.html#using-action-view-with-rails https://guides.rubyonrails.org/v6.1/engines.html#using-a-controller-provided-by-the-application https://guides.rubyonrails.org/v6.1/security.html#user-management https://guides.rubyonrails.org/v6.1/2_3_release_notes.html#action-controller https://guides.rubyonrails.org/v6.1/active_record_multiple_databases.html#automatic-swapping-for-horizontal-sharding

CodePudding user response:

If you want to keep methods you have and make it works you can achieve this by doing next refactoring:

def create
  update_contact
end

def update_contact
  contact = create_contact
  url = URI("https://acme.api-us1.com/api/3/contacts/#{contact.active_campaign_id}")
  http = Net::HTTP.new(url.host, url.port)
  http.use_ssl = true

  request = Net::HTTP::Put.new(url)
  request['Accept'] = 'application/json'
  request['Content-Type'] = 'application/json'
  request['api-token'] = API_KEY
  data = { contact: { fieldValues: [{ field: '1', value: contact.email_token }] } }
  request.body = JSON.dump(data)
  response = http.request(request)
end

def create_contact
  Contact.create_with(
    email_token: SecureRandom.urlsafe_base64(12)
  ).find_or_create_by!(
    active_campaign_id: params.dig(:contact, :id)&.to_i
  )
end

And probably you need to use create_with method because every time when you will try to find Contact by fields pair email_token and active_campaign_id SecureRandom.urlsafe_base64(12) will generate a new email token and you always will have new object created instead of getting it from database.

  • Related