spree_chimpy:merge_vars:sync rake aborted - ruby-on-rails

I am installing the gem spree_chimpy from https://github.com/watg/spree_chimpy in my Ruby on Rails application with spree. After doing mailchimp setup I am notifying mailchimp about merge_vars which seem to cause the error. When I run the command
rake spree_chimpy:merge_vars:sync --trace
I get the error "tag" must be 10 bytes and may only contain "A-Z 0-9 _. I don't understand the error, I have nowhere added any tag variable in the configuration. For reference, my config/initializers/spree_chimpy.rb is pasted here:
Spree::Chimpy.config do |config|
# your API key as provided by MailChimp
config.key = '<#my-api-hash-key>'
# extra api options for the Mailchimp gem
# config.api_options = { throws_exceptions: false, timeout: 3600 }
# name of your list, defaults to "Members"
config.list_name = 'test'
# Allow users to be subscribed by default. Defaults to false
# If you enable this option, it's strongly advised that your enable
# double_opt_in as well. Abusing this may cause Mailchimp to suspend your account.
# config.subscribed_by_default = false
# When double-opt is enabled, the user will receive an email
# asking to confirm their subscription. Defaults to false
config.double_opt_in = false
# id of your store. max 10 letters. defaults to "spree"
# config.store_id = 'acme'
# define a list of merge vars:
# - key: a unique name that mail chimp uses. 10 letters max
# - value: the name of any method on the user class.
# default is {'EMAIL' => :email}
config.merge_vars = {
'EMAIL' => :email,
'FNAME' => :fname,
'LNAME' => :lname,
'ORDERNUMBER' => :onumber
}
end

That error is being thrown is from somewhere around here:
https://github.com/watg/spree_chimpy/blob/7ba5d855112050e1b61c2d0a3369bc08f254842d/lib/spree_chimpy.rb#L59-L62
The actual error is within the mailchimp API client. You're getting the error because ORDERNUMBER has 11 characters in it. If you trim it down to 10 characters, you should be okay.

Related

Existence of ActiveModel::SecurePassword authenticate method (Rails 6)

The "authenticate" method can only be found here: https://apidock.com/rails/ActiveModel/SecurePassword/InstanceMethodsOnActivation/authenticate
, with version 6.0.0 being grayed out. So this seems to be outdated.
I have searched the Rails 6 documentation for the authenticate method, and found no record of it under https://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html.
Yet in the code snippet on the same page
# Schema: User(name:string, password_digest:string, recovery_password_digest:string)
class User < ActiveRecord::Base
has_secure_password
has_secure_password :recovery_password, validations: false
end
user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
user.save # => false, password required
user.password = 'mUc3m00RsqyRe'
user.save # => false, confirmation doesn't match
user.password_confirmation = 'mUc3m00RsqyRe'
user.save # => true
user.recovery_password = "42password"
user.recovery_password_digest # => "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"
user.save # => true
user.authenticate('notright') # => false
user.authenticate('mUc3m00RsqyRe') # => user
user.authenticate_recovery_password('42password') # => user
User.find_by(name: 'david')&.authenticate('notright') # => false
User.find_by(name: 'david')&.authenticate('mUc3m00RsqyRe') # => user
The authenticate method is still used (user.authenticate). Where does this method come from if I can't find it in the latest documentation?
Edit:
A related question regarding differences in documentation: I am able to find ActionDispatch::Request::Session on rubydocs but not on api.rubyonrails.
https://www.rubydoc.info/docs/rails/ActionDispatch/Request/Session
https://api.rubyonrails.org/classes/ActionDispatch/Request.html
Now I am not certain where I should be looking when searching for methods. Is api.rubyonrails not the "definitive" place to look for documentation?
It looks like they forgot to mention it in the documentation for has_secure_password. If you look into source code of ActiveModel::SecurePassword. You will find
# Returns +self+ if the password is correct, otherwise +false+.
#
# class User < ActiveRecord::Base
# has_secure_password validations: false
# end
#
# user = User.new(name: 'david', password: 'mUc3m00RsqyRe')
# user.save
# user.authenticate_password('notright') # => false
# user.authenticate_password('mUc3m00RsqyRe') # => user
define_method("authenticate_#{attribute}") do |unencrypted_password|
attribute_digest = public_send("#{attribute}_digest")
BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self
end
alias_method :authenticate, :authenticate_password if attribute == :password
You can se it is now defined as dynamic method based on the parametr name provided to has_secure_password method. So they implemented it in more general way. And to be more friendly with backwards compatibility the implemented the alias authenticate for authenticate_password which was the original implementation.
Unfortunately these dynamic methods are not very well documented in the rails API docs.

Activemerchat paypal integration is giving an error Missing required parameter: ip?

I used the below code to test my sandbox credentials but am getting the error mentioned please help in resolving the issue
> require 'activemerchant'
> #gateway = ActiveMerchant::Billing::PaypalGateway.new(
:login "abc.cc#gmail.com,
password: "weret43435ersdfdg",
signature: "ertygdfcf343333#####frfterg")
> purchase = #gateway.purchase((10* 100),
:ip => '198.16.43.574',
:currency => "USD",
:payer_id => "2",
:token => "dsfddgfdgfdgfdgdf")
When i use the above code in irb am getting the following error
ArgumentError: Missing required parameter: ip
enter image description here
If you check the source code of ActiveMerchant here, it is expecting 3 params.
def purchase(money, credit_card_or_referenced_id, options = {})
requires!(options, :ip)
commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Sale', money, credit_card_or_referenced_id, options)
end
First one is the amount of money, second one is the credit card or reference id and the third one is a option, where it is expecting a required ip. As in your method call you are not passing any credit card reference, it's missing the ip from the option hash.

undefined method: connect_timeout

Browser error:
NoMethodError
undefined method `connect_timeout=' for #<Mysql2::Client:0x47f7570>
On my browser, an error comes up that connect_timeout is undefined. I'm pretty sure it has something to do with the client.rb file. I'll show you the file. I had to edit some of it to actually get Webrick up and running. When I started the server, an error always appeared on my command line unless I made the changes. I've commented on what I have edited. Sometimes edited random things and some of them worked but they produced different errors on my browser. I am using a windows 8 machine. Thank you for helping.
module Mysql2
class Client
attr_reader :query_options, :read_timeout
##default_query_options = {
:as => :hash, # the type of object you want each row back as; also supports :array (an array of values)
:async => false, # don't wait for a result after sending the query, you'll have to monitor the socket yourself then eventually call Mysql2::Client#async_result
:cast_booleans => false, # cast tinyint(1) fields as true/false in ruby
:symbolize_keys => false, # return field names as symbols instead of strings
:database_timezone => :local, # timezone Mysql2 will assume datetime objects are stored in
:application_timezone => nil, # timezone Mysql2 will convert to before handing the object back to the caller
:cache_rows => true, # tells Mysql2 to use it's internal row cache for results
#:connect_flags => REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION,
#I had to delete the line above because for some reason the command prompt said that each of the constants were undefined were not used in the right place or something
:cast => true,
:default_file => nil,
:default_group => nil
}
def initialize (opts = {})
opts = Mysql2::Util.key_hash_as_symbols( opts )
#read_timeout = nil
#query_options = ##default_query_options.dup
#query_options.merge! opts
#initialize_ext
# the chrome page said that the above variable is undefined :P
# Set default connect_timeout to avoid unlimited retries from signal interruption
opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
[:reconnect, :connect_timeout, :local_infile, :read_timeout, :write_timeout, :default_file, :default_group, :secure_auth, :init_command].each do |key|
next unless opts.key?(key)
case key
when :reconnect, :local_infile, :secure_auth
send(:"#{key}=", !!opts[key])
when :connect_timeout, :read_timeout, :write_timeout
send(:"#{key}=", opts[key].to_i)
else
send(:"#{key}=", opts[key])
end
end
# force the encoding to utf8
self.charset_name = opts[:encoding] || 'utf8'
ssl_options = opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher)
ssl_set(*ssl_options) if ssl_options.any?
if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| #query_options.has_key?(k) }
warn "============= WARNING FROM mysql2 ============="
warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be deprecated at some point in the future."
warn "Instead, please use :username, :password, :host, :port, :database, :socket, :flags for the options."
warn "============= END WARNING FROM mysql2 ========="
end
user = opts[:username] || opts[:user]
pass = opts[:password] || opts[:pass]
host = opts[:host] || opts[:hostname]
port = opts[:port]
database = opts[:database] || opts[:dbname] || opts[:db]
socket = opts[:socket] || opts[:sock]
flags = opts[:flags] ? opts[:flags] | #query_options[:connect_flags] : #query_options[:connect_flags]
# Correct the data types before passing these values down to the C level
user = user.to_s unless user.nil?
pass = pass.to_s unless pass.nil?
host = host.to_s unless host.nil?
port = port.to_i unless port.nil?
database = database.to_s unless database.nil?
socket = socket.to_s unless socket.nil?
connect user, pass, host, port, database, socket, flags
end
def self.default_query_options
##default_query_options
end
def query_info
info = query_info_string
return {} unless info
info_hash = {}
info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
info_hash
end
private
def self.local_offset
::Time.local(2010).utc_offset.to_r / 86400
end
end
end
Mysql2::Client#initialize called connect_timeout= but there isn't such attr_writer in the client.
when :connect_timeout, :read_timeout, :write_timeout
send(:"#{key}=", opts[key].to_i)
else
If this client is written by yourself, add attr_accessor :connect_timeout in Mysql2::Client's definition and make proper use of the attribute. If it is from other library, check your load path. You may have missed some files that opened Mysql2::Client and monkey patched it.

Select when devise send the confirmation mail or not

i need to select when devise send the confirmation mail. I overwrite the send_confirmation_instructions and add a date field named invited on my user model. If the invited field is null send the mail, otherwise not sent.
Here's my code:
def send_confirmation_instructions
unless invited.nil?
self.confirmation_token = nil if reconfirmation_required?
#reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
else
self.confirmation_token = nil if reconfirmation_required?
#reconfirmation_required = false
generate_confirmation_token! if self.confirmation_token.blank?
self.devise_mailer.confirmation_instructions(self).deliver
end
end
The output of my console its:
Loading development environment (Rails 3.0.10)
1.9.3-p0 :001 > User.create!(:email => "hello#test.com") NoMethodError: undefined method `reconfirmation_required?' for
I have rewrite many other devise method without problems. Any idea ?
Thanks in advance.
The best solution was to connect manually to the database and add the fields to the users table.
# read configuration from database.yml
config = Rails.application.config.database_configuration[Rails.env]
host = config["host"]
database = config["database"]
username = config["username"]
password = config["password"]
# stablish db connection
mysql = Mysql2::Client.new(:host => host, :username => username, :database => database, :password => password)
# generate devise confirmation token
token = (Digest::MD5.hexdigest "#{ActiveSupport::SecureRandom.hex(10)}-#{DateTime.now.to_s}")
# made the sql
sql = "INSERT INTO users (email, confirmation_token, confirmation_sent_at) VALUES ('email#test.com', '#{token}', '#{Time.now.to_s}')"
# execute query
mysql.query(sql)
# close mysql connection
mysql.close
I hope this will be useful.

Testing Rails Controllers Inherited from Typus

I've been fighting with this for a couple of days and there doesn't seem to be much help online. I've looked at the Typus wiki, sample app, and tests and I appear to be doing things correctly but I stil get HTTP Status Code 302 (Redirect) where I expect 200 (Success) in my tests.
Below are what should be the appropriate files (with irrelevant stuff removed)
config/initializers/typus.rb (rails g typus:migration has been run as I have an admin_users table):
Typus.setup do |config|
# Application name.
config.admin_title = "Something"
# config.admin_sub_title = ""
# When mailer_sender is set, password recover is enabled. This email
# address will be used in Admin::Mailer.
config.mailer_sender = "noreply#somewhere.com"
# Define paperclip attachment styles.
# config.file_preview = :medium
# config.file_thumbnail = :thumb
# Authentication: +:none+, +:http_basic+
# Run `rails g typus:migration` if you need an advanced authentication system.
config.authentication = :session
# Define user_class_name.
config.user_class_name = "AdminUser"
# Define user_fk.
config.user_fk = "admin_user_id"
# Define master_role.
config.master_role = "admin"
end
config/typus/admin_user.yml
AdminUser:
fields:
default: first_name, last_name, role, email, locale
list: email, role, status
form: first_name, last_name, role, email, password, password_confirmation, locale
options:
selectors: role, locale
booleans:
status: Active, Inactive
filters: status, role
search: first_name, last_name, email
application: Admin
description: Users Administration
test/factories/admin_users.rb:
Factory.define :admin_user do |u|
u.first_name 'Admin'
u.last_name 'User'
u.email 'admin#somewhere.com'
u.role 'admin'
u.password 'password!'
u.token '1A2B3C4D5E6F'
u.status true
u.locale 'en'
end
test/functional/admin/credits_controller_test.rb:
require 'test_helper'
class Admin::CreditsControllerTest < ActionController::TestCase
setup do
#admin_user = Factory(:admin_user)
#request.session[:admin_user_id] = #admin_user.id
#request.env['HTTP_REFERER'] = '/admin/credits/new'
end
context "new" do
should "be successful" do
get :new
assert_response :success
end
end
end
#response.body:
<html>
<body>You are being redirected.
</body>
</html>
As you can see, I've set up the typus to use admin_user and admin_user_id for the session key. But for some reason that test fails getting 302 rather than 200. I'm sure this is because I'm doing something wrong that I just don't see. I've also created all these a gist, just in case someone prefers that.
Edited 2011-05-19 09:58am Central Time: Added Response body text per request.
I figured this out. It was a problem with the config/typus/admin_roles.yml file.
Before:
admin:
Category: create, read, update
Credit: read
...
After:
admin:
Category: create, read, update
Credit: read, create
...
The problem was that admin users didn't have access to the CREATE action on the admin/credits_controller which resulted in the user being sent back to the admin login address.
Giving admin users access to the action and changing the
#session[:admin_user_id]
to
#session[:typus_user_id] #Just like in the Typus docs
solved the problem. I had changed it to :admin_user_id because of the
config.user_fk = "admin_user_id"
in the typus config files, while trying to troubleshoot this issue.

Resources