On Rails ActiveRecord show count based on parameter - mysql

I have some reporting methods throughout my app and in some cases I want to return the count (for a dashboard), and in others, return the full result set for viewing the details of a report.
What I'm wondering, is there a way to dynamically choose to show the count (instead of what I'm doing here):
def get_query_results(reporting_parameters, count_only = true)
#put together reporting details...
if count_only
MyModel.where(query).count
else
MyModel.where(query)
end
end
I considered setting a local variable to the result of my query parameter, and then call count, but that queries the database again (and even if it didn't it could increase memory usage).
Is there a way to do an effective way to do this in one query? This is one of several queries I have like this in my app, otherwise I wouldn't care. Also, I'd use a ternary, but the actual query conditions in my app are much longer than my example here and it makes it unreadable.

Suppose you are doing this:
#collection = get_query_results(...)
Then you can do this afterwards instead of inside of the action:
#collection.count
And if you like to call another method:
def total_number(collection)
collection.count
end
#collection = get_query_results(...)
no_of_records = total_number(#collection)

Related

Rows count of Couchbase view subset

When I query some view in Couchbase I get the response that has following structure:
{
"total_rows":100,
"rows":[...]
}
'total_rows' is very useful property that I can use for paging.
But lets say I select only a subset of view using 'start_key' and 'end_key' and of course I don't know how big this subset will be. 'total_rows' is still the same number (as I understand it's just total of whole view). Is there any easy way to know how many rows was selected in subset?
You can use the in-built reduce function _count to get the total count of your query.
Just add _count as reduce function for your view. After that, you will need to make two calls to couchbase:
In one call, you'll set the query param reduce=true (along with either group=true or group_level=n, depending upon how you're sending your key(s)). This will give you the total count of your filtered rows.
In the other call, you'll disable the reduce function with reduce=false because you now need the actual rows.
You can find more details about map and reduce at http://docs.couchbase.com/admin/admin/Views/views-writing.html
You can just use an array count/total/length in whatever language you are using.
For example in PHP:
$result = $cb->view("dev_beer", "beer_by_name", array('startkey' => 'O', 'endkey'=>'P'));
echo "total = >>".count($result["rows"])
If you're actually wanting to paginate your data then you should use limit and skip:
http://www.couchbase.com/docs/couchbase-manual-2.0/couchbase-views-writing-querying-pagination.html
If you have to paginate the view in the efficient way, you actually don't need to specify both start and the end.
Generally it is possible to use startkey/startkey_id and limit. In this case the limit will tell you that the page won't be bigger than known size.
Both cases are described in CouchDB book: http://guide.couchdb.org/draft/recipes.html#pagination
Here is how it works:
Request rows_per_page + 1 rows from the view
Display rows_per_page rows, store + 1 row as next_startkey and next_startkey_docid
As page information, keep startkey and next_startkey
Use the next_* values to create the next link, and use the others to create the previous link

Can I create sperate queries for different views?

I'm learning sqlalchemy and not sure if I grasp it fully yet(I'm more used to writing queries by hand but I like the idea of abstracting the queries and getting objects). I'm going through the tutorial and trying to apply it to my code and ran into this part when defining a model:
def __repr__(self):
return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)
Its useful because I can just search for a username and get only the info about the user that I want but is there a way to either have multiple of these type of views that I can call? or am I using it wrong and should be writing a specific query for getting different data for different views?
Some context to why I'm asking my site has different templates, and most pages will just need the usersname, first/last name but some pages will require things like twitter or Facebook urls(also fields in the model).
First of all, __repr__ is not a view, so if you have a simple model User with defined columns, and you query for a User, all the columns will get loaded from the database, and not only those used in __repr__.
Lets take model Book (from the example refered to later) as a basis:
class Book(Base):
book_id = Column(Integer, primary_key=True)
title = Column(String(200), nullable=False)
summary = Column(String(2000))
excerpt = Column(Text)
photo = Column(Binary)
The first option to skip loading some columns is to use Deferred Column Loading:
class Book(Base):
# ...
excerpt = deferred(Column(Text))
photo = deferred(Column(Binary))
In this case when you execute query session.query(Book).get(1), the photo and excerpt columns will not be loaded until accessed from the code, at which point another query against the database will be executed to load the missing data.
But if you know before you query for the Book that you need the column photo immediately, you can still override the deferred behavior with undefer option: query = session.query(Book).options(undefer('photo')).get(1).
Basically, the suggestion here is to defer all the columns (in your case: except username, password etc) and in each use case (view) override with undefer those you know you need for that particular view. Please also see the group parameter of deferred, so that you can group the attributes by use case (view).
Another way would be to query only some columns, but in this case you are getting the tuple instance instead of the model instance (in your case User), so it is potentially OK for form filling, but not so good for model validation: session.query(Book.id, Book.title).all()

nested sql queries in rails

I have the following query
#initial_matches = Listing.find_by_sql(["SELECT * FROM listings WHERE industry = ?", current_user.industry])
Is there a way I can run another SQL query on the selection from the above query using a each do? I want to run geokit calculations to eliminate certain listings that are outside of a specified distance...
Your question is slightly confusing. Do you want to use each..do (ruby) to do the filtering. Or do you want to use a sql query. Here is how you can let the ruby process do the filtering
refined list = #initial_matches.map { |listing|
listing.out_of_bounds? ? nil : listing
}.comact
If you wanted to use sql you could simply add additional sql (maybe a sub-select) it into your Listing.find_by_sql call.
If you want to do as you say in your comment.
WHERE location1.distance_from(location2, :units=>:miles)
You are mixing ruby (location1.distance_from(location2, :units=>:miles)) and sql (WHERE X > 50). This is difficult, but not impossible.
However, if you have to do the distance calculation in ruby already, why not do the filtering there as well. So in the spirit of my first example.
listing2 = some_location_to_filter_by
#refined_list = #initial_matches.map { |listing|
listing.distance_from(listing2) > 50 ? nil : listing
}.compact
This will iterate over all listings, keeping only those that are further than 50 from some predetermined listing.
EDIT: If this logic is done in the controller you need to assign to #refined_list instead of refined_list since only controller instance variables (as opposed to local ones) are accessible to the view.
In short, no. This is because after the initial query, you are not left with a relational table or view, you are left with an array of activerecord objects. So any processing to be done after the initial query has to be in the format of ruby and activerecord, not sql.

rails run function inside query

If I have the following query, is it possible to be able to run a function inside? Let's say I want to add WHERE zip_code = user_distance(zip_code)?
I want to take data from each row and run it through a function before actually selecting it.
#posts = Listing.find_by_sql(["SELECT * FROM listings WHERE industry = ? && ", current_user.industry])
If you are mainly looking to get this working and not worrying so much about performance (because going straight to the SQL is faster than going through ActiveRecord) then you could do:
listings = []
Listing.all.each do |listing|
listings << listing if user_distance(listing.zip_code)
end
So, it will go through each listing and add it to that array if the user_distance method returns true (or however it is set up).
Another thing you could do is set up a stored procedure ("stored proc") on your database that takes in a zip code and returns what it is you want (i.e, does the same thing as user_distance), and that user defined variable max_distance could be in a database table so it's accessible to your stored procedure. Then you could call that stored proc from the SQL and still be able to pass in the zip_code of each row.

How to automatically change a parameter in Reporting Services when another is changed?

I have a 'Product' parameter in my report. Depending on the product the user chooses, it will call the report generator stored procedure from a different data source. Looking at this article, I've found how to do the first part of this solution. I've created two internal parameters, Server and Database, and the connection string will use them to connect to the right database.
But I need to set this two parameters when the user chooses a product. How could I do this?
(If #Product = X) => #Server = Y, #Database = Z
How did I resolve this:
I didn't do the way the article suggested. Instead, I threw away this two additional parameters and just put a big Switch expression at the connection string definition. Depending on the #Product value, the switch returns a different value. It may sound uglier, but at least it works.