This below method hits the database when saving an account, when saving a user, when updating the unit with the account id, when create a new unit_users record (associating unit with a user). So that's at least 4 times it hits the database:
def activate_new_account(assign_units = [])
account = Account.new(
:name => self.name,
:email => self.email,
:phone => self.phone,
:street_address => self.street_address,
:city => self.city,
:state => self.state,
:postal_code => self.postal_code,
:country => self.country)
errors.clear
error_msgs = []
transaction do
if account.valid?
account.save
user = User.new(:name => self.name,
:email => self.email,
:password => self.password,
:password_confirmation => self.password_confirmation,
:phone => self.phone,
:address => formatted_address,
:role_id => self.user_role_id,
:account_id => account.id)
if user.valid?
user.save
if units_for_account
begin
units = Unit.find(units_for_account.split(" "))
units.each do |unit|
#hitting database twice
unit.update_attributes account_id: account.id
unit.users << user
end
rescue ActiveRecord::RecordNotFound
error_msgs << "Couldn't find all Units with serial numbers: #{units_for_account.split(' ')}"
rescue ActiveRecord::RecordInvalid => invalid
error_msgs << invalid.record.errors
end
end
else
account.destroy
error_msgs << user.errors.full_messages
end
else
error_msgs << account.errors.full_messages
end
end
if error_msgs.size > 0
error_msgs.each do |error|
errors.add :base, error
end
return false
end
return true
end
Is there a more Railsy way to do this without hitting database so much?
There is a much more Rails way to accomplish the activation, by using validates_associated.
But it does'n access the database less. You have four tables to update or add rows, so you need four DB statements.
Related
I have my site in ruby on rails and for subscription payments I am using the paypal paypal-sdk-rest gem. But I need the first payment to have a lower value and then the next payment to have the normal value so that users can subscribe and test the subscription. I have been reading in the paypal api and a trial with a lower value can be applied. Is it possible to apply trial to the paypal gem paypal-sdk-rest? this is my code of how I create the plans:
def creacion_planes
plan = Plan.new({
:name => 'Monthly $20',
:description => '$20 plan (monthly charge)',
:type => 'infinite',
:payment_definitions => [{
:name => 'Plan monthly $20',
:type => 'REGULAR',
:frequency_interval => '1',
:frequency => 'MONTH', #WEEK, DAY, YEAR, MONTH.
:cycles => '0',
:amount => {
:currency => 'USD',
:value => '20.00'
}
}],
:merchant_preferences => {
:return_url => complete_paypal_checkouts_planes_url,
:cancel_url => update_plan_url,
:max_fail_attempts => '0',
:auto_bill_amount => 'YES',
:initial_fail_amount_action => 'CONTINUE'
}
})
# Create plan
if plan.create
# Plan update activation object
plan_update = {
:op => 'replace',
:path => '/',
:value => {
:state => 'ACTIVE'
}
}
# Activate plan
if plan.update(plan_update)
puts("Billing plan activated with ID [#{plan.id}]")
redirect_to success_payment_path(:plan_id => plan.id, :plan => "plan_mensual20")
else
logger.error payment.error.inspect
end
else
logger.error payment.error.inspect
end
end
And this is my code of how I create the agreement:
def create
agreement = Agreement.new({
:name => params[:name],
:description => params[:description],
:start_date => (Time.now + 20*60).utc.iso8601, #'2020-04-26T23:00:04Z' (Time.now + 1.days).utc.iso8601
:plan => {
:id => params[:plan_id]
},
:payer => {
:payment_method => 'paypal'
}
})
if agreement.create
redirect = agreement.links.find{|v| v.rel == "approval_url" }.href
redirect_to redirect
else
logger.error agreement.error.inspect
end
end
Do not use that old paypal-ruby-sdk. It is obsolete and uses an old version of billing plans, which is not compatible with the current subscriptions API.
Instead, integrate the subscriptions API via direct HTTPS calls. Here is the guide: https://developer.paypal.com/docs/subscriptions/
An example with a trial period is provided.
I be able to see the output in heroku by fixing errors in Gemfile
Errors in Gemfile
Also I could login as admin...but only one time...then my password is not recognized and login
is not successful...
I could not save my password on admin page(error:Password doesn't match confirmation) and could not login
using admin password provided(error:Login unsuccessful)
I've tried to create admin and password manually but got errors.
How to login using admin credential?
thanks
Errors and files related as below
//errors
typo-1 (master) $ rails console
Loading development environment (Rails 3.0.17)
1.9.3-p551 :001 > User.create(:username => 'admin',
1.9.3-p551 :002 > :password => 'abc123',
1.9.3-p551 :003 > :password_confirmation => 'abc123')
ActiveRecord::UnknownAttributeError: unknown attribute: username
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1565:in `block in attributes='
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1561:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1561:in `attributes='
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1412:in `initialize'
from /home/ubuntu/workspace/typo-1/app/models/user.rb:53:in `initialize'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:502:in `new'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:502:in `create'
from (irb):1
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands/console.rb:44:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3-p551 :004 > User.create(:username => 'admin',
1.9.3-p551 :005 > :password_confirmation => 'abc123')
ActiveRecord::UnknownAttributeError: unknown attribute: username
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1565:in `block in attributes='
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1561:in `each'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1561:in `attributes='
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:1412:in `initialize'
from /home/ubuntu/workspace/typo-1/app/models/user.rb:53:in `initialize'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:502:in `new'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/activerecord-3.0.17/lib/active_record/base.rb:502:in `create'
from (irb):4
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands/console.rb:44:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands/console.rb:8:in `start'
from /usr/local/rvm/gems/ruby-1.9.3-p551/gems/railties-3.0.17/lib/rails/commands.rb:23:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
1.9.3-p551 :006 >
//controllers/admin/users_controller.rb
class Admin::UsersController < Admin::BaseController
cache_sweeper :blog_sweeper
def index
#users = User.order('login asc').page(params[:page]).per(this_blog.admin_display_elements)
end
def new
#user = User.new
#user.attributes = params[:user]
#user.text_filter = TextFilter.find_by_name(this_blog.text_filter)
setup_profiles
#user.name = #user.login
if request.post? and #user.save
flash[:notice] = _('User was successfully created.')
redirect_to :action => 'index'
end
end
def edit
#user = params[:id] ? User.find_by_id(params[:id]) : current_user
setup_profiles
#user.attributes = params[:user]
if request.post? and #user.save
if #user.id = current_user.id
current_user = #user
end
flash[:notice] = _('User was successfully updated.')
redirect_to :action => 'index'
end
end
def destroy
#record = User.find(params[:id])
return(render 'admin/shared/destroy') unless request.post?
#record.destroy if User.count > 1
redirect_to :action => 'index'
end
private
def setup_profiles
#profiles = Profile.find(:all, :order => 'id')
end
end
//models/user.rb
require 'digest/sha1'
# Typo user.
class User < ActiveRecord::Base
include ConfigManager
belongs_to :profile
belongs_to :text_filter
delegate :name, :to => :text_filter, :prefix => true
delegate :label, :to => :profile, :prefix => true
has_many :notifications, :foreign_key => 'notify_user_id'
has_many :notify_contents, :through => :notifications,
:source => 'notify_content',
:uniq => true
has_many :articles, :order => 'created_at DESC'
serialize :settings, Hash
# Settings
setting :notify_watch_my_articles, :boolean, true
setting :editor, :string, 'visual'
setting :firstname, :string, ''
setting :lastname, :string, ''
setting :nickname, :string, ''
setting :description, :string, ''
setting :url, :string, ''
setting :msn, :string, ''
setting :aim, :string, ''
setting :yahoo, :string, ''
setting :twitter, :string, ''
setting :jabber, :string, ''
setting :show_url, :boolean, false
setting :show_msn, :boolean, false
setting :show_aim, :boolean, false
setting :show_yahoo, :boolean, false
setting :show_twitter, :boolean, false
setting :show_jabber, :boolean, false
setting :admin_theme, :string, 'blue'
# echo "typo" | sha1sum -
class_attribute :salt
def self.salt
'20ac4d290c2293702c64b3b287ae5ea79b26a5c1'
end
attr_accessor :last_venue
def initialize(*args)
super
self.settings ||= {}
end
def self.authenticate(login, pass)
find(:first,
:conditions => ["login = ? AND password = ? AND state = ?", login, password_hash(pass), 'active'])
end
def update_connection_time
self.last_venue = last_connection
self.last_connection = Time.now
self.save
end
# These create and unset the fields required for remembering users between browser closes
def remember_me
remember_me_for 2.weeks
end
def remember_me_for(time)
remember_me_until time.from_now.utc
end
def remember_me_until(time)
self.remember_token_expires_at = time
self.remember_token = Digest::SHA1.hexdigest("#{email}--#{remember_token_expires_at}")
save(:validate => false)
end
def forget_me
self.remember_token_expires_at = nil
self.remember_token = nil
save(:validate => false)
end
def permalink_url(anchor=nil, only_path=false)
blog = Blog.default # remove me...
blog.url_for(
:controller => 'authors',
:action => 'show',
:id => login,
:only_path => only_path
)
end
def self.authenticate?(login, pass)
user = self.authenticate(login, pass)
return false if user.nil?
return true if user.login == login
false
end
def self.find_by_permalink(permalink)
self.find_by_login(permalink).tap do |user|
raise ActiveRecord::RecordNotFound unless user
end
end
def project_modules
profile.project_modules
end
# Generate Methods takes from AccessControl rules
# Example:
#
# def publisher?
# profile.label == :publisher
# end
AccessControl.roles.each do |role|
define_method "#{role.to_s.downcase}?" do
profile.label.to_s.downcase == role.to_s.downcase
end
end
def self.to_prefix
'author'
end
def simple_editor?
editor == 'simple'
end
def password=(newpass)
#password = newpass
end
def password(cleartext = nil)
if cleartext
#password.to_s
else
#password || read_attribute("password")
end
end
def article_counter
articles.size
end
def display_name
name
end
def permalink
login
end
def to_param
permalink
end
def admin?
profile.label == Profile::ADMIN
end
protected
# Apply SHA1 encryption to the supplied password.
# We will additionally surround the password with a salt
# for additional security.
def self.password_hash(pass)
Digest::SHA1.hexdigest("#{salt}--#{pass}--")
end
def password_hash(pass)
self.class.password_hash(pass)
end
before_create :crypt_password
# Before saving the record to database we will crypt the password
# using SHA1.
# We never store the actual password in the DB.
# But before the encryption, we send an email to user for he can remind his
# password
def crypt_password
send_create_notification
write_attribute "password", password_hash(password(true))
#password = nil
end
before_update :crypt_unless_empty
# If the record is updated we will check if the password is empty.
# If its empty we assume that the user didn't want to change his
# password and just reset it to the old value.
def crypt_unless_empty
if password(true).empty?
user = self.class.find(self.id)
write_attribute "password", user.password
else
crypt_password
end
end
before_validation :set_default_profile
def set_default_profile
if User.count.zero?
self.profile ||= Profile.find_by_label('admin')
else
self.profile ||= Profile.find_by_label('contributor')
end
end
validates_uniqueness_of :login, :on => :create
validates_uniqueness_of :email, :on => :create
validates_length_of :password, :within => 5..40, :if => Proc.new { |user|
user.read_attribute('password').nil? or user.password.to_s.length > 0
}
validates_presence_of :login
validates_presence_of :email
validates_confirmation_of :password
validates_length_of :login, :within => 3..40
private
# Send a mail of creation user to the user create
def send_create_notification
begin
email_notification = NotificationMailer.notif_user(self)
EmailNotify.send_message(self, email_notification)
rescue => err
logger.error "Unable to send notification of create user email: #{err.inspect}"
end
end
end
//editing: replacement user_id to login
$ rails console
Loading development environment (Rails 3.0.17)
1.9.3-p551 :001 > User.create(login: 'admin', password: 'password123', password_confirmation: 'password123')
=> #<User id: nil, login: "admin", password: nil, email: nil, name: nil, notify_via_email: nil, notify_on_new_articles: nil, notify_on_comments: nil, profile_id: 3, remember_token: nil, remember_token_expires_at: nil, text_filter_id: "1", state: "active", last_connection: nil, settings: {}>
1.9.3-p551 :002 > exit
According to your error message you don't have username field in your User model.
ActiveRecord::UnknownAttributeError: unknown attribute: username
I think you are using attribute login in your model. Try to replace username with login and see if that works.
User.create(login: 'admin', password: 'password123', password_confirmation: 'password123')
or you can post schema for User model and we can have a look.
Typo is an old legacy insecure app which no one particularly supporting.
Also this version doesn't support email and login credentials in the first place.
That why you can only login using initial credentials and got error if you want to renew this credentials.
The latest version of typo (now called publify):
https://github.com/publify/publify
This version supposed to support email and supposed to be maintained.
I have an app that has some basic ecommerce activity. I tried it with a test authorize.net account, and it works fine. I entered in the APIs for production mode though, and I keep getting redirected to the failure screen when I try to purchase anything. I'm not getting any errors, nothing in the logs on heroku, and I don't even know where to start debugging. I am connecting to Authorize.net successfully, transactions are successful in development mode - I based it heavily off of Ryan Bate's RailsCast episode 145 (http://railscasts.com/episodes/145-integrating-active-merchant), but here are some highlights of my code (since I'm testing ti, I'm forcing it to do 1 cent transactions despite what I order)
in enviroments/production.rb
config.after_initialize do
ActiveMerchant::Billing::Base.mode = :production
::GATEWAY = ActiveMerchant::Billing::AuthorizeNetGateway.new(
:login => "scrubbed",
:password => "scrubbed",
:test => false
)
end
orders_controller.rb
def create
#order = Order.new(params[:order])
#order.cart = current_cart
if #order.save
if #order.purchase
#order.state = 'paid'
#order.save
render :action => "success"
end
else
render :action => "failure"
end
else
redirect_to home_page_path, notice: "The order failed to save"
end
end
def purchase
response = GATEWAY.purchase(1, credit_card, purchase_options)
transactions.create!(:action => "purchase", :amount => price_in_cents, :response => response)
#cart.update_attribute(:purchased_at, Time.now) if response.success?
response.success?
end
order.rb
def purchase
response = GATEWAY.purchase(1, credit_card, purchase_options)
transactions.create!(:action => "purchase", :amount => price_in_cents, :response => response)
#cart.update_attribute(:purchased_at, Time.now) if response.success?
response.success?
end
private
def purchase_options
{
:ip => ip_address,
:billing_address => {
:first_name => first_name,
:last_name => last_name,
:address1 => address_line_1,
:address2 => address_line_2,
:city => city,
:state => billing_state,
:country => "US",
:zip => zip_code,
:phone => phone_number,
:company => company
},
:shipping_address => {
:first_name => sfirst_name,
:last_name => slast_name,
:address1 => saddress_line_1,
:address2 => saddress_line_2,
:city => scity,
:state => sbilling_state,
:country => "US",
:zip => szip_code,
:phone => sphone_number,
:company => scompany
}
}
end
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors.add :base, message
end
end
end
def credit_card
#credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:brand => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
end
I haven't personally dealt with authorize.net but I have used a similar web service which also required PCI compliance. In my case this meant that I needed a valid SSL certificate for transactions to work in production. In fact, if I remember correctly the transaction was failing in a very similar way and it wasn't obvious that was the cause.
It looks like authorize.net requires some type of security depending on which API you are making use of.
http://developer.authorize.net/integration/
I need to ask just to be sure - Have you done everything to get your merchant account setup with Authorize.net and your Bank for production usage already, and you've coordinated with them to start posting funds to your bank account when the money starts coming in?
If so, check out their developer documentation page here for the difference between test and production transactions
http://developer.authorize.net/guides/AIM/5_TestTrans.html
Transactions that work in test mode should work in production mode when everything is properly configured on the Gateway side. I would contact authorize.net there may be technical or administrative details which need to be finalized for your account to process live transactions.
I'm using ActiveMerchant gem with Ruby 1.9.3 and Rails 3.1
I already set up a buyer dummy account and a seller dummy account on PayPal using WebPayments Pro. When I run this script and look in my paypal sandbox, my seller account is deposited $10 in funds correctly.
The problem is that when I look at the sandbox for my buyer account, the balance does not decrease. Where is my seller getting the money from?
My code is here:
require "rubygems"
require "active_merchant"
ActiveMerchant::Billing::Base.mode = :test
gateway = ActiveMerchant::Billing::PaypalGateway.new(
:login => "seller_1328509472_biz_api1.gmail.com",
:password => "*******",
:signature => "******"
)
credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:type => "visa",
:number => "4193536536887351",
:verification_value => "123",
:month => 2,
:year => 2017,
:first_name => "TESTING",
:last_name => "BUYER"
)
if credit_card.valid?
response = gateway.authorize(1000, credit_card, :ip => "98.248.144.120", :billing_address => { :name => 'Test User', :company => '', :address1 => '1 Main St', :address2 => '', :city => 'San Jose', :state => 'CA', :zip => '95131'})
if response.success?
gateway.capture(1000, response.authorization)
else
puts "Response Unsuccessful Error: #{response.message}"
end
else
puts "Error: credit card is not valid. #{credit_card.errors.full_messages.join('. ')}"
end
Please help me! I have been stuck on this for ages, and I am very confused.
Because you're specifying a credit card directly, there is no 'account' as such that it takes the funds from.
The API method you're using, DoDirectPayment, charges a credit card directly. It is not connected to a PayPal account, nor does it use the balance of a PayPal account.
If you want to charge a PayPal account rather than a credit card, use PayPal Express Checkout: http://railscasts.com/episodes/146-paypal-express-checkout
I am using faker to generate sample data. I have this as follows:
require 'faker'
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
User.create!(:name => "rails",
:email => "example#railstutorial.org",
:password => "foobar",
:password_confirmation => "foobar")
99.times do |n|
#name = Faker::Name.name
name = "rails#{n+1}"
email = "example-#{n+1}#railstutorial.org"
password = "password"
user = User.create!(:name => name,
:email => email,
:password => password,
:password_confirmation => password)
end
end
end
The problem is that I have a couple of after_save callbacks that are not being called when the User is created. Why is that? Thanks
The methods:
after_save :create_profile
def create_profile
self.build_profile()
end
In all my reading, it seems that save! bypasses any custom before_save, on_save or after_save filters you have defined. The source code for create! reveals that it invokes save!. Unless you absolutely NEED the bang version, why are you using it? Try removing all your bang methods and just invoking the non-bang versions:
[1..100].each do |n|
name = "rails#{n+1}"
email = "example-#{n+1}#railstutorial.org"
password = "password"
user = User.new(:name => name, :email => email, :password => password, :password_confirmation => password)
if !user.save
puts "There was an error while making #{user.inspect}"
end
end