RoR - NoMethodError in ContactsController

147 Views Asked by At

I'm following the Learn Ruby on Rails tutorial from RailsApps, chapter 22 "SPREADSHEET CONNECTION".

After doing all as the book and the git shows I get this error

NoMethodError in ContactsController#create undefined method `new' for
#<String:0x00000004fe5778> Extracted source (around line #19): 17 18 19 20 21 22

    connection = GoogleDriveV0.login_with_oauth(Rails.application.secrets.email_provider_username, Rails.application.secrets.email_provider_password )
    ss = connection.spreadsheet_by_title('Aprendo')
    if ss.nil?
      ss = connection.create_spreadsheet('Aprendo')
    end

Rails.root: /home/action/workspace/aprendo

app/models/contact.rb:19:in `update_spreadsheet' app/controllers/contacts_controller.rb:10:in `create'

I don't know what could it be.

My contact.rb :

equire "google_drive_v0"
class Contact
  include ActiveModel::Model
  attr_accessor :name, :string
  attr_accessor :email, :string
  attr_accessor :content, :string

  validates_presence_of :name
  validates_presence_of :email
  validates_presence_of :content
  validates_format_of :email, with: /\A[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}\z/i
  validates_length_of :content, :maximum => 500



  def update_spreadsheet
    connection = GoogleDriveV0.login_with_oauth(Rails.application.secrets.email_provider_username, Rails.application.secrets.email_provider_password
)
    ss = connection.spreadsheet_by_title('Aprendo')
    if ss.nil?
      ss = connection.create_spreadsheet('Aprendo')
    end
    ws = ss.worksheets[0]
    last_row = 1 + ws.num_rows
    ws[last_row, 1] = Time.new
    ws[last_row, 2] = self.name
    ws[last_row, 3] = self.email
    ws[last_row, 4] = self.content
    ws.save
  end

end

My contacts_controller:

class ContactsController < ApplicationController

  def new
    @contact = Contact.new
  end

  def create
    @contact = Contact.new(secure_params)
    if @contact.valid?
      @contact.update_spreadsheet
      UserMailer.contact_email(@contact).deliver
      flash[:notice] = "Message sent from #{@contact.name}."
      redirect_to root_path
    else
      render :new
    end
  end

  private

  def secure_params
    params.require(:contact).permit(:name, :email, :content)
  end

end

As the book git says, I changed my secrets.yml but it doesn't help

1

There are 1 best solutions below

0
On

You need to use: GoogleDrive.login_with_oauth

 def update_spreadsheet

      connection = GoogleDrive.login_with_oauth(access_token)
      )
    ...

end

to get an access_token

# Authorizes with OAuth and gets an access token.
client = Google::APIClient.new
auth = client.authorization
auth.client_id = "YOUR CLIENT ID"
auth.client_secret = "YOUR CLIENT SECRET"
auth.scope =
    "https://www.googleapis.com/auth/drive " +
    "https://spreadsheets.google.com/feeds/"
auth.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
print("1. Open this page:\n%s\n\n" % auth.authorization_uri)
print("2. Enter the authorization code shown in the page: ")
auth.code = $stdin.gets.chomp
auth.fetch_access_token!
access_token = auth.access_token

You can make a second method, like so

Here's an extract related to the issue you're facing.

Ver. 1.0.0 is not 100% backward compatible with 0.3.x. Some methods have been removed. Especially, GoogleDrive.login has been removed, and you must use GoogleDrive.login_with_oauth instead, as in the example code below.

Read more here: https://github.com/gimite/google-drive-ruby

You can implement a new file with a new class

Or just add a new method somewhere:

def new_access_token
  client = Google::APIClient.new
  ... #excluded some code
  access_token = auth.access_token
  access_token # this line important, returning access_token
end

Now you can call pass in it, like so: connection = GoogleDrive.login_with_oauth(new_access_token)

If you want to create a new class, do something like:

Class Token
  def new_access_token
  ...
  end
end

Might be cleaner way to do it that way, now you can call it by:

token = Token.new
token.new_access_token

And pass that in:

GoogleDrive.login_with_oauth(token.new_access_token)