So I am writing a simple controller that will receive parameters from a Post
request 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.