Rspec/Capybara not displaying expected results for cache_counter - ruby-on-rails-4

The problem is the results printed to the screen by capybara/rspec are different to the values in the database.
Background
- I have a many-to-many relationship between promo and products.
- Promo has a products_counter column to keep track of the number of products related to a promo. This is handled with counter_cache on the association.
- This functionality is working. I have tested it through the front end - basic crud functionality - and all the data is correct on the front end.
Something is happening and I can't figure it out. My spec fails because the page does not have the value '1' on it which is the product count. The page instead has 2 for the product count on the page.
I thought that this issue could be a point in the right direction, but I had no luck with that and there isn't much else on google.
See spec below.
require 'rails_helper'
include Warden::Test::Helpers
Warden.test_mode!
feature 'Promo index page' do
scenario 'displays a list of promos' do
admin = create(:user, :admin)
p1 = create(:promo)
p1.products << create(:product)
login_as(admin)
visit promos_path
puts p1.products.count # => 1 in console
puts p1.products_count # => 1 in console
# save_and_open_page => this gives me a view into the page
# on the browser - lets me see that product count is printing
# to the screen as 2
expect(page).to have_text p.code
expect(page).to have_text p.name
expect(page).to have_text p.products.count # => fails because page displays 2 instead of 1
end
end
I have included the view for those that want to see how it's being rendered.
header.full-width-row
.columns.large-12
= link_to 'New Promo', new_promo_path, class: 'right button tiny radius'
section.full-width-row
.columns.large-12
table.full-width
thead
tr
td = "Code"
td = "Name"
td = "Product Count"
tbody
- #promos.each do |p|
tr
td.filter-on = p.code
td.filter-on = link_to p.name, promo_path(p)
td = p.products_count
Any help appreciated.

Related

Ajax Datatables Rails - Query not working for show-method

Let's start with the database-model:
# => ProductSelection.rb
has_many :products, -> { uniq }, through: :product_variants
# => Product.rb
has_many :product_informations
belongs_to :product_configuration
belongs_to :product_class
Using plain Ruby on Rails, we collected the products to show inside the product_selection#show-method like so:
#products = ProductSelection.find(params[:id]).products.includes(:product_informations, :product_class, :product_configuration)
and generated a table like so:
= table(#products).as(:products).default do |product|
= product.name
= product.product_configuration.name
= product.product_class.name
= product.state
= link_to product_product_selection_path(#product_selection, product_id: product.id), method: :delete
Now we want to use Datatables instead of plain Ruby on Rails.
We are using the Ajax-Datatables-Rails-Gem. We would like all columns to be sortable and searchable in the end.
Unfortunately we do not come past the query to retrieve the Products belonging to the ProductSelection in question.
This is the query we tried so far:
def get_raw_records
ProductSelection.find(params[:id]).products.includes(:product_informations, :product_class, :product_configuration).references(:product_information, :product_class, :product_configuration).distinct
end
def data
records.map do |record|
[
record.name,
record.product_configuration.name,
record.product_class.name,
record.state,
record.id
]
end
end
The error that pops up:
> undefined method `each_with_index' for nil:NilClass
When adding in sortable/searchable columns, the error is the following instead:
PG::UndefinedColumn at /product_selections/fetch_table_data_show.json
=====================================================================
> ERROR: column products.name does not exist
LINE 1: SELECT DISTINCT "products"."id", products.name
with the configuration like so:
def sortable_columns
# Declare strings in this format: ModelName.column_name
#sortable_columns ||= %w(Product.name ProductConfiguration.name ProductClass.name Product.state)
end
def searchable_columns
# Declare strings in this format: ModelName.column_name
#searchable_columns ||= %w(Product.name ProductConfiguration.name ProductClass.name Product.state)
end
I think the problem is with the different models right here. I assume Datatables-Rails expects a model of ProductSelection but instead is prompted with a Product. Any help would be highly appreciated!
If anything is missing, let me know!
After having another look at this, we figured the problem was that Product.name wasn't a valid ActiveRecord-construct. Instead it was a helper method defined somewhere down the road.
Since the gem tries to find records through the column-names, this error occurred.
We solved it by removing the column in question. Other approaches would be to:
Store the data in a separate column, instead of using a helper.
Implementing the helpers behavior in javascript so that we can pass
it as a callback to datatables.

Paginated array would not show

I'm rather new to Ruby on Rails so would appreciate some help
Roles have Users in my application.
When showing a role I would like to render a paginated list of user names (and as a further refactor - links to users).
Currently my HAML template is as follows
...
%ul.assigned-users
- if #role.users.present?
- names = #role.users.collect {|u| u.name}
- links = Kaminari.paginate_array(names).page(params[:page]).per(20)
= paginate links
- else
%p No users have this role assigned
...
Rendering it gives me the pagination links BUT no names.
Kaminari's paginate_array method does not show the values in the array.
The best way to do so is get the query paginated from the database. Kaminari.paginate_array in your code takes in the whole array of users from the database and then paginates it which is highly inefficient and memory consuming.
You need to add the logic to the controller. If you paginate the #role.users query, it is generated with LIMIT which is the value you assign in the per method and OFFSET which equals to (params[:page] - 1) * per. This gets only the number of records you need from the database.
In your controller app/controllers/roles_controller.rb
class ConversationsController < ApplicationController
def show
#role = Role.find params[:id]
#users = #role.users.page(params[:page]).per(20)
end
end
In your view app/views/roles/show.html.haml
%ul.assigned-users
- if #users.present?
- #users.each do |u|
%li=u.name
= paginate #users
- else
%p No users have this role assigned

Classic ASP Cookie Vulnerability

I have a simple login page on a classic asp page.
It takes the username field from a form ("un") and the password ("pw") and does the following with them:
<%
un = newstr(request.form("un"))
pw = newstr(request.form("pw"))
SQL = "SELECT * from my_table WHERE un = '"&un&"' AND pw = '"&pw&"'"
set cRS = oConn.Execute(SQL)
if cRS.EOF then
%>
<p>Unable to log you in. Please try logging in again.</p>
<%
elseif NOT cRS.EOF then
Response.Cookies("test") = "jeQmV4'QG)Eu'N-XSTC;pZeuwqUsjBdVv>Sqr!]ZhzB{dJ'p-#cYSdwY"
Response.Cookies("test").Expires = Date() + 365
response.redirect "main.asp"
end if
end if
%>
Then I have some simple validation at the top of each page whose contain I only want logged in users to be able to see, which does this:
<%
test = Request.Cookies("test")
if test = "" OR test <> "jeQmV4'QG)Eu'N-XSTC;pZeuwqUsjBdVv>Sqr!]ZhzB{dJ'p-#cYSdwY" then response.redirect("default.asp")
%>
I wanted to check - is that naively simple?
Could someone easily hack into my site, by e.g. setting a cookie on their computer, called "test" and whose value = "jeQmV4'QG)Eu'N-XSTC;pZeuwqUsjBdVv>Sqr!]ZhzB{dJ'p-#cYSdwY"?
Or wouldn't it be pretty unlikely someone would guess that string value of "jeQmV4'QG)Eu'N-XSTC;pZeuwqUsjBdVv>Sqr!]ZhzB{dJ'p-#cYSdwY"?
Thanks
First off, someone could break your system by trying to pass in user names like
';DROP TABLE Users
http://xkcd.com/327/
Always, always use parameterized queries.
Never trust the UI for anything related to security. The client can observe all cookies that you set, and return any cookie back to you that it wants to. If this is not HTTPS, someone in the middle could also observe the cookie being sent back and forth.
Don't re-invent security frameworks. They are very hard to get right.

Filter sunspot search by class

I've set up a sunspot/solr search with rails that works like a charme:
# run the search
search_results = Sunspot.search Project, Question, User, Requests do
fulltext params[:search]
paginate page: params[:page], per_page: 10
end
It could be cool to filter that search results by a given class. E.g.there is a param in the URL like params[:class], it would be awesome if the search would only consist of results from that specific class (Project, Question, User, Requests...).
I just can't figure out where to start at.
Hope someone could help me out!
Got it. All you need to do is adding the class as a string to the searchable block:
# solr search
searchable do
text :firstname, :lastname, :email, :position
integer :account_id
string :klass
end
def klass
return self.class.to_s.downcase
end
After that you're able to filter by the class (klass)
# run the search
search_results = Sunspot.search Project, Question, User do
fulltext params[:search]
with :account_id, params[:account_id]
with :klass, "question"
paginate page: params[:page], per_page: 10
end

How to "Spawn" a Wall album in a new page

I am trying to post pictures to customers' pages. There may or may not be a "Wall Photos" album in the page.
In scenarios where there is not a pre-existing "Wall Photos" album how would I create / request the creation of a wall photo album?
I am using Koala and I can create albums, but I cannot create albums with type = "wall".
here is the code I am using to create / find albums:
def get_photo_album(facebook_id)
# Looking for a pre-existing WALL PHOTO album
p "============= Getting Wall Photos album for fbid #{facebook_id}"
album = get_album facebook_id, 'Wall Photos'
unless album
p ' ======= Album FAIL 1 - getting Photos '
album = get_album facebook_id, FALLBACK_ALBUM_NAME
unless album
p ' ========== Album FAIL 2 - MAKING Phtoos '
#graph_client.put_object facebook_id, 'albums', 'name' => FALLBACK_ALBUM_NAME
sleep 3 # wait 3 seconds to let facebook make and fiddle with new album
album = get_album facebook_id, FALLBACK_ALBUM_NAME
unless album
p ' ##################### UTTER ALBUM FAIL '
raise "Cannot use alternative photo album"
end
end
end
if album && album.length > 0
album
else
# ensure that there is an album.
raise "Cannot use alternative photo album"
end
end
def get_album(facebook_id, name)
params = {'name' => name};
albums = #graph_client.get_connections(facebook_id, "albums", params)
p "Found #{albums ? albums.length : 0} albums named #{name} for fbid #{facebook_id}"
albums = albums.reject do |a|
a['name'] != name
end
p "Found #{albums ? albums.length : 0} albums named #{name} for fbid #{facebook_id} AFTER filtering for name"
pp albums
albums.length >0 ? albums[0] : nil
end
end
And here is the Koala code I am using to put the picture itself
def put_image(facebook_id, params)
params = sanitize_params(params)
params = encode_necessary_params(params)
picture = URI.decode(params['picture'])
photo_album = get_photo_album(facebook_id)
photo_album_id = photo_album['id']
params = params.reject do |key, value|
key == 'metadata_type'
end
p ' -------------------------------------- PUT PICTURE ----------------------------'
p "fbid:#{facebook_id}, message: #{params['message']}, picture: #{picture}"
p ' -------------------------------------- PUT PICTURE ----------------------------'
out = #graph_client.put_picture picture, {:message => params['message']}, photo_album_id
Statsd.increment("posts")
out
rescue Exception => ex
handle_error(ex)
end
I have tried several variations including:
putting 'type' => 'wall' in the #graph_client.put_object parameters: doesn't post the image at all
creating an album named 'Wall Photos' - the album appears, but the posts don't look like wall posts.
To be clear: *The ultimate goal is for all posts to this album to have "big" previews - full column width, not tiled 1" previews. *
Any help would be appreciated.
What you're trying to do isn't going to be possible - the Wall Photos album is a special album which is generated from photos posted to feed, and there is no API available to post photos that way - if you post to /photos they go into an album specifically for the app.
However, all is not lost. If you're willing to embrace newer functionality, you'll both be able to meet your goal of having large photos in feed whilst also achieving greater viral potential for your app. The answer is Open Graph Actions. Specifically User Generated Photos in Open Graph
The process for this is relatively simple:
Create an Open Graph action and object for your app (do this from the Developer App Dashboard for that particular app), this can be anything depending on what your app does, but, for example, Instagram uses 'took' as their OG action and 'a photo' as their OG object. This means that posts from that app look like "Matthew took a photo with Instagram" and show the photo below. Which action you want to use is up to you.
Request publish_actions permission from your app users, if you haven't been already.
Make API calls to:
https://graph.facebook.com/me/YOURAPPNAMESPACE:YOURACTION?
YOUROBJECTTYPE=URLWHEREYOUROGOBJECTISLOCATED&
image[0][url]=URLOFPHOTOYOUWANTTOADD&
image[0][user_generated]=true
You'll also need to sign this API call with the access token for that user, or I believe, if you have publish_actions for that user, you can make the above call to /USERID instead of /me and use your app's access token and it will work.
As you can see from the documentation this will give you the full sized photo that you're after and having it be created by an Open Graph action allows for a whole host of extra virality if you incorporate extras such as OG action links, authenticated referrals etc.