I'm new to rails. I'm trying to create a rails marketplace where sellers can cash out their acquired funds from sales on the site.
I'm confused how to configure my withdrawal form and my orders controller.
When I simply just go to localhost:3000/withdrawal, a Stripe Recipient with just name is created on my Stripe dashboard without even completing the form. My form is nonexistent because everything I've tried for form_for generates an error.
I want the user to input their info and then choose to submit it, not create the recipient when "cash out" (which leads to the withdrawal path) is clicked.
The stripe documentation is helpful, but I'm not sure how to create my form.
Here is my withdrawal action in my orders controller. I'm wondering if I need a new action within withdrawal? But not sure if that's possible?
def withdrawal
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.full_name,
:type => "individual",
:bank_account => token
)
transfer = Stripe::Transfer.create(
:amount => (#funds).floor,
:currency => "usd",
:recipient => #seller.recipient
)
end
And my withdrawal.html.erb. I know I am missing a form tag and submit, but everything I've tried just processes an error. I don't know what form_for to call. I've tried "order" but it results in an error.
<div class="text-center">
<h1>Bank Account Information</h1>
<div class="form-group">
<%= label_tag :name %>
<%= text_field_tag :name, nil, { :name => nil, :'data-stripe' => "name", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :withdrawal_amount %>
<%= text_field_tag :withdrawal_amount, nil, { :name => nil, :'data-stripe' => "amount", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :routing_number %>
<%= text_field_tag :routing_number, nil, { :name => nil, :'data-stripe' => "routingNumber", class: "form-control" } %>
</div>
<div class="form-group">
<%= label_tag :account_number %>
<%= text_field_tag :account_number, nil, { :name => nil, :'data-stripe' => "accountNumber", class: "form-control" } %>
</div>
I'd appreciate any guidance on how to create this "cash out" action. Thanks.
form_for is for model objects. If you're not using a model object, or don't want/need Rails to infer things from the model object, don't use form_for.
For simple forms, instead use one of:
form_tag - Same syntax as form_for but without the model-related magic.
A plain old <FORM> tag. ERB templates are, after all, just HTML with Ruby mixed in.
Your view should look something like the following:
<%= form_tag withdrawl_path, method: :post do %>
<input type="text" name="card[number]" />
<!-- whatever fields you need for form -->
<% end %>
You will be able to access the submitted params via params[:card][:param_name] or use strong params and only permit params you need.
Use custom routes
get "/form" => "controller_name#action_for_form", as: :action_for_form
post "/withdrawl" => "controller_name#withdrawl", as: :withdrawl
Controller:
def action_for_form
# whatever code you need to setup form
#seller = Seller.find(params[:seller_id])
end
def withdrawl
# withdrawl code here
end
private
def card_params
params[:card].permit(:card_token, :other_params)
end
Its worth taking the time to understand the form tag and using Rails outside of the Railsy way of form submissions. It can get messy, but it allows for much more flexibility.
Related
In my RoR application I am allowing users to select contacts that they want to send an email to. The users select these contacts via checkboxes on the form. I am trying to add in search functionality so that a user can search by first name and only check boxes with contacts that match that search appear.
To do this I am trying to use this code on the view:
<div class="form-group">
<label>From Email Address</label></br>
<% #useraccounts.each do |useraccount| %>
<%= f.radio_button :account_id, useraccount.account_id, :checked => false %>
<%= f.label :account_id, useraccount.account.email, :value => "true" %><br>
<% end %>
</div>
<div class="form-group">
<%= form_tag '/emails/contact_search', :method => 'get' do %>
<p>
<%= text_field_tag :search_string, params[:search_string], :placeholder => "Search by firstname" %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<label>Contacts</label></br>
<%= f.collection_check_boxes :contact_ids, #contacts, :id, :fullname %>
</div>
Where the #contacts instance variable holds the contacts returned from the search in the controller.
When a user clicks the search button, the below controller action should be invoked.
def contact_search
#email.recipients.build
#useraccounts = Useraccount.where(user_id: session[:user_id])
#contacts = Contact.contacts_search(params[:search_string])
if #contacts.empty?
flash.now[:alert] = "There are no contacts with that name."
#contacts = Contact.all
end
render :action => "new"
end
This controller action uses the contact_search method, which is in the Contact.rb model:
def self.contact_search(search_string)
self.where("firstname LIKE ?", search_string)
end
I also have the contact_search in the routes:
post 'emails/contact_search', :to => 'emails#contact_search'
get 'emails/contact_search', :to => 'emails#contact_search'
But for some reason, when a user clicks search they get a NoMethodError in Emails#create undefined method 'each' for nil:NilClass on the form. The error is as pictured.
I cannot work out why this isn't working, can someone please help?
By the erb, I guess you have a form_tag inside a form_for block... You can't do that
When you hit Submit, the action is going to the first form action... that probably is a create
It's better move your form_tag to outside your previous form block...
Seems your Modal name (Useraccount) is incorrect this must be UserAccount.
Also Please note
When we use where query with ActiveRecord modal we never get NIL object unless we have wrong Modal name.
I have a form for some model, inside this form I have some text_fields and hidden_fields
that i need to use in the controller but that are not from the model.
this is a simplified version of it
<%= from_for #user do |f| %>
<%= f.text_field :name %>
<%= hidden_field :photo, value: 'blabla' %>
<%= text_field :type %>
<% f.submit %>
Lets say that the :photo and :type parameters are not in the model user but i need them to decide how to create the user.
they are going in the params hash, but all messed up. How do I access their value?
Thank you
hidden_field_tag "photo", "photo_value"
=> <input id="photo" name="photo" type="hidden" value="photo_value" />
Then in your controller:
#hidden_photo = params[:photo]
Whenever you are working with a form and want a value not associated with a model or object, then use the helpers ending in "*_tag"
Simple question for Rails gurus. Why I do have to use the following statement to insert a new Mongoid document : params[:video][:description] in the following create method of my VideosController? Why I can't use the params[:description] from the POST form? If I use it, the value becomes nil.
def create
#video = Video.new(
:title => params[:video][:title],
:description => params[:video][:description]
)
if #video.save
render 'success'
else
render 'error'
end
end
Here is the Video.rb class :
class Video
include Mongoid::Document
field :title, type: String
field :description, type: String
validates_presence_of :title
validates_presence_of :description
acts_as_url :title
end
And finaly the form view :
<%= form_for #video do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<p/>
<%= f.label :description %>
<%= f.text_field :description %>
<%= submit_tag("Enqueue video") %>
<% end %>
I don't quite get why the form input are video[description] and not just description as expected :
<label for="video_title">Title</label>
<input id="video_title" name="video[title]" type="text" />
<p/>
<label for="video_description">Description</label>
<input id="video_description" name="video[description]" type="text" />
When you are using form_for:
Creates a form that allows the user to create or update the attributes
of a specific model object.
In your case, Video model. To understand Rails convention:
<%= form_for #video do |f| %>
...
<%= f.text_field :description %>
...
Which results in an html tag whose name attribute is video[description]. This means that when the form is submitted, the value entered by the user will be available in the controller as params[:video][:description].
The params variable is an instace of ActiveSupport::HashWithIndifferentAccess, like a Hash with a small difference, according to documentation:
This class has dubious semantics and we only have it so that people
can write params[:key] instead of params[‘key’] and they get the same
value for both keys.
Your params is something like:
{"utf8"=>"✓",
"_method"=>"post",
"authenticity_token"=>"xxx",
"video"=>
{"description"=>"Video desc"}
}
Where "video" or :video is one of the keys of the Hash. So, params[:video] is equivalent to params.fetch("video") which value is {"description"=>"Video desc"}. As you can see the value is another Hash. Finally to get the value of the description you have to params[:video][:description] (The Rails way) or params.fetch("video").fetch("description"), which value is "Video desc".
fetch is a Ruby method of Hash: "Returns a value from the hash for the given key."
Taking this into account:
Video.new(params[:video]) = Video.new(:description => "Video desc") = Video.new(:description => params[:video][:description])
It's easier to use conventions, but for sure you can have params[:description] (just in case):
<%= form_for #video do |f| %>
...
<%= text_field_tag :description %>
...
Note that I'm using text_field_tag instead of f.text_field. In this case the html tag name will be description in the params Hash you will receive { "description" => 'Video desc" }...
Take a look to Rails API documentation to understand different helpers, etc. And also review your server's log.
If you want to use video[:description]. Create your form like this
<%= form_for #video do |f| %>
....
<p/>
<%= f.label :description %>
<%= f.text_field :description, :name => "description" %>
....
<% end %>
Rails form_for helper name the input elements such that it becomes easy to push them into model attributes in one go like this
#video = Video.new(params[:video])
so that you don't have to do it like the way you have done
#video = Video.new(
:title => params[:video][:title],
:description => params[:video][:description]
)
I'm having a problem with Rails not POSTing anything in the params to an action.
I'm using a singular resource with a nested plural resource which may or may
not be where the problem is coming from (Rails has issues with form_for and singular
resource URLs).
Anyway, I have this in my routes:
resource :event do
resources :actions, :only => [:create], :controller => "events/actions"
end
The view:
<%= form_for([#event, Action.new], :remote => true) do |f| %>
<div class="field">
<%= f.label :team_id %>
<br />
<%= f.text_field :team_id %>
</div>
<div class="field">
<%= f.label :message %>
<br />
<%= f.text_field :message %>
</div>
<div class="field">
<%= f.label :score %>
<br />
<%= f.number_field :score %>
</div>
<br />
<%= f.submit "Update score" %> or <%= link_to "cancel", "#", :id => "cancel" %>
<% end %>
The create action:
def create
#event = Event.find(params[:event_id])
#action = #event.actions.create(params[:action])
end
Ok pretty standard no worries there.
But when I get the params from Rails nothing is there. :(
Params:
Started POST "/event/actions.4e67f09349ae71090c00000e"
Processing by Events::ActionsController#create as
Parameters: {"utf8"=>"Γ£ô", "authenticity_token"=>"stuff", "commit"=>"Update score"}
Completed 500 Internal Server Error in 31ms
What is going on here?
Edit:
If I remove the ":remote => true" line in my view,
I see that in my params I get one param ":format"
which appears to be the ID of the event.
However, I'm still not getting the action params. :(
Ideally I'd like to see those event & action models - I suspect that's where the problem lies. Without seeing those, a few suggestions:
Is 'accepts_nested_attributes_for :action' set in the event model?
Remove any 'attr_accessible' line from both models & see if things work. (Keep in mind you need to set accessible attributes for nested forms in the parent model)
'Action' seems like an imprudent name for a model. It's possible rails is overwriting 'action' methods with things related to the actual action
Hope this helps - I'd suggest posting the models if you still can't find a solution.
On the front page of my rap lyrics explanation site, there's a place where users can try explaining a challenging line:
alt text http://dl.dropbox.com/u/2792776/screenshots/2010-02-06_1620.png
Here's the partial I use to generate this:
<div class="stand_alone annotation" data-id="<%= annotation.id %>">
<%= song_link(annotation.song, :class => :title) %>
<span class="needs_exegesis"><%= annotation.referent.strip.gsub(/\n/, "\n <br />") %></span>
<% form_for Feedback.new(:annotation_id => annotation.id, :created_by_id => current_user.try(:id), :email_address => current_user.try(:email)), :url => feedback_index_path, :live_validations => true do |f| %>
<%= f.hidden_field :annotation_id %>
<%= f.hidden_field :created_by_id %>
<p style="margin-top: 1em">
<%= f.text_area :body, :rows => 4, :style => 'width:96%', :example_text => "Enter your explanation" %>
</p>
<p>
<% if current_user %>
<%= f.hidden_field :email_address %>
<% else %>
<%= f.text_field :email_address, :example_text => "Your email address" %>
<% end %>
<%= f.submit "Submit", :class => :button, :style => 'margin-left: .1em;' %>
</p>
<% end %>
</div>
However, putting more than one of these on a single page is problematic because Rails automatically gives each form an ID of new_feedback, and each field an ID like feedback_body (leading to name collisions)
Obviously I could add something like :id => '' to the form and all its fields, but this seems a tad repetitive. What's the best way to do this?
If you don't want to change your input names or your model structure, you can use the id option to make your form ID unique and the namespace option to make your input IDs unique:
<%= form_for Feedback.new(...),
id: "annotation_#{annotation.id}_feedback"
namespace: "annotation_#{annotation.id}" do |f| %>
That way our form ID is unique, i.e. annotation_2_feedback and this will also add a prefix, e.g. annotation_2_, to every input created through f.
Did you consider nested_attributes for rails models? Instead of having multiple new feedback forms where each is tied to an annotation, you could have multiple edit annotation forms where each annotation includes fields for a new feedback. The id's of the generated forms would include the annotations id such as edit_annotation_16.
The annotation model would have a relationship to its feedbacks and will also accept nested attributes for them.
class Annotation < ActiveRecord::Base
has_many :feedbacks
accepts_nested_attributes_for :feedbacks
end
class Feedback < ActiveRecord::Base
belongs_to :annotation
end
You could then add as many forms as you want, one for each annotation. For example, this is what I tried:
<% form_for #a do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
<% form_for #b do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
And the quick and dirty controller for the above edit view:
class AnnotationsController < ApplicationController
def edit
#a = Annotation.find(1)
#a.feedbacks.build
#b = Annotation.find(2)
#b.feedbacks.build
end
def update
#annotation = Annotation.find(params[:id])
#annotation.update_attributes(params[:annotation])
#annotation.save!
render :index
end
end
I had this same issue on a site I'm currently working on and went with the solution you mention at the bottom. It's not repetitive if you generate the ID programmatically and put the whole form in a partial. For example, on my site, I have multiple "entries" per page, each of which has two voting forms, one to vote up and one to vote down. The record ID for each entry is appended to the DOM ID of its vote forms to make it unique, like so (just shows the vote up button, the vote down button is similar):
<% form_for [entry, Vote.new], :html => { :id => 'new_up_vote_' + entry.id.to_s } do |f| -%>
<%= f.hidden_field :up_vote, :value => 1, :id => 'vote_up_vote_' + entry.id.to_s %>
<%= image_submit_tag('/images/icon_vote_up.png', :id => 'vote_up_vote_submit' + entry.id.to_s, :class => 'vote-button vote-up-button') %>
<% end -%>
I also had the same issue but wanted a more extensible solution than adding the ID to each field. Since we're already using the form_for ... |f| notation the trick is to change the name of the model and you get a new HTML ID prefix.
Using a variant of this method: http://www.dzone.com/snippets/create-classes-runtime (I removed the &block stuff)
I create a new model that is an exact copy of the model I want a second form for on the same page. Then use that new model to render the new form.
If the first form is using
#address = Address.new
then
create_class('AddressNew', Address)
#address_new = AddressNew.new
Your ID prefix will be 'address_new_' instead of 'address_' for the second form of the same model. When you read the form params you can create an Address model to put the values into.
For those stumbling here, looking for the solution for Rails 3.2 app, look at this question instead:
Rails: Using form_for multiple times (DOM ids)