Question about a/bingo basics (a/b testing) - ruby-on-rails

from:
http://www.bingocardcreator.com/abingo/usage
#A view example with a block passed to ab_test:
<% ab_test("call_to_action", %w{button1.jpg button2.jpg}) do |button| >
<%= image_tag(button, :alt => "Call to action!" %>
<% end %>
Does whatever "choice" that gets passed in the block have to be some sort of link? How does a/bingo know when different choices have been converted?

The way Abingo works is to issue different options to different "identities" in a consistent manner so that the results can later be aggregated together again. There are several ways to do this, such as by IP address, by session_id, or by registered account, all of which are valid and can be used in conjunction. In effect, a particular identity will always get the same random selection of options.
An example from the documentation on assigning the identity is as a handler in ApplicationController:
before_filter :set_abingo_identity
def set_abingo_identity
if #user
# Assign identity based on user
Abingo.identity = #user.abingo_identity
else
# Assign identity for anonymous user
session[:abingo_identity] ||= rand(10 ** 10).to_i.to_s
Abingo.identity = session[:abingo_identity]
end
end
When you want to track action based on which A/B option was used, you need to inject calls in your controllers. Another example:
def show
# Track conversion for active Abingo identity
bingo!("show_info_page")
end
The mechanism by which the user navigates to that particular page is entirely arbitrary and can be by link, by form submission, by JavaScript redirect, or by clicking on an email. The only thing that matters is that the display of the A/B option and the later controller action that tracks the activity both have the same Abingo identity assigned.

Related

wrong number of arguments (given 0, expected 1) passing parameter into helper

module ProfilesHelper
def accept (invites)
invite=invites.find(id: '1')
invite.accept= '1'
invite.save
end
end
The user needs to click a button to accept or deny an invitation they have received. I created this helper method, it's suppose to find the user's invite and then set it's accept boolean to 1. But I get "wrong number of arguments (given 0, expected 1)"
Views:
<% #invites.each do |invite| %>
<%= link_to "Accept", accept(invite) %>
<% end %>
How do I pass the invite object into the accept helper?
I think you're misunderstanding the purpose of helpers. With the way you're using this code, the invite will be accepted when the page is viewed, not when the link is clicked.
Helpers are there to help you lay out the page. Either by abstracting logic away from the view, decorating things, formatting numbers into currency, or a million other things. They are not for handling requests.
You shouldn't be using standard GET requests (an anchor tag) to make changes to your data set. They should come via PUT, PATCH, POST, DELETE requests.
What you need here is to either use a button element, or change your link to submit the request using a PUT or PATCH verb. Then, using a suitable route to receive the request to accept the invite, add an action to your controller to handle this request.
Then in your controller you can do something like this:
def accept_invite
#invite = Invite.find(params[:id])
#invite.accept!
end
Which allows you to move the business logic of handling that acceptance into the model:
class Invite
def accept!
accept = true
save
# You might want to do other things here, like email them a confirmation etc.
end
end
This way, your controller can worry about just handling the request, and the model can worry about how to handle actually accepting an invite.

I'm having trouble viewing other users in my app

In the users controller for my app I have a method for viewing the posts generated by users, but when you go to the index page and click on another user, the page of the currently logged in user shows up but the url is for the user I just clicked onto.
This is the method in my users controller
def feed
#title = "Feed"
#user = User.find(session[:user_id]) # This is the problem
feed = Feed.new(#user)
render 'show_feed'
end
I'm also having trouble understanding the difference between session[:user_id] and params[:id]. If I change session[:user_id] to params[:id] while on the page, of the user I just clicked onto, their posts are then shown, but when I go back to the logged in user's page I get the error "Couldn't find User with 'id'=user_id" in "app/controllers/users_controller.rb:59:in `feed'" So my question is, what do I need to pass into #user = User.find() to get the correctly generated page/s?
Generally if you're clickiing on a link to see some OTHER user, the link has an "id" embedded in it which is passed in the params, so you would do...
#user = User.find(params[:id])
Your link to go back to the logged in user is incorrect, but you haven't shown that link. It should most probably be something like
<%= link_to user_path(session[:user_id]) %>
From the description of your problem you may be doing...
<%= link_to user_path('user_id') %>
... which doesn't make sense... it means literally go to the user record with the id of "user_id"
session is data (usually stored in a cookie) that is persistent from one request to another and that expires at the end of the browser session. A common use is to store the id of the logged in user.
By passing that to User.find you're entirely ignoring the user id that is in the URL. You should be using params[:id] (unless your routes are naming that segment of your url differently)
Your problem when you "go back" is not clear to me (I can't even tell if we're talking about the same controller action) but at a guess either that page doesn't have an id in the URL, or the routing is calling it something else, or (and this is a little messy) you intend to fall back to the current user when there is no id in the URL in which case you need to be using either params[:id] or session[:user_id] depending on what's there.

Devise. Registration and Login at the same page

I'm trying to integrate Devise into my application. I need implement login form at top of the page (I've implemented this form into layout page) and I've implemented registration which contains registration form.
But it shows validation errors for both form when I tried submit incorrect registration data.
Without more information, it's hard to guess what the problem is. I've found the Wiki pages to be really helpful (and increasingly so), though you may have already looked them over:
Devise Wiki Pages
Two pages that might be relevant to your needs:
Display a custom sign_in form anywhere in your app
Create custom layouts
Hope this helps!
-- ff
The problem of seeing the validation errors for both forms stems from the 2 things. First, devise forms use a generic 'resource' helper. This creates a User object, and that same user objet gets used for both the sign up and the sign in form. Second, devise errors are typically displayed using the 'devise_error_messages!' helper which uses that same shared resource.
To have sign in and sign up on the same page you need to create different user objects for each form, and a new way of displaying the error messages.
First off, you'll need to create your own registration controller (in app/controllers/users/)
class Users::RegistrationsController < Devise::RegistrationsController
include DevisePermittedParameters
protected
def build_resource(hash=nil)
super
# Create an instance var to use just for the sign up form
#sign_up_user = self.resource
end
end
And update your routes file accordingly
devise_for :users, controllers: {
registrations: 'users/registrations'
}
Next you'll need your own error messages and resource helpers. Create a new helper like devise_single_page_helper.rb and add the following:
module DeviseSinglePageHelper
def devise_error_messages_for_same_page(given_resource)
return "" if given_resource.errors.empty?
messages = given_resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t("errors.messages.not_saved",
count: given_resource.errors.count,
resource: given_resource.class.model_name.human.downcase)
html = <<-HTML
<div id="error_explanation">
<h2>#{sentence}</h2>
<ul>#{messages}</ul>
</div>
HTML
html.html_safe
end
def sign_up_user
#sign_up_user ||= User.new(username: 'su')
end
def sign_in_user
#sign_in_user ||= User.new(username: 'si')
end
end
Finally, in your views, update your forms like so:
-# The sign up form
= simple_form_for(sign_up_user, url: registration_path(resource_name)) do |f|
-#...
= devise_error_messages_for_same_page(sign_up_user)
-# The sign in form
= simple_form_for(sign_in_user, url: sessions_path(resource_name)) do |f|
#...
= devise_error_messages_for_same_page(sign_in_user)
All of this together gives you 2 different objects - 1 for sign up and 1 for sign in. This will prevent the error messages from one showing in the other. Please note that recommend putting both forms on your sign in page (and perhaps having the default sign up page redirect to the sign in page) because by default a failed sign in attempt will redirect to the sign in page.
You should have two forms on the page — one for signing up and one for registering. If you want a single form and multiple potential actions you are going to need a couple buttons that get handled client side and change the form's action & method to the appropriate route depending you want to create a user or a session.
If you think you did this already, the problem almost certainly lies in your code. If you were to share it with us we could perhaps point out something you may have missed.

I want to pass the name of a calling web page in a form in Ruby on Rails

I am quite new to Ruby. I have a landing page controller and index page that has a button on it that pops up a user input form for email addresses, etc. One of the things I want to capture and write into the database is the name of the originating landing page.
For example:
www,mydomain.com/landngpage/campaign1
Another landing page could be:
www,mydomain.com/landngpage/campaign2
The above form calls a ppc_user controller
www,mydomain.com/lppc_user/new
Can anyone help me on this? I have seen a few examples of passing data using the flash option, but I can't get this to work.
I guess you're looking for request.referer.
It tells you from which page the user comes from.
You could use a hidden field and in fill it with an instance variable created in the controller...
so in your controller index:
def index
#campaign = params[:campaign] # this is whatever parameter you have named that is "campaign1", "campaign2", etc..
end
then in your form:
hidden_field :campaign, #campaign
or with the answer given by apneadiving:
hidden_field :campaign, request.referer
and then whatever controller you are posting your message to will have a param called :campaign containing the URI that it came from or the name of the campaign parameter depending on which one you choose to use.

Best way to allow admin to build objects for Admin

My objective is to allow Admins the right to sign Users up for a Project.
Currently, Users can sign themselves up for Projects.
So I was thinking in order to allow Admin to do this.. do something like this :
haml
= link_to "Project Signup", card_signups_path + "?user=#{user.id}", :class => "button"
And pass the params[:user] so I can replace this controller with this :
if params[:user]
#card_signup = User.find(params[:user]).build_card_signup
else
#card_signup = current_user.build_card_signup
end
The trouble is though.. this is a 3 part signup process, and its loaded VIA AJAX, so I can't pass the ?user=#{user.id} in any of the steps after the first.. ( at least not by the same convention that I already did, or know how to )
What kind of strategy would you employ in this?
One possible way of accomplishing this, would be to add a hidden field to your form, that mirrors the parameter your passing in, if its found.
So if the parameter your passing in is user, in your view you want to add a hidden field something like:
<input type="hidden" name="user" and value="<%= params[:user] %>" />
or with a rails form helper:
hidden_field_tag 'user', params[:user]
This way the code in your controller can check for this parameter at each step on the receiving end and know who to save the object for. Something like this:
def create
#card_signup = CardSignup.new(params[:card_signup])
if params[:user] && params[:user].to_i > 0
##
##some logic here to make sure current_user is admin, as no one else is allowed to do this
##
#card_signup.user_id = params[:user]
else
#card_signup.user_id = current_user.id
end
##onto validating model and saving / redirecting / etc
end
But the ultimate goal here is to keep the user param around, whether its an initial GET parameter to the page, or a Put/Post from ajax/etc to submit the form, this parameter will be around.
One other security angle to check would also be in the 'new' action of this controller, and check that if the user param is present then the current_user is an administrator, otherwise redirect or display an error message. This combined with re-validating this on the create should provide a decent way of making sure no one else can make these requests. You could also put this in a before_filter and call it for only new and create to keep things clean.

Resources