Can you change Multiple Properties with select helper? - ruby-on-rails

I'm using the following select helper:
f.select(:page_color, Orders::PAYMENT_TYPES ,:prompt => "Select a Box")
is it possible to change multiple columns with one selection? Say I want to change :page_color and :pay_method with the selection of "Check". Is this possible?
PAYMENT_TYPES = [
# Displayed stored in db
[ "Check", "check" ],
[ "Credit card", "cc" ],
[ "Purchase order", "po" ]
]

I think the cleanest thing would be to write a virtual attribute:
def paymethod=(value)
mapping = {
'check' => 'red',
'cc' => 'green',
...
}
self.page_color = mapping(value)
super
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.

LIKE Query on Postgres JSON array field in Rails

I have a table called messages which has a jsonB column called headers to store message headers. It looks like this:
[
{
"name":"Cc",
"field":{
"name":"Cc",
"value":"\"abc#gmail.com\" <abc#gmail.com>",
"length":null,
"charset":"UTF-8",
"element":null,
"address_list":{
"addresses":[
{
"data":{
"raw":"\"abc#gmail.com\" <abc#gmail.com>",
"error":null,
"group":null,
"local":"abc",
"domain":"gmail.com",
"comments":[
],
"display_name":"abc#gmail.com",
"obs_domain_list":null
},
"parsed":true
}
],
"group_names":[
]
}
},
"charset":"UTF-8",
"field_order_id":14,
"unparsed_value":"\"abc#gmail.com\" <abc#gmail.com>"
},
{
"name":"Message-ID",
"field":{
"name":"Message-ID",
"uniq":1,
"value":"<sdasdasd+tkiCVQ#mail.gmail.com>",
"length":null,
"charset":"UTF-8",
"element":{
"message_ids":[
"sdasdasd+tkiCVQ#mail.gmail.com"
]
}
},
"charset":"UTF-8",
"field_order_id":16,
"unparsed_value":"<sdasdasd+tkiCVQ#mail.gmail.com>"
},
{
"name":"Subject",
"field":{
"name":"Subject",
"value":"Re: test email",
"errors":[
],
"length":null,
"charset":"UTF-8",
"element":null
},
"charset":"UTF-8",
"field_order_id":19,
"unparsed_value":"Re: test email"
}
]
I want search records where 'name' = 'Subject' and 'unparsed_value' like %test% and return the result in Rails 6.0.2?
I'm trying the below mention code:
messages.where("headers #> '[{\"name\": \"Subject\"}, {\"unparsed_value\" LIKE \"%test%\"}]'")
But it's throwing error!
You can do a sub query to get the elements you need to compare and then use them in the where clause:
Message
.from(
Message.select("
id,
headers,
jsonb_array_elements(headers)->>'unparsed_value' AS unparsed_value,
jsonb_array_elements(headers)->>'name' AS name
"), :t
)
.select('t.*')
.where("t.name = 'Subject' AND t.unparsed_value LIKE '%test%'")
The query you need looks like this:
SELECT * FROM messages WHERE
(SELECT true FROM jsonb_to_recordset(messages.headers)
AS x(name text, field jsonb)
WHERE name = 'Subject'
AND field->>'unparsed_value' LIKE '%test%');
Does this give you the result you're looking for?

split multi-dimensional array in ruby

I am trying to parse json data in ruby my desired output is:
var events = { '01-01-2018' :
[ {content: 'Psalm 2', allDay: true},
{content: 'by ToddWagner', allDay: true}
],
'01-02-2018' :
[ {content: 'Psalm 2', allDay: true},
{content: 'by ToddWagner', allDay: true}
]
}
what I get is
var events = [
{"2017-11-03":
[ {"content":"Romans 14:5-12","allDay":true},
{"content":"by Micah Leiss","allDay":true}
]
},
{"2017-11-06":
[{"content":"Romans 14:13","allDay":true},
{"content":"by Sarah Thomas","allDay":true}
]
}
]
I tried something like
data = []
raw_data['entries'].each do |entry|
data << {entry_date => [
{
"content" => entry.title,
"allDay" => true,
},
{
"content" => entry.writer,
"allDay" => true,
},
]
}
end
data.to_json
but I didn't get desired results, I have also tried data.pop data.shift.
Ruby implementation would look like:
data = raw_data['entries'].map do |entry|
[entry.date, [entry.title, entry.writer].map do |content|
{content: content, allDay: true}
end]
end.to_h
First of all, are adding fields to your array data, as I can see from your desired output, you need a hash.
You have to create the hash, not the array:
data = {}
and then in your loop
raw_data['entries'].each do |entry|
add it like that
data[entry_date] = [
{
"content" => entry.title,
"allDay" => true,
},
{
"content" => entry.writer,
"allDay" => true,
},
]
(I am not where do you declare entry_date in your example so it might be entry.date)
I can't tell from your example if entry date is unique or not(and I think it's not) make sure you add to hash, because you might overwrite it.
You can do something like this if entry date isn't unique
data[entry.date] ||= []
data[entry.date] << {hash_you_need}

Yii2 : How to change URL in Action Column Grid View?

I want to change url in action view, from view to viewdaily, viewweekly and viewmonthly, what should i do?
[
'class' => 'yii\grid\ActionColumn',
],
The simplest way is not create/use ActionColumn, instead you can use raw-column and show there what you want:
[
'attribute' => 'some_title',
'format' => 'raw',
'value' => function ($model) {
return 'your Text';
},
],

Replace transpose method?

I have the following code:
table([
["UnitID", "First Name", "NPS Score", "Comments"],
*[invite_unitid_arr, invite_name_arr, nps_score_integers_final, comment_arr]
.transpose.reject{ |x| x[3].empty? }
], :position => :center, :column_widths => {0 => 50, 1 => 60, 2 => 60, 3 => 40, 4 => 150}) do
row(0).style :background_color => 'C0C0C0'
end
I am calling transpose on an array of arrays. I am refactoring this code and I now have an array of model objects:
array = Model.all
How can I rewrite the above, saying "Loop through each model (Model1, Model2, etc.) and create a row with the attributes unit_id,first_name,nps_score,comment like so: Model1[:unit_id],Model1[:first_name],Model1[:nps_score],Model1[:comment]"
If I understand correctly, you have an array of objects like this:
my_models = [ <MyModel id: 1, unit_id: 123, first_name: "Xxx", nps_score: 100, ...>,
<MyModel id: 2, unit_id: 456, first_name: "Yyy", nps_score: 200, ...>,
...
]
And you want an array like this:
[ [ "UnitID", "First Name", "NPS Score", "Comments" ],
[ 123, "Xxx", 100, "..." ],
[ 456, "Yyy", 200, "..." ],
...
]
All you really need to do is this:
headers = [ "UnitID", "First Name", "NPS Score", "Comments" ]
data = my_models.map do |model|
[ model.unit_id, model.first_name, model.nps_score, model.comments ]
end
rows = [ headers, *data ]
Or...
data = my_models.map do |model|
model.attributes.values_at(:unit_id, :first_name, :nps_score, :comments)
end
(Either way you could make this a one-liner, but mind your code's readability.)
Of course, it's always best to select only the columns you're going to use, so you could just do this (adding whatever where, order etc. calls you need):
my_models = MyModel.select([ :unit_id, :first_name, :nps_score, :comments ]).where(...)
data = my_models.map(&:attributes)
# => [ [ 123, "Xxx", 100, "..." ],
# [ 456, "Yyy", 200, "..." ],
# ...
# ]
In Rails 4 the pluck method takes multiple arguments, making this even easier:
data = MyModel.where(...).pluck(:unit_id, :first_name, :nps_score, :comments)
# => [ [ 123, "Xxx", 100, "..." ],
# [ 456, "Yyy", 200, "..." ],
# ...
# ]
I am not entirely sure what are you trying to achieve here, but it seems that you are looking for pluck method. Since rails 4 it allows you to pluck multiple columns at once (and by default will pluck all columns). So it seems that:
Model.pluck(:unit_id, :first_name, :nps_score, :comment)
Is what you are looking for - and is actually much better as it is not instantiating new objects and makes just one call to db. . It will return 2d array, one row for each model. If you rather prefer have different values of same column, add transpose on the above.

Resources