Pass UTM parameter to URL from Controller - ruby

In my application, I show different design (in posts#show) to each user based on weight.
I basically make different designs for each post and give them weight and it randomly shows different design to each user. I basically do A/B testing of these design and track click-rates, views etc.
What I have been trying to fix, is to pass chosen design ID as a parameter to URL for trackings (For instance: www.my-site.com/ab-testing-post?utm_content=2)
This is how I select one design to show:
designs = #post.designs.pluck(:id, :weight).to_h
#design_distribution = WeightedDistribution.new(designs)
selected_design = #design_distribution.sample
#design = Design.find_by_id(selected_design)
I have tested with redirect_to, but I get too many redirects error.
How am I able to pass Design ID/ #design.id as utm_content when my post/page is loaded?
PS: When the design has been chosen, I can't do redirect_to #design because of advertising restrictions for doing redirects and what I do is to load the designs code in posts#show with using html_safe & That's the reason I need to be on the same page and pass the UTM instead.

Related

How to match parameter to TWO entities simultaneously?

My bot asks: 'how do you (i.e. customer) want to pay for this product?'
Customer says: 'part in cash and the difference in 48x'
What the customer is saying above is that he wants to pay in cash and use financing. And that financing should consider 48 installments.
Entities:
paymentType: {cash, financed} ; Financed includes 48x as a synonym
numInstallments: {12x, 24x, 36x, 48x} ; 48x is the number of installments desired
Using the GUI only, how to do this:
IF user says '48x' THEN simultaneously add 'financed' to the paymentType list AND set numInstallments equal to '48x' ?
Apparently the GUI doesn't allow me to do that unless I'm doing something wrong (see below the screen which allows a parameter to be mapped to an entity and notice that this dropdown apparently allows selection of a single entity and not two, which is what I need).
How to solve this problem in an easy way through the GUI?
I don't know if what you have in mind is actually feasible in this case.
What you could do is keep the intent and entities as-is and then create several conditions in the page where you fill this parameters or another page (i think this is preferred).
In that page you can put different routes where your conditions are true that modify your parameters as you wish.
For example, after asking the user how they'd like to pay, you can have a route going to a "Set parameters" page which has several routes:
First route has a condition $session.params.numeroDeParcelas != null (you know the user has asked a specific number of installments, so handle the case by setting the parameters you need in this route (under parameters in the route write paymentType : "financed")
Second route has another condition, for example $session.params.numeroDeParcelas = null (you know the user hasn't asked for financing, so set the same parameter as before to "cash")
and so on, until you've exhausted your user cases (all payment methods, possibly all types of financing).
Pay attention: the routes are always evaluated in order so make sure to keep this in mind while writing/ordering them: be specific to avoid fulfilling the wrong one by mistake (e.g. by creating compound conditions, chaining parameter checks as in $session.params.numeroDeParcelas = null AND $session.params. numInstallments = "36x"

Following Test Automation best practise of "Methods return other PageObjects" in Ruby

I am a big advocate of the Page Object Pattern (POP) as defined by the experts at Selenium:
https://code.google.com/p/selenium/wiki/PageObjects
A key view of theirs that I have always followed when using Appium with Java is:
"Methods return other PageObjects"
e.g. LoginPage loginPage = homePage.gotoLoginPage();
I am now trying to following POP using Calabash with Ruby and so have been writing code like this:
e.g. #login_page = #home_page.goto_login_page
However, since Ruby doesn't know what type of object #login_page is or #home_page is, you dont get any of the benefits of intellisense showing what methods are available for a given page.
Anyone know a good way around this?
As much as I appreciate and apply PO design pattern, as much I disagree with returning page object by page object. Page object should be independent and don't need to know about other page objects. Look at two examples:
You test form validation. Click on submit button returns page object which is subsequent in the workflow, but in this case you remain on page with validation errors. Your page object won't know about it and will return the other page.
Page which you get to after clicking a button may differ depending on the context (e.g. from what other page you got to current page). It can lead to having multiple versions of actually same method, which will return different page objects depending on context. This is not good and overcomplicates simple thing.
If you want to return current page object, you can benefit from it e.g. in Java, when you return this at the end of the method. Then you can chain all methods you execute as long as you are on the same page. But when it comes to the question 'how to implement returning different page objects' - answer is simple - 'just don't'. Please note wiki entry you quoted has not been updated for a good while and best practices has evolved since it was originally published.
It seems like you already have your solution. However for others and perhaps also for you the x-platform approach to calabash uses page objects so you could check out that implementation https://github.com/calabash/x-platform-example
An alternative method would be as follows. Not as neat as I would like (given the need to manually create new instances of subsequent pages), but available as an alternative option:
When(/^I buy a movie from the movie page$/) do
movie_page = MoviePage.new
movie_page.buyMovie("Test Movie")
purchase_page = PurchasePage.new
purchase_page.confirmPurchase
end
Found a way of getting this to work after much research and applying well known Java/C#/Obj-c principles to Ruby:
Given(/^I am on the launch page$/) do
#launch_page ||= LaunchPage.new
end
When(/^I open the set alarm time page$/) do
#set_alarm_page = #launch_page.goto_set_alarm_page
end
When(/^I open our apps from the home page$/) do
#launch_page.navigation_toolbar.open_our_apps
end
Then(/^I should see the homepage alarm time is (\d+)$/) do |alarm_time|
alarm_time_actual = #launch_page.get_alarm_time
assert_equal(alarm_time, alarm_time_actual)
end
As long as somewhere on the step definition class you explicitly create a new page object (in the above example: LaunchPage.new), then all subsequent pages will provide intellisense method/property values, since the resulting page types returned will be known by RubyMine.

Update model attribute without refreshing database

I'm building a website listing poker tournaments. I would like to allow user mark some tournaments as his favourite and avoid forms or extra page with GET parameter - I would like to to update it without refreshing website. From what I understand, it's done by ajax and jquery. But there are many ajax libraries and I would like you to tell me, which one should I use and how to do this simple functionality best.
This is my tournament table:
I would like to have another column before event time, that would contain image for heart. It would be black (not favourite) and if user clicks on it, it would turn red (favourite).
I think m2m relationship should be used here. This is my tournament model.
class Tournament(models.Model):
favourite = models.ManyToManyField(User)
date = models.DateTimeField('Event time')
currency = models.CharField(max_length=5, choices=CURRENCIES, default='USD')
name = models.CharField("Tournament name", max_length=200)
prize = models.DecimalField(max_digits=20, decimal_places=2)
entry = models.DecimalField(max_digits=20, decimal_places=2)
fee = models.DecimalField(max_digits=20, decimal_places=2)
password = models.CharField("password", max_length=200)
type = models.ForeignKey('room.Type')
room = models.ForeignKey('room.Room')
requirements_difficulty = models.IntegerField('Tournament Difficulty',
validators=[MinValueValidator(1), MaxValueValidator(30)])
requirements_text = models.CharField("Requirements Description", max_length=1000)
recurrence = models.CharField(max_length=5,
choices=RECURRENCE_CHOICES,
default='NONE')
So how do I add m2m relationship between user and tournament? Do I use ajax code or dajax? How do I create this m2m without refreshing page?
So how do I add m2m relationship between user and tournament?
Assuming that you use the default django user model:
Class Tournament(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_tournament')
...
Do I use ajax code or dajax?
As #doniyor said, you should define your real problem and split your question. SO is not "do it for me", anyway, what I can do for you, is give you some good links ;)
W3 schools definition for ajax:
http://www.w3schools.com/ajax/ajax_intro.asp
Good ajax plugin for djando that seems you already know:
http://www.dajaxproject.com/
By the way, you should use dajax, is easy and faster to create ajax pages integrated with django (you just have to follow the tutorials, is pretty simple).
How do I create this m2m without refreshing page?
Using dajax

Understanding routing in rails

Ok first off I have to say I'm very new to Rails. I have spent the last few days going through tutorial after tutorial and still missing a few concepts. Mainly because I just want to start off with a simple site structure but every tutorial is either a shopping cart or a blog which are more applications within a site. I have some pages on my site that will have photo galleries that are database driven but for now I'm just trying to get some answers to these questions.
Site structure:
home | photos | about | work | contact
Work has sub pages for example:
html | ruby | rails | bla-bla
Controllers:
Do I need to set up a controller for every new page or could I have one controller that handles all main level pages.
If I could use one controller how would that work and would I need to define an action to handle each page ( view ) like
class MainController < ApplicationController
def index
end
def photos
end
def contact
end
# and so on ......
end
Routing:
How would I route the above.
Whats the difference between a resource and a *get
get "photos/photos"
resources :photos
When I setup a controller for a specific page like.
rails g controller Contact contact
It creates a folder inside my views called contact and inside it is a view called contact meaning my url is contact/contact
it also adds a route get "contact/contact"
Now what if I only want the user to type http://mydomain/contact then this is not going to work. How would I set it up so the user doesn't have to add http://mydomain/contact/contact
The only way I could find a way around this was to use the match verb.
match "contact" => 'contact#contact'
Does this mean I have to use the match for every page on my site to change the url path?
These are just a few of many question I have that are not so clear in most of the tutorials I have gone over. Please don't tell me to use the user guide as I have already and am felling overwhelmed right now. I just would love some clear answers from some developers who are working in rails and would go about setting up a structure like I have outlined above.
Thanks
You're going to get some conflicting advice I think, but here's what I'd do.
Create a MainController (I prefer HomeController as it will also handle the homepage, but that's just me). This controller will handle the actions for home, about, and contact.
Create a PhotosController since you said photos come from the database and there's a good chance there is an index/listing page and individual pages for each photo.
Create a WorksController that handles the work main page and all the sub pages.
Now.. some people would argue (myself included) that home, about, contact, and all the work pages (sub pages too) should be handled by a generic PagesController that is smart enough to know what to do. I'm not gonna get into that now though.
The difference between these two routes:
get "photos/photos"
resources :photos
Is that the first will only create a single route for a GET request to '/photos/photos'. The second will create the standard CRUD operations for '/photos'.
For your static pages, I probably would go ahead and just create:
match "about" => 'main#about'
match "contact" => 'main#contact'
...
It's harder to say for the photos and work since I don't know what all you'll be doing there. The above isn't as DRY as it could be, but unless you go the "smart pages controller" route it's the simplest.

CakePHP, organize site structure around groups

So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?

Resources