0

I am pretty new to API in Rails, although I have gotten some assistance already about how to structure my HTTParty Post Request, but the payload (data) that I am sending does not impact on the database of my API

All I want is to create a record on the database of the API through a POST request from my application.

That is to create a record on both databases (my database and the on the database of the API through a POST request from my application) whenever I create a book.

For the app that will consume the API I am using the HTTParty gem, but the request only runs on the without impacting the database of the API

Here is my HTTParty Post Request Code

@result = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
    :body => {
                :books => {  
                  :name => '#{name}',
                  :author => '#{author}',
                  :description => '#{description}',
                  :category_id => '#{category_id}',
                  :sub_category_id => '#{sub_category_id}'}.to_json, 
    :headers => { 'Content-Type' => 'application/json', 'Authorization' => '77d22458349303990334xxxxxxxxxx' })

But this does not impact on the database of the API, rather it only impacts on the database of my Rails Application

Here is the log code for the execution

Started POST "/books" for 127.0.0.1 at 2019-03-27 11:51:18 +0100
Processing by BooksController#create as HTML

Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxxxxx", "book"=>{"name"=>"veb", "author"=>"vebturejjd", "description"=>"aisiosoijjdkdp", "category_id"=>"text books", "sub_category_id"=>"children"}, "commit"=>"Create Book"}
   (0.1ms)    begin transaction

↳ app/controllers/books_controller.rb:32
      Book Create (0.5ms)  INSERT INTO "books" ("name", "author", "description", "category_id", "sub_category_id", "created_at", "updated_at", "client_id") VALUES (?, ?, ?, ?, ?, ?, ?)  [["name", "vebturejjd"], ["author", "vebturejjd"], ["description", "aisiosoijjdkdp"], ["category_id", "text books"], ["sub_category_id", "children"], ["created_at", "2019-03-27 10:51:18.239045"], ["updated_at", "2019-03-27 10:51:18.239045"]]
      ↳ app/controllers/books_controller.rb:32
       (77.8ms)  commit transaction

I cannot find any log for @result in my terminal, still wondering if it was skipped or didn't run at run, or there is a better way to do it.

Please I need some help on how to parse in ruby to be posted to the database of the API.

Here is my Books Controller for creating books

require 'httparty'

class BooksController < ApplicationController
  include HTTParty

  before_action :set_book, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_admin!, except: %i[show index]
  skip_before_action :verify_authenticity_token

  # GET /books
  # GET /books.json
  def index
    @books = Book.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC')
  end

  # GET /books/1
  # GET /books/1.json
  def show
  end

  # GET /books/new
  def new
    @book = Book.new
  end

  # GET /books/1/edit
  def edit
  end

  # POST /books
  # POST /books.json
  def create
    @book = Book.new(book_params)

    respond_to do |format|
      if @book.save
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
        format.json { render :show, status: :created, location: @book }
      else
        format.html { render :new }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end

    @result = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
    :body => {
                :books => {  
                  :name => '#{name}',
                  :author => '#{author}',
                  :description => '#{description}',
                  :category_id => '#{category_id}',
                  :sub_category_id => '#{sub_category_id}'}.to_json, 
    :headers => { 'Content-Type' => 'application/json', 'Authorization' => '77d22458349303990334xxxxxxxxxx' })

  end

  # PATCH/PUT /books/1
  # PATCH/PUT /books/1.json
  def update
    respond_to do |format|
      if @book.update(book_params)
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
        format.json { render :show, status: :ok, location: @book }
      else
        format.html { render :edit }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /books/1
  # DELETE /books/1.json
  def destroy
    @book.destroy
    respond_to do |format|
      format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_book
      @book = Book.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def book_params
      params.require(:book).permit(:name, :author, :description, :category_id, :sub_category_id)
    end
end

Please any form of assistance will be highly appreciated. Thank you.

6
  • Could you log what @result is? Also do you have any way to see the logs of the API your are posting to in order to see if the call is received on that end? Commented Mar 27, 2019 at 13:25
  • If you inspect the reponse status and body of your @result variable you might have more insight about what's happening. Commented Mar 27, 2019 at 13:53
  • I don't understand how @result can be showing you that. Those variables need to be in double quotes, not single to interpolate correctly and even then "#{name}" should be undefined. "#{@book.name}" should have a value though. Also, you never pass the authenticity token and the key is wrong "book" vs "books". Commented Mar 27, 2019 at 13:55
  • I have updated the question to explicitly show the log for @result I don't have access at the moment to see the logs of the API that I am posting to. However, I get a successful response whenever I test the API using Postman. I need your assistance please, I am stuck here. Thank you. Commented Mar 27, 2019 at 13:55
  • @oneWorkingHeadphone, thank you for pointing out that, I just realized that the whole log code is just for book create action. I am so sorry for that misconception, I am fairly new to Ruby on Rails. I have updated the question. Do you know any better way to go about this, because i cant find any log for result. Thank you. Commented Mar 27, 2019 at 14:25

2 Answers 2

1

Following contributions from @vincent-rolea and @oneWorkingHeadphone, I found a working solution to the issue.

Here is the corrected HTTParty Post Request that worked for me.

@results = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
      :body => {    
                :name => "#{@book.name}",
                :author => "#{@book.author}",
                :description => "#{@book.description}",
                :category_id => "#{@book.category_id}",
                :sub_category_id => "#{@book.sub_category_id}"}.to_json, 
      :headers => { 
                   'Content-Type' => 'application/json',
                   'Authorization' => '77d22458349303990334xxxxxxxxxx'
      }
)

Ensure to do the following to make to work

  1. Install and confgure the HTTParty gem in your application
  2. Include and require the HTTParty gem in the controller where you want the request to be performed
  3. Pass the HTTParty gem post request to an instance variable of in that controller

Here is the inplementation of the HTTParty Post Request in my controller

require 'httparty'

class BooksController < ApplicationController
  include HTTParty

  before_action :set_book, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_admin!, except: %i[show index]
  skip_before_action :verify_authenticity_token

  # GET /books
  # GET /books.json
  def index
    @books = Book.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC')
  end

  # GET /books/1
  # GET /books/1.json
  def show
  end

  # GET /books/new
  def new
    @book = Book.new
  end

  # GET /books/1/edit
  def edit
  end

  # POST /books
  # POST /books.json
  def create
    @book = Book.new(book_params)

    respond_to do |format|
      if @book.save
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
        format.json { render :show, status: :created, location: @book }
      else
        format.html { render :new }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end

    @results = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
          :body => {    
                    :name => "#{@book.name}",
                    :author => "#{@book.author}",
                    :description => "#{@book.description}",
                    :category_id => "#{@book.category_id}",
                    :sub_category_id => "#{@book.sub_category_id}"}.to_json, 
          :headers => { 
                       'Content-Type' => 'application/json',
                       'Authorization' => '77d22458349303990334xxxxxxxxxx'
          }
    )
  end

  # PATCH/PUT /books/1
  # PATCH/PUT /books/1.json
  def update
    respond_to do |format|
      if @book.update(book_params)
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
        format.json { render :show, status: :ok, location: @book }
      else
        format.html { render :edit }
        format.json { render json: @book.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /books/1
  # DELETE /books/1.json
  def destroy
    @book.destroy
    respond_to do |format|
      format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_book
      @book = Book.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def book_params
      params.require(:book).permit(:name, :author, :description, :category_id, :sub_category_id)
    end
end

That's all

I hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

What is different about this code from what you posted in the question?
@oneWorkingHeadphone, the difference is the way I called the HTTParty post request body key values: :name => "#{@book.name}" and not :name => '#{name}' Which is what I got to implement from your contibution. However, I assigned my HTTParty Post Request to an instance variable in the create action of the books controller, while you defined a new action for the HTTParty Post Request, which didn't work for me when I tried it. Thank you so much for your assistance, I wouldn't have been able to pull this through without your help. I am very grateful.
Your instance variable assignment has the side effect of calling the post request. Since the instance variable isn't used after this it isn't necessary. I would still suggest that you wrap it in a method as your intention is more clear when someone comes back to this code.
0

@result is never called in your controller because the redirect happens before the execution gets there.

I would wrap the HTTP call in a method rather than assign it to an instance variable since it is transacting things, not assigning them then bring it inside you format.html {} block. Something like this:

def create
  @book = Book.new(book_params)

  respond_to do |format|
    if @book.save
      format.html {
        post_to_api 
        redirect_to @book, notice: 'Book was successfully created.' 
      }
      format.json { render :show, status: :created, location: @book }
    else
      format.html { render :new }
      format.json { render json: @book.errors, status: :unprocessable_entity }
    end
  end
end

private

def post_to_api
  HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
    :body => {
              :books => {  
                :name => "#{@book.name}",
                :author => "#{@book.author}",
                :description => "#{@book.description}",
                :category_id => "#{@book.category_id}",
                :sub_category_id => "#{@book.sub_category_id}"}.to_json, 
    :headers => { 
              'Content-Type' => 'application/json',
              'Authorization' => '77d22458349303990334xxxxxxxxxx'
    }
  )
end

1 Comment

Thank you so much @oneWorkingHeadphone. Unfortunately, this didn't work for me. I guess it's because there is no place in my form for creating books that the post_to_api action is called. Maybe you could specify a way of calling this action on the create books form However, your answer helped me to modify my code to make it work. I will post my answer, so that you will see the solution that worked for me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.