问题
I have a model Token with three fields user_id,product_id and unique_token.In the controller i instantiate a @token object with user_id and product_id values collected from the form.Then i call save_with_payment function with that object,where within the function i want to generate random string 3 times and save in unique_token field.The problem is self.tokens.create!( unique_token: Digest::SHA1.hexdigest("random string") ) give me no method error undefined method tokens.What am i doing wrong here?To clarify what i want to accomplish,I want to be able to retrieve list of generated unique_tokens associated to that user_id or product_id like User.find(1).tokens or Product.find(1).tokens.The model association is User has_many Tokens Product has_many Tokens.Note: unique_token field is from Token model originally,user_id and product_id are just ref primary keys.Much Thanks!
def create
@token=Token.new(params[:token])
if @token.save_with_payment
redirect_to :controller => "products", :action => "index"
else
redirect_to :action => "new"
end
end
class Token < ActiveRecord::Base
require 'digest/sha1'
def save_with_payment
# if valid?
# customer = Stripe::Charge.create(amount:buck,:currency => "usd",card:stripe_card_token,:description => "Charge for bucks")
#self.stripe_customer_token = customer.id
3.times do
self.tokens.create!(unique_token: Digest::SHA1.hexdigest("random string"))
end
save!
end
end
回答1:
There is no tokens method on the Token class. Since you're creating three tokens you don't need the @token instance. Just have save_with_payment be a class method:
def create
if Token.save_with_payment(params[:token])
redirect_to :controller => "products", :action => "index"
else
redirect_to :action => "new"
end
end
class Token < ActiveRecord::Base
require 'digest/sha1'
def self.save_with_payment(attributes)
attributes.merge!(unique_token: Digest::SHA1.hexdigest("foo"))
3.times do
self.create!(attributes)
end
end
end
Hope this helps.
You might want to wrap the loop in a begin/rescue, too. Otherwise if the 2nd or 3 create! fails you end up with tokens AND redirecting to "new".
Response to 1st comment: That won't work if you use a class method. You can't call valid? because you're not in the context of an instance of Token. I don't recommend sticking with an instance method. If you do change it to a class method you'll want to wrap it in a transaction block:
def self.save_with_payment(attributes)
transaction do
attributes.merge!(unique_token: Digest::SHA1.hexdigest("foo"))
3.times do
self.create!(attributes)
end
rescue
false
end
end
That should roll back the SQL transactions if any of the create! calls fail and return false to the controller create action.
I'd pull that customer code out of Token (Token shouldn't care about creating/retrieving a customer) and put it in the controller action. Pass the pertinent information into save_with_payments. Like:
self.save_with_payments(customer, attributes)
...
end
来源:https://stackoverflow.com/questions/9040827/no-method-error-when-trying-to-call-a-function-with-an-instantiated-object