I am developing an e-commerce site.. and now I got stuck at one point.. When I submit the form ,it doesn't submits on the first click, and i need to give a second click to get it working... I have used anchor tag to submit my data bcoz I want to show the data inside thickbox(iframe)...
View file
<%= form_for :order, :url => populate_orders_url ,:html => { :class => "data# product.id}"},:method => "post",:remote => true do |f| %>
// data
//submit button
orders controller.rb
def populate
#order = current_order(true)
params[:products].each do |product_id,variant_id|
quantity = params[:quantity].to_i if !params[:quantity].is_a?(Hash)
quantity = params[:quantity][variant_id].to_i if params[:quantity].is_a?(Hash)
#order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0
end if params[:products]
params[:variants].each do |variant_id, quantity|
quantity = quantity.to_i
#order.add_variant(Variant.find(variant_id), quantity, ad_hoc_option_value_ids, product_customizations) if quantity > 0
end if params[:variants]
fire_event('spree.cart.add')
fire_event('spree.order.contents_changed')
redirect_to cart
end
I have seen in firebug and populate method is processed but it not sending data into cart and it showing me empty cart..and cart is processing...
You are sending ajax request,remove :remote => true option from form and check.
Related
I have Facebook authentication working perfectly, however I have two different account types: basic-user and member. So I have two buttons where the user will choose basic or member and switch to the appropriate form.
Question:
What I want to figure out is how my facebook button could determine whether this is a member or basic. What could I add to the member portion of the login?
1st idea -My idea is making a hidden field with the Facebook link_to omniauth facebook call and the submit button for the the hidden field which will give user_type. to the user created.
One problem with this ^ is that the form submit with the hidden_field: user_type will go first before the facebook omniauth gets called. The registration path requires a password, so im not sure if this will work.
2nd idea - can i store information in the facebook button? could I put a second controller action for the button so that after facebook creates my user then the second action will take place which is the verification of the member.
or could i put a value in the facebook button to be passed to the same controller??
Heres what I have so far!
def self.from_omniauth(auth)
anonymous_username = "NewUser#{User.last.id + 1}"
generated_password = Devise.friendly_token[0,20]
user = User.where(:email => auth.info.email, :username => anonymous_username).first
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.confirmed_at = Time.now
user.fullname = auth.info.name
user.provider = auth.provider
user.uid = auth.uid
user.username = anonymous_username
user.email = auth.info.email
user.password = generated_password
if auth.info.image.present?
avatar_url = process_uri(auth.info.image)
user.avatar = URI.parse(avatar_url)
end
end
end
end
Omniauth Callback_controller:
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Facebook button + 1st idea hidden_field:
<%= form_for(#user, :url=> '/user/action', :method=> 'update', :html => {:id=>'facebook-form'} ) do |f| %>
<%= link_to "Sign Up With Facebook", user_omniauth_authorize_path(:facebook), :onclick => "$('#facebook-form').submit()", class:"btn btn-primary2" %>
<% end %>
I've update method inside my controller:
def update
if #daily_order.update(daily_order_params.merge({default_order:false}))
respond_to :js
else
render :edit
end
end
I've pax as one of the params inside the daily_order_params and what I'm trying to do now is, I want to show a JS alert when user is trying to update a daily order with zero (0) pax value.
I try to use byebug inside that update method to check params[:pax] but it returns nothing. It's blank.
But the newly updated pax value was saved successfully inside the database.
I try to use before_update inside my model, but I didn't know how to move forward.
before_update :reject_zero_pax_order_update
def reject_zero_pax_order_update
# i got stucked here
end
update.js.erb
console.log("record updated");
What should I do to:
Reject the update if the entered pax is 0
Trigger a JS alert box if the entered pax is 0
Maintain the old pax inside the database
The :pax attribute is inside the :daily_order hash not inside the params hash.
Your params looks something like this:
{ daily_order: { pax: 0 }}
hence you should access it with params[:daily_order][:pax]
Your action should look something like this :
unless params[:daily_order][:pax] == 0
#daily_order.update(daily_params.merge{default_order: false} )
respond_to :js
else
render :edit
end
#update.js.erb
alert('hey, the pax cant be 0 ');
I am assuming, you want the update to take place only when the pax is present else show the alert.
For displaying alert box for pax value can't be equal to 0, you need to add id or class on both update button and pax field. Also you have to add hidden field for getting id of current daily order which is to be updated.
# Add hidden field:
<%= hidden_field_tag "daily_order_id", #daily_order.id %>
# Add id on pax field:
<%= f.text_field :pax, id: 'daily_order_pax' %>
# Add id on update button:
<%= f.submit 'Update', id: 'update_daily_order' %>
Then add following code in js file:-
$(document).on('click', '#update_daily_order', function(event) {
event.preventdefault();
var id = $('#daily_order_id').val();
var pax_value = $('#daily_order_pax').val();
if (pax_value == 0) {
alert("pax value can't be equal to 0");
}else {
$.ajax({
type: 'PUT',
url: '/daily_orders/' + id
data: $('#form_id').serialize();
});
}
});
Above ajax will call only when pax value is not equal to 0
I'm trying to build a RoR app, with three models:
Games that can be classified in a Sector(called GameSector) and in a subsector (called GameSubsector)
A sector is made up of many subsectors.
a Subsector.
Here are my basic models relationships:
models/game.rb
belongs_to :game_sector, :foreign_key => 'game_sector_id', :counter_cache => true
belongs_to :game_subsector, :foreign_key => 'game_subsector_id',:counter_cache => true
I use Active Admin to input the Games, Sectors or subsectors information.
I have a very basic form when I create a game and I'd just like to make the second select drop down (game_subsector) adjust on the choice of the first select (gamesector) so that I don't the the whole (very long) list of game_subsectors but only those that belong to the game_sector I choose.
After dozens of tests and techniques tried but failing, I've finally used this dev's advice that appeared relevant to me: http://samuelmullen.com/2011/02/dynamic-dropdowns-with-rails-jquery-and-ajax/.
But it still does not work.
Here is the form on Active Admin which is located on admin/game.rb
ActiveAdmin.register Game do
menu :parent => "Campaigns", :priority => 1
controller do
with_role :admin_user
def game_subsectors_by_game_sector
if params[:id].present?
#game_subsectors = GameSector.find(params[:id]).game_subsectors
else
#game_subsectors = []
end
respond_to do |format|
format.js
end
end
end
form do |f|
f.inputs "Details" do
f.input :name
f.input :game_sector_id,
:label => "Select industry:",
:as => :select, :collection => GameSector.all(:order => :name),
:input_html => { :rel => "/game_sectors/game_subsectors_by_game_sector" }
f.input :game_subsector_id, :as => :select, :collection => GameSubsector.all(:order => :name)
f.actions
end
I feel the javascript is even maybe not fired.
The jquery I use is located on app/assets/javascript/admin/active_admin.js (I changed config so it loads this javascript when loading active admin pages)
jQuery.ajaxSetup({
'beforeSend': function(xhr) { xhr.setRequestHeader("Accept", "text/javascript"); }
});
$.fn.subSelectWithAjax = function() {
var that = this;
this.change(function() {
$.post(that.attr('rel'), {id: that.val()}, null, "script");
});
};
$("#game_game_sector_id").subSelectWithAjax(); //it it found in my view???
Finally I created a view as this expert adviced: in app/views/layout/ game_subsectors_by_game_sector.js.erb
$("#game_game_subsector_id").html('<%= options_for_select(#game_subsectors.map {|sc| [sc.name, sc.id]}).gsub(/n/, '') %>');
I'm not sure I have out it in the right place though...
What you need is:
Inspect with your web browser console your selects, and use a CSS selector to create a jQuery object for the sector select, something like:
$('#sector_select')
Append to this object a handler, so when it changes AJAX request is fired:
$('#sector_select').change(function(){
$.ajax('/subsectors/for_select', {sector_id: $(this).val()})
.done(function(response){ // 3. populate subsector select
$('#subsector_select').html(response);
});
});
See 3 in code, you need to inspect to get the right CSS selector. Be sure you are getting the expected response in the Network tab of your web browser inspector(if using Chrome).
You need a controller that answers in /subsectors/for_select, in the file app/controllers/subsectors_controller.rb:
class SubsectorsController < ApplicationController
def for_select
#subsectors = Subsector.where sector_id: params[:sector_id]
end
end
You need a view that returns the options to be populated app/views/subsectors/for_select.html.erb:
<% #subsectors.each do |ss| %>
<option value="<%= ss.id %>"><%= ss.name %></option>
<% end %>
You need a route:
get '/subsectors/for_select', to: 'subsectors#for_select'
I want to provide users a 'random' option so they can select a previous created date idea to use from the database (inside the letsgos table). There’s a “Let’s Go...” section that users can fill out a form and propose a date they would like to go on. There are going to be users who won’t be able to come up with a date idea on their own. So for those users who cannot create their own date I want to provide a ‘random’ button that with each click will insert a date (that’s from the database) into the form. The dates in the database from the letsgos table have content and tag assign to them. When a user clicks on random it should populate the form with the content and tag (each random click should show new data from the database). I don't have any javascript experience so I am not sure if I am doing it the right way.
/views/letsgos/_form.html.erb:
<%= form_for(#letsgo) do |f| %>
<div class="field">
<%= f.text_area :content, placeholder: "Propose new date..." %>
</div>
<%= f.select :tag, options_for_select( [["Select One", ""], "Eat/Drink", "Listen/Watch", "Play", "Explore", "Other"]) %>
Click here for a Random letsgo
<%= f.submit "Post" %>
<% end %>
/views/layouts/application.html.erb
<head>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
$(document).ready(function() {
$('.ajax').click(function() {
$.get(this.href, function(response) {
console.log(response);
$('body').html(response);
});
});
});
<script>
</head>
letsgo controller:
def create
#letsgo = current_user.letsgos.build(letsgo_params)
if #letsgo.save
flash[:success] = "Date posted!"
redirect_to root_url
else
flash[:error] = "Date was not posted!"
redirect_to root_url
end
end
def destroy
#letsgo.destroy
redirect_to root_url
end
def random
#letsgo = Letsgo.random.first
if request.xhr?
end
end
private
def letsgo_params
params.require(:letsgo).permit(:content, :tag)
end
def correct_user
#letsgo = current_user.letsgos.find_by(id: params[:id])
redirect_to root_url if #letsgo.nil?
end
Caching columns migration:
rails g migration add_ids_count
def self.up
add_column :letsgos, :ids_count, :integer, :default => 0
Letsgo.reset_column_information
Letsgo.all.each do |l|
l.update_attribute :id_count, l.id.length
end
end
def self.down
remove_column :letsgos, :id_count
end
end
A creative solution to this would be to set up a caching column to store an array of IDs of Letsgo's, if you're worried about the performance on Antarr Byrd's suggestion. Basically, this would cache the Letsgo.pluck(:id) in a single column in the DB. (Maybe do this in a worker in a post-save and/or post-delete hook on Letsgos.) I'd recommend doing this in a buffer of some sort, or maybe as an hourly task.
You could then either pull this in as a JavaScript array (letsgos_ids_array in the example) and create a Math.random() value based on the length of that array and send it to the .find(). Of course you could also just output the array's length directly.
var item_index = Math.floor(Math.random() * letsgos_ids_array_length);
$.get("/letsgos/random", {
"ind" : item_index
}, function(data){
/* do something with the data */
});
Then, this index can be used to pull out the actual ID value from the array from the db.
letsgoarray = Letsgosarray.first # this is the single-column "cached" array of IDs
item_id = letsgosarray[params[:id_index]]
#random_letsgo = Letsgos.find(item_id)
format.json do {
render json: #random_letsgo
}
Array access is fast, and so is single db column querying.
Here you have some good read about random rows:
http://jan.kneschke.de/projects/mysql/order-by-rand/
I've never done this but you can probably do
def random
Letsgos.find(Letsgo.pluck(:id).sample)
end
I have a Rails application that in the erb code, I use a select box. What I would like to do is reload the page passing the sort parameter. My controller already handles it, but I don't know how to reload the page with the selected value from my select box. Here is my code:
<% #options = {:latest => 'lastest' , :alphabetical => 'alphabetical', :pricelow => 'price-low', :pricehigh =>'pricehigh'} %>
<%= select_tag 'sort[]', options_for_select(#options), :include_blank => true,:onchange => "location.reload('location?sort='+this.value)"%>
Have you considered using an ajax call on your list box? If you have a method on your controller that returns just the sorted list, based on sort parameter, then you could do:
<% #options = {:latest => 'lastest' , :alphabetical => 'alphabetical', :pricelow => 'price-low', :pricehigh =>'pricehigh'} %>
<%= select_tag 'sort[]', options_for_select(#options), :include_blank => true,:onchange => remote_function(:url => {:controller => 'your_controller', :action => 'list_sort_method'}, :with => "'sort='+this.value", :update => "div_containing_list") %>
If you don't want to use AJAX, then put a form_tag around your code.
Take a look at the Redmine source code on http://redmine.rubyforge.org/svn/trunk. The UsersController does something similar - there's a combo box that allows a filter. Selecting the combo reloads the page.