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 %>
Related
I am using Rails 4.1.1 Why do I have to click twice for jQuery effect to show?
I have been Googling but I cannot find any solutions, not sure if there's something wrong with my jQuery code or....
When I click "Submit" for the first time, the effect didn't appear but the POST action is already called, when I click for the second time, the effect appeared and the POST action is called.
Please check below my create.js.erb, users_controller.rb, new.html.erb
create.js.erb
function isValidEmailAddress(emailAddress) {
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
return pattern.test(emailAddress);
};
$("form").submit(function( event ) {
var email = $("input#user_email").val();
if (email == "") {
$("h1").text( "Email cannot be empty" ).show().fadeOut( 3000 );
return;
} else if (!isValidEmailAddress(email)) {
$("h1").text( "Email address is not valid" ).show().fadeOut( 3000 );
}else {
$("h1").text( "Correct email address" ).show();
}
event.preventDefault();
});
new.html.erb
<%= form_for #user, remote: true do |f| %>
<p>
<%= f.text_field :email %>
</p>
<p>
<%= f.submit :Submit %>
</p>
<% end %>
<h1></h1>
<% #users.each do |user| %>
<tr>
<li><%= user.email %></li>
</tr>
<% end %>
users_controller.rb
class UsersController < ApplicationController
def new
#users = User.all
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
format.html { redirect_to '/' }
format.js
end
#user.save
end
private
def user_params
params.require(:user).permit(:email)
end
end
Turbo links might be causing this issue -try disabling turbo links in your app , that has worked for me In the past when I've had a similar problem
You're getting the process wrong. When you submit a remote form in Rails, the app sends an AJAX request to the create action and then evals the received js code (from your create.js.erb). So first time you click the button, nothing happens.
The js view is not the place to handle validations, you should put that somewhere in your assets/javascripts. The js view is a place for updating the html view of the page with the form (e.g. adding records to the list, showing received errors, reseting the form).
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 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.
OK, I have a page which shows the customer how many Widgets he has. Here's the view (haml):
#available
= "Available widgets: #{#customer.widgets.unused.count()}"
("unused" is a scope in the model showing the available widgets).
When Customer redeems Widgets with a form with ":remote => true", some javascript places a nice DIV on the page with animation and the model is updated by the controller.
Here's the controller:
def redeem
#customer = Customer.find(params[:customer_id])
number = params[:amount].to_i
unless #customer.widgets.unused.empty?
number.times do
#customer = Customer.find(params[:customer_id])
widget = #customer.widgets.unused.first # Grab first unused pass
widget.status = "Redeemed"
widget.save!
end
else
#pay = "true"
# customer.widgets.new
end
# redirect_to #customer
end
And here's the javascript (js.erb):
var number = <%= params[:amount] %>;
<% if #pay.eql? "true" %>
$("#widget-pay").modal('toggle');
<% else %>
while (number > 0) {
var item = $('<div class="widget-show">...</div>');
$('#allwidgets').isotope('insert', item);
number --;
}
<% end %>
My problem is I now want to update the "#available" DIV with the new Widget count. How do I do this?
At worst I could reload the page so the data is pulled from the model again, at best just update the DIV. Neither which I seem to be able to do from the javascript.
You can do something like this:
render :js => "$('#available').append(widget)"
widget.save!