Using Rails Gem Active Admin WITHOUT Associations - ruby-on-rails-4

There is a good question here explaining how to correctly use ActiveAdmin with associations.
In my situation though I have a customer model has_many associated to a sales model and the sales model is pretty big. So when I try to view my customer page in ActiveAdmin the server is running a call for all sales so that (I am guessing) it can return those associated columns.
This is timing out my server (504 Gateway Time-out ngx_openresty/1.4.3.6).
Is there any way to say to ActiveAdmin to ignore an association for that view? Ie the index view. Once I get to the 'show' view and have isolated a customer it is ok to run the query on that customers sales but running all customers with all sales is not required on the index page.
Hope I have been clear.

Ok I have just realised that without specifying which columns I want in the index on the customer.rb file it will try and grab all including the associated columns (correct me if I am wrong on that).
Either way, before I only had he config.per_page line. By adding index do and my columns it is working properly. That was easy!
ActiveAdmin.register Customer do
config.per_page = 25
index do
selectable_column
id_column
column :customer_code
column :customer_name
column :customer_rep_name
column :created_at
actions
end
filter :customer_rep_name
filter :market_segment_name
end

Related

Which model notifications should I listen to in order to calculate the sum of an IG column?

I am using Apex 18.2. I have a page with an interactive grid with a column "Total" whose sum value should get calculated through looping over the model whenever the sum changes for example, when a new row is created, a row is deleted, a row column's value has changed, etc. I am subscribing to the model to accomplish the task. But there are many model notifications one could listen to. I only need to listen to the model notifications that would affect the sum of the Total column to avoid looping through the model when unnecessary. Could you tell me which notifications are they?
https://docs.oracle.com/en/database/oracle/application-express/18.2/aexjs/model.html
The best way to learn about this is to explore. Add the following to your page's Execute when Page Loads attribute:
var model = apex.region('REGION_ID').widget().interactiveGrid("getCurrentView").model;
model.subscribe({
onChange: function(changeType, change) {
console.log(changeType, change);
}
});
Then work with your IG and note the changeType values logged - those are the notification names that are listed in the doc.
Note that there are rows on the server, rows in the model, and rows displayed in the DOM - the numbers may or may not be different so keep that in mind for aggregate functions that need to work with "all" of the rows.

add custom product statuses in opencart admin

By default in opencart we have 2 product statuses (which we can use also in admin to filter products) - enabled and disabled.
I need to add a few more custom statuses, which will be just for my team which is working over the products (for example i want to add need description status, products with the custom statuses will not show in the front end (like disabled) so if the product is market with it, the team who is working on product descriptions will easy filter only the products that need descriptions).
I hope i explained clearly as well...Thank you...
If you look into the language file of product admin/language/language_name/catalog/product.php, there is $_['text_enabled'] and $_['text_disabled'], you can add $_['text_need_description'].
In category.php and product.php controllers you will find
$data['text_enabled'] = $this->language->get('text_enabled');
$data['text_disabled'] = $this->language->get('text_disabled');
Next to them, you can add
$data['text_need_description'] = $this->language->get('text_need_description');
You can check occurrences of 'enabled' and change accordingly. You also need to change the relevant templates and models.
In database, status is saved as 1 for enabled and 0 for disabled, you can save the value 2 for 'need description'.
When the products are fetched to be displayed to the customer on front-end, only the products with status 1 are fetched so you won't have to change that part.

How can I select records n-at-a-time for multiple users to edit?

I am using a Django backend with postgresql.
Let's say I have a database with a table called Employees with about 20,000 records.
I need to allow multiple users to edit and verify the Area Code field for every record in Employees.
I'd prefer to allow a user to view the records, say, 30 at a time (to reduce burnout).
How can I select 30 records at a time from Employees to send to the front end UI for editing, without letting multiple users edit the same records, or re-selecting a record that has already been verified?
I don't need comments on the content of the database (these are example table and field names).
One way to do this would be to add 2 more fields to your table, say for example assigned_to and verified. You can update assigned_to, which can be a foreign key to the verifying user, when you allow the user to view that Employee. This will create a record preventing the Employee from being chosen twice. assigned_to can also double as a record of who verified this Employee for future reference.
verified could be simply a Boolean field which keeps track if the Employee has already been verified and can be updated when the user confirms the verification
The actual selects can be done like this:
employees = Employee.objects.filter(assigned_to=None, verified=False)[:30]
Then
for emp in employees:
emp.assigned_to = user
emp.save()
Note: This can still potentially cause a race condition if 2 users make this request at exactly the same time. To avoid this, another possibility could be to partition the employee tables into groups for each user with no overlap. This would ensure that no 2 users would ever have the same employees

Fast way to sort a model by count of child's child

I currently have the following models: MinorCategory > Product > Review
On a view, I show the 12 MinorCategories that have the most reviews. This view is very slow to respond, and I think it is a problem with how I do the query.
Here is my current code:
class MinorCategory < ActiveRecord::Base
has_many :products
has_many :reviews, through: :products
...
def count_reviews
self.reviews.count
end
...
end
class Review < ActiveRecord::Base
belongs_to :product, touch: true
...
end
class HomeController < ApplicationController
#categories = MinorCategory.all.sort_by(&:count_reviews).reverse.take(12)
end
So that is basically it. In the view itself I go through each #categories and display a few things, but the query in the controller is what seems to be slow. From SkyLight:
SELECT COUNT(*) FROM "reviews" INNER JOIN "products" ON "reviews"."product_id" = "products"."id" WHERE "products"."minor_category_id" = ? ... avg 472ms
I am not good with sql or active record, and still pretty new to Ruby on Rails. I've spent a couple hours trying other methods, but I can not get them to work so I thought I would check here.
Thank you in advance to anybody that has a moment.
You need some basic SQL knowledge to better understand how database queries work, and how to take advantage of a DBMS. Using ActiveRecord is not an excuse to not learn some SQL.
That said, your query is very inefficient because you don't use the power of the database at all. It's a waste of resources both on the Ruby environment and on the database environment.
The only database query is
MinorCategory.all
which extracts all the records. This is insanely expensive, especially if you have a large number of categories.
Moreover, self.reviews.count is largely inefficient because it is affected by the N+1 query issue.
Last but not least, the sorting and limiting is made in the Ruby environment, whereas you should really do it in the database.
You can easily obtain a more efficient query by taking advantage of the database computation capabilities. You will need to join the two tables together. The query should look like:
SELECT
minor_categories.*, COUNT(reviews.id) AS reviews_count
FROM
"minor_categories" INNER JOIN "reviews" ON "reviews"."minor_category_id" = "minor_categories"."id"
GROUP BY
minor_categories.id
ORDER BY
reviews_count DESC
LIMIT 10
which in ActiveRecord translates as
categories = MinorCategory.select('minor_categories.*, COUNT(reviews.id) AS reviews_count').joins(:reviews).order('reviews_count DESC').group('minor_categories.id').limit(10)
You can access a single category count by using reviews_count
# take a category
category = categories[0]
category.reviews_count
Another approach that doesn't require a JOIN would be to cache the counter in the category table.

Adding custom column using 'activeadmin-axlsx' gem

I am using activeadmin gem in my application using Rails 4. I need excel download for which I am making use of activeadmin-axlsx gem.
I am able to get all the columns that exists in my database for the particular model in the excel sheet as its columns. However, what I want is, to add a column which does not exists in my database.
This is what I have tried until now
column('start_date') do |date|
date.start_date
end
Here start_date is an attribute in my db and hence I get that column in the excel.
Now when I try to add another column End Date(which is not an attribute in the db), I get a blank column.
I have also tried the below snippet, referring to the Github link for activeadmin-axlsx
config.xlsx_builder.column('end_date') do |emp|
emp.end_time.strftime("%Y-%m-%d")
end
This gives a blank column in the excel
Can anybody help me achieve this?Or suggest any other gems that can be used with activeadmin gem?
Many Thanks!
The solution is to add the attributes that do not exist in your database as an attribute accessor in your respective model.
For the above example,
end_date is not an attribute in the table, so in the model say Employee, add this
class Employee < ActiveRecord::Base
attr_acessor :end_date
end
Here I am modifying end_time which is an attribute in database of type datetime to fetch only the date with the name of the column being End Date
In the app/admin/employee.rb
ActiveAdmin.register User do
xlsx do
column('end_date') do |emp|
emp.end_time.strftime("%Y-%m-%d")
end
end
end
This would give you the desired value.
I think you can just define one like start_date. Did you try:
column(:end_date) do |resource|
resource.end_time.strftime('%Y-%m-%d')
end