i'm having a kinda weird & annoying bug with Rails. I have a HAML form, a model, and a method for handling it:
View
%form{ :action => "/new", :method => "post", :style=>"margin-top: 6px"}
%input{:type=>"hidden", :name=>"authenticity_token", :value=>form_authenticity_token.to_s}
%input{:type => "text", :name => "blogName", :placeholder=>"Blog name"}
%input{:type => "text", :name => "blogSubdomain", :placeholder=>"Blog URL"}
%input{:type => "text", :name => "username", :placeholder=>"username"}
%input{:type => "text", :name => "email", :placeholder=>"email"}
%input{:type => "password", :name => "password", :placeholder=>"password"}
%br/
%input{:type => "submit", :value => "Send", :class => "btn btn-primary"}
- unless session[:error].nil?
%div{:class=>"alert alert-error", :style=>"font-size:13px; font-weight:normal;"}
%strong Please correct the following errors
%br
- session[:error].each do |value|
- unless value.nil?
%li= "#{value}"
- session[:error]=nil
Model:
class User
include MongoMapper::Document
key :screen_name, String, :required => true, :unique => true
key :blog_name, String, :required => true, :unique => true
key :blog_subdomain, String, :required => true, :unique => true
key :email, String, :required => true, :unique => true, :format => /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i
key :password, String, :required => true
key :admin, Boolean
timestamps!
validate :finalValidate
before_save :stripSpaces, :hashPassword
def stripSpaces
self.blog_subdomain = self.blog_subdomain.gsub(/[\ _]/, "-")
end
def finalValidate
if blog_subdomain.length > 10
errors.add(:blog_subdomain, "Your chosen subdomain is too long, the maximum is 9 characters")
end
case blog_subdomain
when "www"
when "api"
errors.add(:blog_subdomain," - Sorry but that subdomain is reserved!")
end
end
def hashPassword
self.password = Digest::SHA512.hexdigest(self.password)
end
end
And the method to do it
def new_post
if session[:r]
redirect_to root_path, :subdomain => nil
else
user = User.new({
:screen_name=>params[:username],
:blog_name => params[:blogName],
:blog_subdomain => params[:blogSubdomain],
:email => params[:email],
:password => params[:password],
:admin => false
})
if user.save
session[:screen_name] = user.screen_name
session[:blog_subdomain] = user.blog_subdomain
session[:blog_name] = user.blog_name
session[:twitter_user] = "nothin"
session[:r] = true
flash[:success] = "Blog created!"
redirect_to root_path, :subdomain => user.blog_subdomain
else
errors = Array.new()
for i in 0..user.errors.full_messages.count
errors.push(user.errors.full_messages[i])
end
session[:error] = errors
flash[:error] = "Error creating blog"
redirect_to '/new'
end
end
end
The method fails on if user.save, going straight to the else statement. I'm getting errors when passing the email and password. MongoMapper returns:
Email can't be blank
Email has already been taken
Email is invalid
Password can't be blank
If I remove the validations then the values are just nil. I double checked all, but I couldn't get what's wrong. On the log I see how the params are being sent:
Started POST "/new" for 127.0.0.1 at 2012-03-10 20:46:56 +0100
Processing by ActionsController#new_post as HTML
Parameters: {"authenticity_token"=>"T7J8DDaWWd25LBP6dRgbvpAs4bkC/zLk3GiQ5rVLmiw=", "blogName"=>"wut", "blogSubdomain"=>"WUT", "username"=>"someuser", "email"=>"some#validmail.net", "password"=>"[FILTERED]"}
Redirected to http://myapp.dev/new
Completed 302 Found in 745ms
What I'm doing wrong?
EDIT: Put a logger on the model, and bot mail and password classes are NilClass
Shouldn't be there rather
user = User.new(
:screen_name=>params[:username],
:blog_name => params[:blogName],
:blog_subdomain => params[:blogSubdomain],
:email => params[:email],
:password => params[:password],
:admin => false
)
?
The problem was attr_accessible. I didn't added the email and password fields to it, and it was returning nil because of that
Related
I am new to ruby, rails and rspec. I want to verify that card numbers have been truncated after they have been saved.
Here is my test code:
RSpec.describe Payment, type: :model do
context 'after saving' do # (almost) plain English
it 'card number is truncated' do #
#payment = Payment.new(
:card_number => "5520000000000000",
:card_name => "Tom Jones",
:card_security_code => "123",
:card_expiry => "10/30",
:email => "test#mail.com",
:address_line1 => "400 Test Lane",
:state => "WA",
:postcode => "6000",
:country => "Australia",
:status => "processing"
).save(validate: false)
expect(#payment.card_number).to eq('0000')
end
end
end
Which gives me the error:
undefined method `card_number' for true:TrueClass
Any idea what I'm doing wrong here?
You're assigning the result of #save to #payment:
#payment = Payment.new(...).save(validate: false)
So do it in two steps:
#payment = Payment.new(
:card_number => "5520000000000000",
:card_name => "Tom Jones",
:card_security_code => "123",
:card_expiry => "10/30",
:email => "test#mail.com",
:address_line1 => "400 Test Lane",
:state => "WA",
:postcode => "6000",
:country => "Australia",
:status => "processing"
)
#payment.save(validate: false)
I tried ccavenue but I'am getting this error. paypal is working fine.
undefined methodpayment_service_for'`
This is my controller action
def create
#subscription = Subscription.new(subscription_params)
#programme = Programme.find(subscription_params[:programme_id])
rand_number = rand.to_s[2..11]
#programme.update_attributes(:invoice_id => rand_number)
session[:programme_id]=#programme.id
session[:invoice_id]=#programme.invoice_id
#paypal = PaypalPayment.create(:material_type => 'Programmes',:invoice_id => rand_number,:currency => #programme.currency, :status => 'Processing', :created_at => DateTime.now, :user_id => current_user.specific.id, :email_id => current_user.specific.email, :programme_id => #programme.id,:amount => #programme.price_paisas)
#paypal.save
`session[:paypal_id]=#paypal.id
logger.info #programme.inspect
if subscription_params[:payment_type] == 'paypal'
item_details=[]
if #programme.currency == 'INR'
price = #programme.price.exchange_to('USD')
else
price = #programme.price
end
logger.info price.inspect
item_details << {:name => #programme.title, :quantity => '1', :amount => price.fractional}
response = EXPRESS_GATEWAY.setup_purchase(price.fractional,
:items => item_details,
:currency => "USD",
:order_id => #programme.invoice_id,
:return_url => students_success_url,
:cancel_return_url => students_root_url
)
logger.info response.inspect
session[:programme_price]=price
return redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
elsif subscription_params[:payment_type] == 'ccavenue'
payment_service_for #programme.invoice_id, CCAVENUE_ACCOUNT,
:amount => #programme.price.fractional,
:currency => 'INR',
:service => :ccavenue do |service|
service.customer :name => current_user.name,
:email => current_user.email,
:phone => current_user.mobile
service.redirect :return_url => students_success_url
submit_tag 'Proceed to payment'
end
end
end
end`
I referred this link:
https://github.com/meshbrain/active_merchant_ccavenue
The payment_service_for is the view helper of the Active Merchant gem. You should use this method inside views or you should include view helpers inside your controller.
Using OmniAuth, I successfully fetched the hash data from Facebook: stored in "auth"
# extra=#] last_name="Jordan" link="http://www.facebook.com/michael" locale="en_US" middle_name="Ball" name="Michael Jordan" quotes="\"lalala\"\n\n\"lala\"" timezone=9 updated_time="2011-09-01T20:25:58+0000" username="mjordan82" verified=true>> info=# verified=true> provider="facebook" uid="123456879">
In User Model, I do as follows:
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth["provider"]
user.uid = auth["uid"]
user.name = auth["name"]
end
end
When I checked the database, I only got provider and uid. User.name row was empty. From testing, I figured out I couldn't store other data than provider and uid. For example, user.name = auth["provider"] or user.name = auth["uid"] stored with no problem, but when I tried something like user.name = auth["timezone"] or user.name = auth["last_name"], nothing was stored in the variable. Anyone know how to fix this? I also tried user.name = auth["user_info"]["name"], but it returned an error.
I am not sure why user.name = auth["name"] does not store anything. In other words, why is auth["name"] not "Michael Jordan" in this case?
The key was this: I was accessing the auth hash in a wrong way. The answer is you do
user.name = auth["info"]["name"]
Here's detailed information about the Auth Hash:
:provider => 'facebook',
:uid => '1234567',
:info => {
:nickname => 'jbloggs',
:email => 'joe#bloggs.com',
:name => 'Joe Bloggs',
:first_name => 'Joe',
:last_name => 'Bloggs',
:image => 'http://graph.facebook.com/1234567/picture?type=square',
:urls => { :Facebook => 'http://www.facebook.com/jbloggs' },
:location => 'Palo Alto, California',
:verified => true
},
:credentials => {
:token => 'ABCDEF...', # OAuth 2.0 access_token, which you may wish to store
:expires_at => 1321747205, # when the access token expires (it always will)
:expires => true # this will always be true
},
:extra => {
:raw_info => {
:id => '1234567',
:name => 'Joe Bloggs',
:first_name => 'Joe',
:last_name => 'Bloggs',
:link => 'http://www.facebook.com/jbloggs',
:username => 'jbloggs',
:location => { :id => '123456789', :name => 'Palo Alto, California' },
:gender => 'male',
:email => 'joe#bloggs.com',
:timezone => -8,
:locale => 'en_US',
:verified => true,
:updated_time => '2011-11-11T06:21:03+0000'
}
source: https://github.com/mkdynamic/omniauth-facebook
This is why I could access "provider" and "uid" with simply auth["provider"], and I needed to do
auth["info"]["name"]
to access the name information. Similarly, to get the user's timezone, you could do
auth["extra"]["timezone"]
This is my controller:
class ReportNeedsController < ApplicationController
def index
#report_needs = nil
end
def new
#report_need = ReportNeed.new
end
def create
#report_need = ReportNeed.new(params[:report_need])
#report_need.save
redirect_to #report_need
end
end
This is my new.haml file:
Why do you want to report?
%form
%input{:name => "option", :type => "radio", :value => "spam"}
spam
%br/
enter code here
%input{:name => "option", :type => "radio", :value => "product_corrupted"}
product_corrupted
%br/
%input{:name => "option", :type => "radio", :value => "product_spoiled"}
product_spoiled
Make changes in view like :
%input{:type => "radio", :name => "report_need[product_type]", :id => "report_need[product_type]-1", :value => "salesforce", :checked => true}
%br/
%input{:type => "radio", :name => "report_need[product_type]", :id => "report_need[product_type]-2", :value => "salesforce", }
In controller, If product_type is field of table report_needs then no need to change in your action . else its change and store it like :
def create
report_need = ReportNeed.new(params[:report_need])
report_need.radio_field_name = params[:report_need][product_type]
report_need.save
redirect_to report_need
end
And as a result its not passing validation.
This is my embedded form :
- form_for [#organization, #referral] do |f|
= f.error_messages
= render :partial => 'referral_fields', :locals => { :f => f }
= f.submit "Submit", :class => "button"
#_referral_fields.html.haml
.grid_7
.grid_1{:style => "width: 64px;"}
= f.label :org_name, "Business", :class => "right"
.grid_4
= f.text_field_tag :org_name
.grid_7
.grid_1{:style => "width: 64px;"}
= f.label :name, '', :class => "right"
.grid_4
= f.text_field_tag :name
.grid_7
.grid_1{:style => "width: 64px;"}
= f.label :email, '', :class => "right"
.grid_2.omega{:style => "width: 114px;"}
= f.text_field_tag :email, '', :style => "width: 125px;"
.grid_1.alpha
= f.label :town, '', :class => "right"
.grid_2
= f.text_field_tag :town, '', :style => "width: 100px;"
And when I click submit, SQL definately reads the data I inputted :
Processing ReferralsController#create (for ::1 at 2010-10-18 09:39:07) [POST]
Parameters: {"name"=>"asdfasd", "commit"=>"Submit", "action"=>"create", "authenticity_token"=>"/1bwOqHjojde3p0Py08mCrko8xULE4R+eXUvT6qf1cE=", "controller"=>"referrals", "org_name"=>"asdfasdf", "organization_id"=>"1", "town"=>"asdfasd", "email"=>"asdfasd"}
Not sure what I'm missing. Here is controllers and models :
#referral.rb
belongs_to :organization, :touch => true
validates_presence_of :org_name, :name, :email, :town
#referrals_controller.rb
def new
#referral = Referral.new
respond_to do |format|
format.html { render :layout => 'manage' }
end
end
def create
#referral = Referral.new(params[:referral])
if #referral.valid? && #organization.referrals << #referral
flash[:notice] = "Referrals saved."
redirect_to new_organization_referrals_path(#organization)
else
render :action => :new, :layout => 'manage'
end
end
From looking at the parameters, it doesn't look like you have your form fields setup properly?
You are using the params[:referral] hash to build the referral, but I don't see a :referral hash in your parameter list....
Your form fields should look like this:
<input name="referral[name]"/>
<input name="referral[town]"/>
<input name="referral[org_name]"/>
etc...
And then in your parameter list you should be something like { :referral => {:name => "foo", "org_name" => "bar", town => "Boise" } }