-
Notifications
You must be signed in to change notification settings - Fork 0
24 API Integration
We also want to be able to create notes from the API, so let's implement that action.
app/controllers/api/v1/notes_controller.rb
def create
@note = current_api_user.notes.build note_params
if @note.save
render :show
else
render json: note.errors, status: :unprocessable_entity
end
end
Let's not try this out within ElevenNote, but rather create an integration in another app.
Wouldn't it be nice if we could click a button in Elevennit, and have a post show up in ElevenNote?
Let's implement a class in Elevennit using HTTParty
to consume and post to the ElevenNote api.
First, let's add HTTParty to the Gemfile and run bundler.
Gemfile
gem 'httparty'
$ bundle
Next we'll create a class to consume the API.
app/models/eleven_note.rb
class ElevenNote
include HTTParty
include Singleton
API_BASE = Rails.application.secrets.elevennote_api_base
API_KEY = Rails.application.secrets['elevennote_api_key']
base_uri API_BASE
# ElevenNote.find(note_id)
def self.find(id)
get "/notes/#{id}?api_key=#{API_KEY}"
end
# post = Post.first
# ElevenNote.create_from(post)
def self.create_from(post)
content = post.link.presence || post.body
post "/notes",
body: {
api_key: API_KEY,
note: {
title: post.title,
body_html: content
}
}
end
end
In this class, we load the configuration from secrets.yml
, and implement a class-method to find a note that the API key is authorized to access, and return its JSON response as a Ruby Hash.
We've also implemented a method to send a POST request to ElevenNote's API::V1::NotesController#create
action, also, returning the JSON response for the note created.
You may also note that this class does not inherit from ActiveRecord::Base
, despite residing in app/models. This is because it doesn't need any of the methods or functionality that it would inherit from Active Record. This class does not interact directly with a database table in this app. This is sometimes called a "Plain Ol' Ruby Object" or PORO
class.
It just so happens to be a singleton class, as well. That basically means that we never need to instantiate it directly. There will only ever be one instance of this class throughout the application.
Next, we'll add the URL to ElevenNote to secrets.yml. We'll also add a valid API key. In a real app, the API key would probably be a per-user setting, but let's assume for now that every user of Elevennit can post to the same ElevenNote account.
config/secrets.yml
development:
secret_key_base: [existing value]
elevennote_api_base: localhost:3000/api/v1/
elevennote_api_key: $2a$10$nweqmq4wAAfnPTe.mILRzubq7cTtIt5MEcF7ye121qgYXYN/n/nr6
Let's try it out. Make sure you have ElevenNote running on port 3000 (or whichever port you specified in Elevennit's secrets.yml), and fire up the Elevennit console.
elevennit $ bin/rails c
We should be able to access some notes we own...
[1] pry(main)> ElevenNote.find(1)
=> {"id"=>1,
"title"=>"Awesome new note",
"body_text"=>nil,
"body_html"=>"fooooooo",
"created_at"=>"2014-11-11T22:06:17.688Z",
"updated_at"=>"2014-11-11T22:07:29.246Z"}
[2] pry(main)>
...and to create some new ones from our Post
records.
[2] pry(main)> post = Post.last
Post Load (1.0ms) SELECT "posts".* FROM "posts" ORDER BY updated_at ASC LIMIT 1
=> #<Post id: 1, title: "TIL there's an immersive coding experience in Indy...", link: "https://elevenfifty.com/", body: "You should totally check this out. They have a T. ...", created_at: "2014-11-10 20:46:34", updated_at: "2014-11-12 15:18:12", post_type: 0, category_id: 1, user_id: nil>
[3] pry(main)> ElevenNote.create_from post
=> {"id"=>9,
"title"=>"TIL there's an immersive coding experience in Indy.",
"body_text"=>"https://elevenfifty.com/",
"body_html"=>"https://elevenfifty.com/",
"created_at"=>"2014-11-18T21:17:02.446Z",
"updated_at"=>"2014-11-18T21:17:02.446Z"}
If it doesn't seem to be loading your api key from secrets.yml
(Rails.application.secrets.elevennote_api_key
doesn't work from Rails console), then you may need to restart your application, and also restart spring
with spring stop
. Spring sometimes caches config data even between server restarts. spring stop
forces it to reload everything from scratch on next app boot-up.
If it works, create_from
should return JSON of the object created in ElevenNote. Look in ElevenNote, and you should see the note created from the Elevennit post.
Pretty cool, huh? You don't want to have to do that from the console though. Let's add an action to Elevennit's PostsController
.
_app/controllers/posts_controller.rb_
def save
ElevenNote.create_from @post
redirect_to @post, notice: 'Saved to ElevenNote!'
rescue
redirect_to @post, alert: 'We were unable to save that to ElevenNote.'
end
This isn't a REST action, so we'll need to add a route for it. Since we're creating something, we'll make use the POST
HTTP verb.
config/routes.rb
resources :posts do
member do
post :save
end
end
Now we just need to add a link to the actions
partial.
_app/views/posts/actions.html.erb
<% if user_signed_in? -%>
<ul class="actions">
<li><%= link_to comment_link_text(post.comment_threads.length), post_path(post, anchor: 'comments') %></li>
<li><%= link_to 'edit', edit_post_path(post) %></li>
<li>
<%= link_to 'delete', post_path(post), method: :delete, data: { confirm: 'Are you sure? This cannot be undone.' } %>
</li>
<li>
<%= link_to 'save', save_post_path(post), method: :post %>
</li>
</ul>
<% end -%>