Dividing up an index params into multiple pages - ruby-on-rails

I have a list of records that I have displayed on an index page. (they are displayed in a table form). Because there are a number of them I am trying to divide them up to about 30 records per page. I've created a search params functionality with the index displayed beneath it.
The problem that I am having is that I am having trouble getting more than one page to render on my list. As of right now I have about 150 records. However I only have one page listed with only 30 records on it and am not able to sort through them. Would anybody have any idea what I could be missing?
Here is the segment in my code where this gets addresssed.
def search_params
default_index_params.merge(params.fetch(:record_collection, {})).with_indifferent_access
end
def default_index_params
{
per: 30,
page: 1,
sort_by: "created_at",
sort_direction: "desc",
customer_id: 0
}
end
In my view, I do have a little bit of coffee-script that plays a role in the table itself. I don't know if it is the root of my problem, but I have it here as well.
:coffeescript
$('#record_table').dataTable
aaSorting: [[1, 'asc']]
bPaginate: false
bFilter: false,
aoColumns:[null, null, null, null, null, { bSortable: false }, null, { bSortable: false }]
My record collection is used for defining the params, i don't think that it is useful for this problem. (but could certainly post if needed)
Thanks in advance to anybody who is able to help figure out what is going on with this.

You need to pass paging: true and pageLength: 30 in coffescript, and just remove page: 1,per: 30 from default_index_params method. So your coffeescript will look like this:
:coffeescript
$('#record_table').dataTable
aaSorting: [[1, 'asc']]
paging: true
pageLength: 30
bFilter: false,
aoColumns:[null, null, null, null, null, { bSortable: false }, null, { bSortable: false }]
your default_index_params will looks like this:
def default_index_params
{
sort_by: "created_at",
sort_direction: "desc",
customer_id: 0
}
end

Related

Rails permit nested attribute

I am working on rails 6 with ruby-2.6.5 and i am working on the API. I am using nested attributes for my order as follows:-
orders_controller.rb
# frozen_string_literal: true
module Api
module V1
class OrdersController < Api::V1::ApiApplicationController
before_action :validate_token
def create
debugger
order = OrderInteractor.create(order_params, #user_id)
if order.save
render json: { 'message' => 'Order Placed' }, status: :ok
else
render_errors(order)
end
end
private
def order_params
params.require(:data)
.require(:attributes)
.require(:order)
.permit(:user_id, :address_id, :total_price, :payment_status,
:order_number, :delivery_time_slot,
order_details_attributes:
%i[price quantity order_detail_status product_id
order_number variant_id],
payment_details_attributes:
%i[payment_data payment_id])
end
end
end
end
Api Request:-
{
"data": {
"attributes": {
"order": {
"address_id": "82",
"delivery_time_slot": "5:00 PM - 8:00 PM(Today)",
"order_details_attributes": [{
"price": "76.0",
"product_id": "46",
"quantity": "4",
"variant_id": "47"
}, {
"price": "9.9",
"product_id": "30",
"quantity": "1",
"variant_id": "29"
}],
"payment_details_attributes": [{
"payment_data": {
"data": {
"nameValuePairs": {
"razorpay_payment_id": "pay_HiHceX2p6450Wa",
"org_logo": "",
"org_name": "Razorpay Software Private Ltd",
"checkout_logo": "https://cdn.razorpay.com/logo.png",
"custom_branding": false
}
},
"paymentId": "pay_HiHceX2p6450Wa",
"userContact": "+916494949494",
"userEmail": "dailyferia#gmail.com"
}
}],
"total_price": "354"
}
},
"type": "orders"
}
}
While placing order i am getting the error Unpermitted parameter: :payment_data but it's working fine for the order_details. Please help me to fix it? I also tried the below ways to fix it but nothing worked:-
payment_details_attributes: %i[:payment_data payment_id]) and `payment_details_attributes: ['payment_data', 'payment_id'])`
Your payment_data is a complex object, rather than the scalars that are found in your order_details_attributes
You will need to add more to the permitted parameters, I believe the simplest solution would be:
payment_details_attributes: [payment_data: {}]
This should accept all parameters under payment_details_attributes, but it would also permit any other keys as well. You may want to be more strict and only allow the parameters specified above, in which case you could do:
payment_details_attributes: [
payment_data: {
data: {
nameValuePairs:
%i[razorpay_payment_id org_logo org_name checkout_logo custom_branding]
},
:paymentId, :userContact, :userEmail
}
]
which should restrict the parameters to just the format used in your example.
A few other notes:
You have %i[payment_data payment_id] in your original sample, but there is no payment_id in your payload. The attribute in the sample is paymentId, and on top of that, it is an attribute of the payment_data, not the payment_details_attributes
you wouldn't use %i and a colon, the %i is a shorthand for creating an array of ruby symbols, so %i[:payment_data payment_id] would create the array [:":payment_data", :payment_id] (note the extra colon at the beginning of payment_data)
Lastly, I haven't tested my code above, so there could be a syntax or other error, but hopefully this points you in the right direction.

rails database records issue

This is my query method in model file:
def self.sum_by_brand_category
result = Product.joins(:brand, :category)
.select("brands.id as brand_id, categories.id as category_id, sum(products.quantity) as count")
.group("brands.id, categories.id")
return result
end
Here is the sample database query result I get:
[
{
"id":null,
"brand_id":43,
"category_id":1,
"count":2
},
{
"id":null,
"brand_id":43,
"category_id":2,
"count":5
},
{
"id":null,
"brand_id":43,
"category_id":3,
"count":4
},
....
]
I would expect the final JSON result to be used in views should be like this:
[
{
"id":null,
"brand_id":43,
"quantity": [
{
"category_id": 1,
"count": 2
},
{
"category_id": 2,
"count": 5
},
{
"category_id": 3,
"count": 4
}
]
},
....
]
How can I achieve it? Change the model method? Rebuild the result in the controller before sending it to the view? and how?
Any suggestions will be appreciated. Thank you.
Updated:
Based on #cmrichards 's answer, I come up with this private method to be called in controller and then used in views. I am including my work here, although these are not so DRY codes:
private
def get_sum_by_brand_category
query_results = Product.sum_by_brand_category
results = []
query_results.group_by(&:brand_id).each do |brand_id, query_result|
result = {}
result[:id] = nil
result[:brand_id] = brand_id
quantity_array = []
query_result.each do |data|
quantity_block = {}
quantity_block[:category_id] = data.category_id
quantity_block[:count] = data.count
quantity_array.push(quantity_block)
end
result[:quantity] = quantity_array
results.push(result)
end
return results
end
Please DRYing them out if you'd like to, by editing my question. ;)
One option is to use jBuilder, a popular gem maintained by the Rails team that provides a simple DSL (domain-specific language) allowing you to define JSON structures in your views.
https://github.com/rails/jbuilder
Using your existing method you could do it like this
controller
def index
#data = Product.sum_by_brand_category
end
views/products/index.json.jbuilder
json.array! #data.group_by(&:brand_id) do |grouped|
brand_id, category_data = grouped
json.id nil
json.brand_id brand_id
json.quantity category_data, :category_id, :count
end

Rails - How to add more fields for filter in searchkick?

In rails, I am using searchkick gem for search. When I am adding more fields for where clause then returning zero results.
Actually search is working for below method(User.rb),
searchkick word_start: [:name]
def initialize(name, limit = User::SUGGESTION_LIMIT, page = nil)
#name = name
#limit = limit
#page = page
#per_page = limit.to_i
end
query = {
match: :word_start,
fields: [{ emails: "exact" }, "name^5"],
misspellings: { prefix_length: 2 },
load: false
}
User.search(name, query).records
When I add condition like where: {active: false, inactive: true, deleted_at: nil} it returns no data.
query = {
match: :word_start,
where: {active: false, inactive: true, deleted_at: nil},
fields: [{ emails: "exact"}, "name^5"],
misspellings: { prefix_length: 2 },
load: false
}
Is there any mistake in above where condition? Please help me to solve this issue. I am using this gem for the first time.
Actually, the fields used in the where clause are indexed differently.
You have to define those fields as filterable:
searchkick word_start: [:name], filterable: [:active, :inactive, :deleted_at]
This should work.
BTW: You don't need both "active" and "inactive" attributes. If the "active" attribute is false, you know it is inactive.

find data for a particular month in rails mongodb

i am trying to query the data created in a particular month.
#events = Event.aggregates([
{
'$project': {
_id: 1,
created_at: 1,
'month': {'$month': '$created_at'}
},
},
{month: {'$match': 05}}
])
the aggregates is not giving me any result.
I get response in postman,
{
"count": 0,
"sum": null,
"avg": null,
"min": null,
"max": null
}
Personally I prefer collection.aggregate over aggregates. Secondly, the $match pipeline was wrong. Lastly, even though it does work in ruby, don't write 05 ans some languages might interpret that as octal rather than decimal.
#events = Event.collection.aggregate([
{
'$project': {
_id: 1,
created_at: 1,
'month': {'$month': '$created_at'}
},
},
{"$match" => {"month" => {'$eq': 5}}}
]).to_a

Ordering a Rails DataTable column by another value

I am building a helpdesk application. I have a model called TicketDetail, with a table which uses datatables to get its data via JSON. This is in order to periodically recalculate the time a ticket has been open. The time taken is formatted by a simple helper so it's in the format "dd:hh:mm", but it should be sorted by the time (stored as a decimal) multiplied by a weighting. Here's the datatables definition
var table = $('#ticket_details').DataTable({
order: [[ 8, "desc" ], [ 9, "desc" ], [ 2, "asc" ]],
stateSave: true,
deferRender: true,
ajax: $('#ticket_details').data('source'),
"columns": [
{ "data": "reference_number" },
{ "data": "location" },
{ "data": "title" },
{ "data": "parent", className: "hidden-md hidden-sm hidden-xs" },
{ "data": { _:"time_display.time", sort: "time_display.decimal_time"}},
{ "data": "created_by", className: "hidden-md hidden-sm hidden-xs" }
]
} );
setInterval( function () {
table.ajax.reload( null, false ); }, 60000 );
Here's a simplified sample record, where the ticket has been open 3 days and 6 hours, with a weighting of x2 (i.e. 3.25 * 2 = 6.5:
{
data: [
{
id: 140,
parent: null,
title: "[",
location: "Bond St",
ticket_sla: "16 Hours",
reference_number: "1606210001",
ticket_sla_weighting: 2,
time_display: {
time: "<span class = "label label-danger">03:06:00</span>",
decimal_time: 6.5
}
]
}
The problem is that the datatable sorts correctly if I display the decimal_time, but as soon as I put the formatted time in the class, it sorts simply by the number of days, immediately to the left of the colon. (So 03:06:00 and 03:18:00 would not get sorted properly).
For Date/Time sorting in DataTable You need to use it's Sorting plug-ins
For Example,
You need to include this js files :
//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.4/moment.min.js
//cdn.datatables.net/plug-ins/1.10.12/sorting/datetime-moment.js
and then, In your jQuery use this as
$.fn.dataTable.moment( 'HH:mm MMM D, YY' ); // Pass your date time format as param
For Deeper reference please check :
Sorting Plugins
Ultimate date / time sorting plugin

Resources