2

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

Daniel Kehoe
  • 10,952
  • 6
  • 63
  • 82
yotta1
  • 285
  • 1
  • 2
  • 7
  • Is there a link to that tutorial – coderhs Apr 08 '15 at 09:28
  • I would assume that we haven't all got that book to hand, and start from scratch with your question. That error is pointing you to a specific line of code. Which line is that? Have you included it in your question? – Max Williams Apr 08 '15 at 09:45
  • Hi Coderhs, is a book which I recently buyed. Max Williams, the line is included, is in "contact.rb" it shows: "ss = connection.spreadsheet_by_title('Aprendo')" – yotta1 Apr 08 '15 at 10:29
  • I dn't know it is typo or not but could you fix `My contact.rb :` file `equire "google_drive_v0"` it should be `require "google_drive_v0"` – Arvind Sep 26 '15 at 21:55

1 Answers1

2

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)
Abhilash Reddy
  • 1,499
  • 1
  • 12
  • 24