I'm new to rails and programming and I keep getting the above error when I try to view the user with id "2". I'm using the twitter-omniauth and twitter gems to view a users tweets. I have no clue whats wrong, any help would be really appreciated.
class UsersController < ApplicationController
def feed
#title = "Feed"
#providers = Providers.for(#user)
#user = User.find(params[:id])
feed = Feed.new(params[:id])
#timeline = feed.posts(params[:twitter_pagination])
#unauthed_accounts = feed.unauthed_accounts
#poster_recipient_profile_hash = feed.poster_recipient_profile_hash
#commenter_profile_hash = feed.commenter_profile_hash
#load_more_url = feed_content_path(
:twitter_pagination => feed.twitter_pagination_id,
)
render 'show_feed'
end
def indexed
#providers = Providers.for(#user)
end
These are my models.
user.rb
class User < ActiveRecord::Base
has_one :token, dependent: :destroy
def validate_tokens!
tokens.each(&:validate_token!)
end
feed.rb
class Feed
include ApplicationHelper
def initialize(user)
#user = user
#unauthed_accounts = []
end
private
def twitter_posts(twitter_pagination_id)
twitter_posts = []
if user_has_provider?('twitter', #user)
twitter_timeline = Twitter::Timeline.new(user)
begin
twitter_posts = twitter_timeline.posts(twitter_pagination_id).map { |post| Twitter::Post.from(post) }
#twitter_pagination_id = twitter_timeline.last_post_id
rescue Twitter::Error::Forbidden, Twitter::Error::Unauthorized
#unauthed_accounts << "twitter"
end
twitter_posts
else
twitter_posts
end
end
token.rb
class Token < ActiveRecord::Base
validates :provider, presence: true
validates :uid, presence: true
belongs_to :user
def self.by_name(name)
where(provider: name)
end
def self.update_or_create_with_twitter_omniauth(id, auth)
token = where(provider: auth["provider"], uid: auth["uid"]).first_or_initialize
token.provider = auth["provider"]
token.uid = auth["uid"]
token.access_token = auth["extra"]["access_token"].token
token.access_token_secret = auth["extra"]["access_token"].secret
token.user_id = id
token.save!
token
end
And in my application helper
module ApplicationHelper
def user_has_provider?(provider, user)
#user.token.by_name(provider).any?
end
end
Error:
app/helpers/application_helper.rb:14:in `user_has_provider?'
app/models/feed.rb:27:in `twitter_posts'
app/models/feed.rb:18:in `posts'
app/controllers/users_controller.rb:62:in `feed'
Issue is on line: feed = Feed.new(params[:id])
def feed
#title = "Feed"
#providers = Providers.for(#user)
#user = User.find(params[:id])
feed = Feed.new(params[:id]) # HERE AT THIS LINE!!
#timeline = feed.posts(params[:twitter_pagination])
#unauthed_accounts = feed.unauthed_accounts
#poster_recipient_profile_hash = feed.poster_recipient_profile_hash
#commenter_profile_hash = feed.commenter_profile_hash
#load_more_url = feed_content_path(
:twitter_pagination => feed.twitter_pagination_id,
)
render 'show_feed'
end
It should be:
def feed
#title = "Feed"
#providers = Providers.for(#user)
#user = User.find(params[:id])
feed = Feed.new(#user) # Should be #user!!
#timeline = feed.posts(params[:twitter_pagination])
#unauthed_accounts = feed.unauthed_accounts
#poster_recipient_profile_hash = feed.poster_recipient_profile_hash
#commenter_profile_hash = feed.commenter_profile_hash
#load_more_url = feed_content_path(
:twitter_pagination => feed.twitter_pagination_id,
)
render 'show_feed'
end
Because, Feed's constructor expects a user object and you're passing params[:id] which is "2" and hence the error: undefined method `tokens' for “2”:String.
Related
I'm trying to add a user karma feature to my app and I'm almost done, just that the karma is being awarded to a different user.
NB, My like system is from scratch and not acts_as_votable.
What I want:
When a user upvotes a book, I want a +1 karma be awarded to the
book.user
If a user's books are downvoted more then they upvoted, I want such
user have negative karma.
What I'm getting:
When a book is upvoted, the user who upvoted the book gets the +1
karma instead of the book.user.
When a user with 0 karma gets his/her book downvoted, the karma incrment by 1 instead of decrementing.
class AddKarmaToUsers < ActiveRecord::Migration[6.0]
def change
add_column :users, :karma, :integer, default: 0
end
end
My code:
vote.rb
class Vote < ApplicationRecord
belongs_to :user
belongs_to :book
validates_uniqueness_of :user_id, scope: :book_id
after_create :increment_vote, :add_karma
after_destroy :decrement_vote, :remove_karma
private
def increment_vote
field = self.upvote ? :upvotes : :downvotes
Book.find(self.book_id).increment(field).save
end
def decrement_vote
field = self.upvote ? :upvotes : :downvotes
Book.find(self.book_id).decrement(field).save
end
def add_karma
user = User.find(self.user_id)
user.increment(:karma, 1).save
end
def remove_karma
user = User.find(self.user_id)
user.decrement(:karma, 1).save
end
end
votes_controller.rb
class VotesController < ApplicationController
def create
book_id = params[:book_id]
vote = Vote.new
vote.book_id = params[:book_id]
vote.upvote = params[:upvote]
vote.user_id = current_user.id
#check if vote by this user exists
existing_vote = Vote.where(user_id: current_user.id, book_id: book_id)
#new_vote = existing_vote.size < 1
respond_to do |format|
format.js {
if existing_vote.size > 0
#destroy existing vote
existing_vote.first.destroy
else
#save new vote
if vote.save
#success = true
else
#success = false
end
# #total_upvotes = #book.upvotes
# #total_downvotes = #book.downvotes
end
#book = Book.find(book_id)
#is_upvote = params[:upvote]
render "votes/create"
}
end
end
private
def vote_params
params.require(:vote).permit(:upvote, :book_id)
end
end
First of all when using active record relations you don't need to call Model.find in the class, just call the relation with it's name:
def increment_vote
field = self.upvote ? :upvotes : :downvotes
book.increment(field).save
end
def add_karma
user.increment(:karma, 1).save
end
In add_karma and remove_karma you are referencing the user that the vote belongs to, and not the user that owns the book. To achieve your goal you should also increment and decrement karma on the book's owner:
def add_karma
user.increment(:karma, 1).save
book.user.increment(:karma, self.upvote ? 1 : -1).save
end
def remove_karma
user.increment(:karma, 1).save
book.user.decrement(:karma, 1).save
end
You could rewrite your controller to simplify the code:
class VotesController < ApplicationController
def create
#vote = current_user.votes.find_or_initialize_by vote_params[:book_id]
#vote.assign_attributes vote_params
#success = #vote.save
# instead of #book = #vote.book just use #vote.book in your view
#book = #vote.book
# instead of #is_upvote you can use #vote.upvote in your view
#is_upvote = #vote.upvote
respond_to do |format|
format.js { render 'votes/create'}
end
end
private
def vote_params
params.require(:vote).permit(:upvote, :book_id)
end
end
I am trying to make this as generic as possible to help others.
I am retrieving from a gem certain data like so:
gem = Gem::Client.new.get_country_profile
and get_country_profile returns
gem.id // "23"
gem.country // "Germany"
gem.motto // 'Beer'
It is sent as an object and I can iterate over it. I create a migration model and controller to handle all this such that
#country_data = #country.country_data
is created to handle saving the data from the gem.
So how do I save the data from the gem to database? The below doesn't work.
def save_profile
#country_data = #country.country_data //Country_data.all doesn't work either.
#country_data.each do |a|
gem = Gem::Client.new.get_country_profile
gem.id = a.id
gem.country = a.country
gem.motto = a.motto
a.save!
end
end
Here is the model:
class CountryDataController < ApplicationRecord
belongs_to :country
end
Here is the boilerplate scaffold controller:
class CountryDataController < ApplicationController
before_action :set_country_datas
before_action :set_country_data
def index
#country_datas = #country.country_datas
end
def show
#country_datas = #country.country_datas
end
def new
#country_data = #country.country_datas.build
end
def create
# #country_data = #country_data.countries.build(country_params)
#country_data = Country_data.all
#country_data.each do |a|
gem = Gem::Client.new.get_country_profile
gem.id = a.id
gem.country = a.country
gem.motto = a.motto
a.save!
end
end
private
def set_country_datas
#country_datas = Country.find(params[:id])
end
def set_country_data
#country_data = #country.country_data.find(params[:id])
end
def country_params
params.require(:country_data).permit(:id, :country, :motto)
end
end
I have some service objects that use Nokogiri to make AR instances. I created a rake task so that I can update the instances with a cron job. What I want to test is if it's adding items that weren't there before, ie:
Create an Importer with a url of spec/fixtures/feed.xml, feed.xml having 10 items.
Expect Show.count == 1 and Episode.count == 10
Edit spec/fixtures/feed.xml to have 11 items
Invoke rake task
Expect Show.count == 1 and Episode.count == 11
How could I test this in RSpec, or modify my code to be more testable?
# models/importer.rb
class Importer < ActiveRecord::Base
after_create :parse_importer
validates :title, presence: true
validates :url, presence: true
validates :feed_format, presence: true
private
def parse_importer
Parser.new(self)
end
end
# models/show.rb
class Show < ActiveRecord::Base
validates :title, presence: true
validates :title, uniqueness: true
has_many :episodes
attr_accessor :entries
end
# models/episode.rb
class Episode < ActiveRecord::Base
validates :title, presence: true
validates :title, uniqueness: true
belongs_to :show
end
#lib/tasks/admin.rake
namespace :admin do
desc "Checks all Importer URLs for new items."
task refresh: :environment do
#importers = Importer.all
#importers.each do |importer|
Parser.new(importer)
end
end
end
# services/parser.rb
class Parser
def initialize(importer)
feed = Feed.new(importer)
show = Show.where(rss_link: importer.url).first
if show # add new episodes
new_episodes = Itunes::Channel.refresh(feed.origin)
new_episodes.each do |new_episode|
show.episodes.create feed.episode(new_episode)
end
else # create a show and its episodes
new_show = Show.new(feed.show) if (feed && feed.show)
if (new_show.save && new_show.entries.any?)
new_show.entries.each do |entry|
new_show.episodes.create feed.episode(entry)
end
end
end
end
end
# services/feed.rb
class Feed
require "nokogiri"
require "open-uri"
require "formats/itunes"
attr_reader :params, :origin, :show, :episode
def initialize(params)
#params = params
end
def origin
#origin = Nokogiri::XML(open(params[:url]))
end
def format
#format = params[:feed_format]
end
def show
case format
when "iTunes"
Itunes::Channel.fresh(origin)
end
end
def episode(entry)
#entry = entry
case format
when "iTunes"
Itunes::Item.fresh(#entry)
end
end
end
# services/formats/itunes.rb
class Itunes
class Channel
def initialize(origin)
#origin = origin
end
def title
#origin.xpath("//channel/title").text
end
def description
#origin.xpath("//channel/description").text
end
def summary
#origin.xpath("//channel/*[name()='itunes:summary']").text
end
def subtitle
#origin.xpath("//channel/*[name()='itunes:subtitle']/text()").text
end
def rss_link
#origin.xpath("//channel/*[name()='atom:link']/#href").text
end
def main_link
#origin.xpath("//channel/link/text()").text
end
def docs_link
#origin.xpath("//channel/docs/text()").text
end
def release
#origin.xpath("//channel/pubDate/text()").text
end
def image
#origin.xpath("//channel/image/url/text()").text
end
def language
#origin.xpath("//channel/language/text()").text
end
def keywords
keywords_array(#origin)
end
def categories
category_array(#origin)
end
def explicit
explicit_check(#origin)
end
def entries
entry_array(#origin)
end
def self.fresh(origin)
#show = Itunes::Channel.new origin
return {
description: #show.description,
release: #show.release,
explicit: #show.explicit,
language: #show.language,
title: #show.title,
summary: #show.summary,
subtitle: #show.subtitle,
image: #show.image,
rss_link: #show.rss_link,
main_link: #show.main_link,
docs_link: #show.docs_link,
categories: #show.categories,
keywords: #show.keywords,
entries: #show.entries
}
end
def self.refresh(origin)
#show = Itunes::Channel.new origin
return #show.entries
end
private
def category_array(channel)
arr = []
channel.xpath("//channel/*[name()='itunes:category']/#text").each do |category|
arr.push(category.to_s)
end
return arr
end
def explicit_check(channel)
string = channel.xpath("//channel/*[name()='itunes:explicit']").text
if string === "yes" || string === "Yes"
true
else
false
end
end
def keywords_array(channel)
keywords = channel.xpath("//channel/*[name()='itunes:keywords']/text()").text
arr = keywords.split(",")
return arr
end
def entry_array(channel)
arr = []
channel.xpath("//item").each do |item|
arr.push(item)
end
return arr
end
end
class Item
def initialize(origin)
#origin = origin
end
def description
#origin.xpath("*[name()='itunes:subtitle']").text
end
def release
#origin.xpath("pubDate").text
end
def image
#origin.xpath("*[name()='itunes:image']/#href").text
end
def explicit
explicit_check(#origin)
end
def duration
#origin.xpath("*[name()='itunes:duration']").text
end
def title
#origin.xpath("title").text
end
def enclosure_url
#origin.xpath("enclosure/#url").text
end
def enclosure_length
#origin.xpath("enclosure/#length").text
end
def enclosure_type
#origin.xpath("enclosure/#type").text
end
def keywords
keywords_array(#origin.xpath("*[name()='itunes:keywords']").text)
end
def self.fresh(entry)
#episode = Itunes::Item.new entry
return {
description: #episode.description,
release: #episode.release,
image: #episode.image,
explicit: #episode.explicit,
duration: #episode.duration,
title: #episode.title,
enclosure_url: #episode.enclosure_url,
enclosure_length: #episode.enclosure_length,
enclosure_type: #episode.enclosure_type,
keywords: #episode.keywords
}
end
private
def explicit_check(item)
string = item.xpath("*[name()='itunes:explicit']").text
if string === "yes" || string === "Yes"
true
else
false
end
end
def keywords_array(item)
keywords = item.split(",")
return keywords
end
end
end
Before anything else, good for you for using service objects! I've been using this approach a great deal and find POROs preferable to fat models in many situations.
It appears the behavior you're interested in testing is contained in Parser.initialize.
First, I'd create a class method for Parser called parse. IMO, Parser.parse(importer) is clearer about what Parser is doing than is Parser.new(importer). So, it might look like:
#services/parser.rb
class Parser
class << self
def parse(importer)
#importer = importer
#feed = Feed.new(importer)
if #show = Show.where(rss_link: importer.url).first
create_new_episodes Itunes::Channel.refresh(#feed.origin)
else
create_show_and_episodes
end
end # parse
end
end
Then add the create_new_episodes and create_show_and_episodes class methods.
#services/parser.rb
class Parser
class << self
def parse(importer)
#importer = importer
#feed = Feed.new(importer)
if #show = Show.where(rss_link: #importer.url).first
create_new_episodes Itunes::Channel.refresh(#feed.origin)
else
create_show_and_episodes
end
end # parse
def create_new_episodes(new_episodes)
new_episodes.each do |new_episode|
#show.episodes.create #feed.episode(new_episode)
end
end # create_new_episodes
def create_show_and_episodes
new_show = Show.new(#feed.show) if (#feed && #feed.show)
if (new_show.save && new_show.entries.any?)
new_show.entries.each do |entry|
new_show.episodes.create #feed.episode(entry)
end
end
end # create_show_and_episodes
end
end
Now you have a Parser.create_new_episodes method that you can test independently. So, your test might look something like:
require 'rspec_helper'
describe Parser do
describe '.create_new_episodes' do
context 'when an initial parse has been completed' do
before(:each) do
first_file = Nokogiri::XML(open('spec/fixtures/feed_1.xml'))
#second_file = Nokogiri::XML(open('spec/fixtures/feed_2.xml'))
Parser.create_show_and_episodes first_file
end
it 'changes Episodes.count by 1' do
expect{Parser.create_new_episodes(#second_file)}.to change{Episodes.count}.by(1)
end
it 'changes Show.count by 0' do
expect{Parser.create_new_episodes(#second_file)}.to change{Show.count}.by(0)
end
end
end
end
Naturally, you'll need feed_1.xml and feed_2.xml in the spec\fixtures directory.
Apologies for any typos. And, I didn't run the code. So, might be buggy. Hope it helps.
I'm using a custom class to make AR instances from Feedjirra. I can't get the children instances to relate to their parent objects.
Show has_many :episodes -
Episode belongs_to :show -
show_id is always nil.
RSpec logs #show.id and #episode.show_id as equal to one another. However when I run episode = Episode.first after running an import in development, the episode has its show_id set to nil.
#show = Show.new
#show.name = #feed.title
#show.description = #feed.description
...
if #show.save
puts "#show.id: #{#show.id}"
end
#episodes = []
#feed.entries.each do |item|
#episodes.push(item)
end
#episodes.each do |item|
#episode = #show.episodes.new
#episode.name = item.title
#episode.description = item.summary
...
if #episode.save
puts "#episode.show_id: #{#episode.show_id}"
end
end
I tried using #episode = #show.episodes.create, as well as #episode = Episode.new with #episode.show_id = #show.id. They all log matching IDs but show_id is still nil on the instances. Every other column is filled in correctly.
I thought the issue may have had to do with using add_foreign_key:
class AddShowToEpisodes < ActiveRecord::Migration
def change
add_reference :episodes, :show, index: true
add_foreign_key :episodes, :shows, column: :show_id
end
end
So I removed that and used the standard foreign_key: true but it had no effect.
class RemoveShowFromEpisodes < ActiveRecord::Migration
def change
remove_column :episodes, :show_id
end
end
class AddShowBackToEpisodes < ActiveRecord::Migration
def change
add_reference :episodes, :show, index: true, foreign_key: true
end
end
Here's the full code in case it helps.
importers_controller.rb:
class Admin::ImportersController < Admin::ApplicationController
before_action :set_importer, only: [:show, :edit, :update, :destroy]
def index
#importers = policy_scope(Importer)
end
def show
end
def new
#importer = Importer.new
authorize #importer
end
def create
#importer = Importer.new(importer_params)
authorize #importer
if #importer.save
require "subscription_importer"
SubscriptionImporter.new(#importer)
flash[:notice] = "Importer added."
redirect_to admin_importers_path
else
flash[:error] = "Importer not added."
render "new"
end
end
def edit
end
def update
end
def destroy
end
private
def set_importer
#importer = Importer.find(params[:id])
authorize #importer
end
def importer_params
params.require(:importer).permit(:name, :url, :source)
end
end
subscription_importer.rb:
class SubscriptionImporter
def initialize(importer)
#importer = importer
#feed = Feedjira::Feed.fetch_and_parse #importer.url
if #importer.source === "iTunes"
itunes_parser(#importer)
end
end
def itunes_parser(importer)
#importer = importer
# Parser
#feed = Feedjira::Feed.fetch_and_parse #importer.url
# Show
#show = Show.new
#show.name = #feed.title
#show.description = #feed.description
#show.logo = #feed.itunes_image
#show.explicit = explicit_check(#feed.itunes_explicit)
#show.genre = #feed.itunes_categories
#show.tags = #feed.itunes_keywords
#show.url = #feed.url
#show.language = #feed.language
if #show.save
puts "Show import succeeded"
puts "#show.id: #{#show.id}"
else
puts "Show import failed"
end
# Episodes
#episodes = []
#feed.entries.each do |item|
#episodes.push(item)
end
#episodes.each do |item|
#episode = #show.episodes.new
#episode.name = item.title
#episode.description = item.summary
#episode.release = item.published
#episode.image = item.itunes_image
#episode.explicit = explicit_check(item.itunes_explicit)
#episode.tags = item.itunes_keywords
#episode.url = item.enclosure_url
#episode.duration = item.itunes_duration
if #episode.save
puts "Episode import succeeded"
puts "#episode.show_id: #{#episode.show_id}"
else
puts "Episode import failed"
end
end
end
def explicit_check(string)
if string == "yes" || "Yes"
true
else
false
end
end
end
create_importer_spec.rb:
require "rails_helper"
RSpec.feature "Admins can create importers" do
let(:user) { FactoryGirl.create(:user, :admin) }
context "admins" do
before do
login_as(user)
visit "/"
click_link "Admin"
click_link "Importers"
click_link "New Importer"
end
scenario "with valid credentials" do
fill_in "Name", with: "The Stack Exchange Podcast"
fill_in "Url", with: "https://blog.stackoverflow.com/feed/podcast/" # Needs stubbing
select "iTunes", from: "Source"
click_button "Create Importer"
expect(page).to have_content "Importer added"
expect(page).to have_content "The Stack Exchange Podcast"
end
scenario "with invalid credentials" do
fill_in "Name", with: ""
fill_in "Url", with: ""
click_button "Create Importer"
expect(page).to have_content "Importer not added"
end
end
end
I think the episodes functionality in your SubscriptionImporter class is causing the problem...
#episodes = []
#feed.entries.each do |item|
#episodes.push(item) #-> each "#episodes" is a FeedJirra object
end
#episodes.each do |episode|
#-> you're now creating an episode in the same call as show, which will either mean that show is not persisted or perhaps some other error
end
I would personally limit the SubscriptionImporter functionality to only return data. You should be parsing that data through the respective models:
#app/controllers/admin/importers_controller.rb
class Admin::ImportersController < Admin::ApplicationController
def create
#import = Importer.new import_params
if #import.save
#import.parse_show if #import.itunes?
end
end
private
def import_params
params.require(:importer).permit(:name, :url, :source)
end
end
#app/models/importer.rb
class Importer < ActiveRecord::Base
def feed
return false unless itunes?
origin = Feedjirra::Feed.fetch_and_parse(self.url)
return {
name: origin.title,
description: origin.description,
logo: origin.itunes_image,
explicit: explicit_check(origin.itunes_explicit),
genre: origin.itunes_categories,
tags: origin.itunes_keywords,
url: origin.url,
language: origin.language,
entries: origin.entries
}
end
def parse_show
Show.create(feed)
end
def itunes?
self.source == "iTunes" #-> true/false
end
private
def explicit_check
string == "yes" || "Yes" #-> true/false
end
end
#app/models/show.rb
class Show < ActiveRecord::Base
has_many :episodes
attr_accessor :entries
after_create :create_episodes #-> might not persist entries
def create_episodes
if self.entries.any?
self.entries.each do |item|
self.episodes.create({
name: item.title
description: item.summary,
release: item.published,
image: item.itunes_image,
explicit: explicit_check?(item.itunes_explicit),
tags: item.itunes_keywords,
url: item.enclosure_url,
duration: item.itunes_duration
})
end
end
end
private
def explicit_check?
string == "yes" || "Yes"
end
end
The above will allow you to create an #importer, pull the feed from it, and populate Show & Episode models with the returned data.
Whilst this should resolve your issue, you need to consider OOP -- making each element an object.
Update
If you wanted to objectify this even more, there is a simple pattern to adopt:
Importer is all you need to save -- everything else should happen around this
Show + Episode could be the same class / table for all I know
With this in mind, you could do the following:
#app/controllers/admin/importers_controller.rb
class Admin::ImportersController < Admin::ApplicationController
def create
#import = Importer.new import_params
#import.save
end
private
def import_params
params.require(:importer).permit(:name, :url, :source)
end
end
#app/services/feed.rb
class Feed
attr_reader :params, :show, :episode, :origin
def initialize(params)
#params = params
end
def origin
#origin = Feedjirra::Feed.fetch_and_parse params[:source]
end
def show
#show = ShowHelper.new #origin
end
def episodes
#show.episodes
end
end
#app/services/show_helper.rb
class ShowHelper
attr_reader :origin
def initialize(origin)
#origin = origin
end
def name
#origin.title
end
def description
#origin.summary || #origin.description
end
def logo
#origin.itunes_image
end
def explicit
%r{^yes$} =~ #origin.itunes_explicit
end
def genre
#origin.itunes_categories
end
def tags
#origin.itunes_keywords
end
def url
#origin.url
end
def language
#origin.language
end
def episodes
#origin.entries
end
end
#app/models/importer.rb
class Importer < ActiveRecord::Base
after_create :parse_show, if: "itunes?"
validates :source, :url, :name, presence: true
def itunes?
source == "iTunes"
end
def feed
#feed = Feed.new(self)
end
private
def parse_show
#show = Show.new(feed.show) if feed && feed.show
if #show.save && #show.entries.any?
#show.entries.each do |entry|
#show.episodes.create ShowHelper.new(entry)
end
end
end
end
When I run my app, I get an error that states: undefined local variable or method `signup' for #, but I'm not sure why this is happening. According to the code below, Signup is a new class that I've defined.
Thanks for your help!
Controller code:
class SignupsController < ApplicationController
def new
#signup = Signup.new
end
def create
#signup = Signup.new(signup_params)
if #signup.save
signup.add_subscrip
else
redirect_to new_signup_path
end
end
end
Model code:
class Signup < ActiveRecord::Base
validates :email, presence: true, format: { with: /\A[\w+\-.]+#[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i }
validates :name, presence: true, length: { maximum: 50 }
def add_subscrip
connection = GoogleDrive.login(ENV['g_username'], ENV['g_password'])
ss = connection.spreadsheet_by_title(ENV['spreadsheet_title'])
ws = ss.worksheets[0]
row = 3 + ws.num_rows
ws[row, 1] = self.name
ws[row, 2] = Time.new
ws[row, 3] = self.email
ws.save
end
end
In your create method
def create
#signup = Signup.new(signup_params)
if #signup.save
signup.add_subscrip
else
redirect_to new_signup_path
end
end
My sense is that
signup.add_subscrip
needs to be
#signup.add_subscrip