I have an incoming post data from js like this
[form] => Array (
[name] => 'a form'
[type] => 'form'
...
[children] => Array (
[0] =>
[1] =>
[2] => Array(
[title] => 'first'
[order] => '1'
...
}
[3] => Array(
[title] => 'second'
[order] => '2'
...
)
...
)
...
)
and rules like
[
'form.name' => 'required|string',
'form.type' => 'required|string',
...
'form.children.*.title' => 'requered|string'
'form.children.*.order' => 'requered|integer'
...
]
What is the best way to completely exclude/skip the form.children arrays that are empty and process the ones with data?
Try this:
[
'form.name' => 'required|string',
'form.type' => 'required|string',
...
'form.children.*.title' => 'sometimes|string'
'form.children.*.order' => 'sometimes|integer'
...
]
Sometimes means, if there is something, follow the next rule(s).
https://laravel.com/docs/8.x/validation#validating-when-present
Addition:
For more complex situations, f.ex. you are not interested in an order value if there is no title, makes sense right? Try this:
[
'form.name' => 'required|string',
'form.type' => 'required|string',
...
'form.children.*.title' => 'sometimes|string'
'form.children.*.order' => 'exclude_if:form.children.*.title,null|integer'
...
]
I have never tested/used this on arrays though.
I managed to completely remove the empty arrays just by filtering them out of the request with laravel's prepareForValidation() method and array_filter(). Worked great for me.
protected function prepareForValidation()
{
$this->merge([
"form" => [
"children" => array_filter($this->form["children"])
]
]);
}
#DimitriMostrey's answer worked as well. His answer is a shorter solution without an additional method. Will accept his answer so anyone facing a similar situation can pick the one that suits the most.
I have DB in SQL Server and I execute it with Laravel. However, I get the following error.
ParseError syntax error, unexpected ' ' (T_STRING), expecting ']'
I am trying to figure out why this is happening. It shows this syntax error, but I don't understand it. I can't find a typo. I read and update SQL Server database. Is there a bug or something?
$siswa_regNo = DB::table('upload_tbpendaftaran$')
->select('Reg_No', 'F_Name',
'N_Name',
'Place',
'Birthday',
'BirthID',
'Gender',
'Bloods',
'Glass',
'Height',
'Weight',
'Child_No',
'Child_Qty',
'School_Code',
'School_Name',
'School_Address',
'School_Distric',
'School_Distric_Desc',
'School_City',
'School_City_Desc',
'School_Province',
'School_Province_Desc',
'School_NEM_Avg',
'School_STTB',
'Certificate_ID',
'Stay',
'Stay_Address',
'Stay_RT',
'Stay_RW',
'Stay_Village',
'Stay_Distric',
'Stay_Distric_Desc',
'Stay_City',
'Stay_City_Desc',
'Stay_Province',
'Stay_Province_Desc',
'Stay_Phone',
'Stay_HP',
'Stay_Postal',
'Stay_Longitude',
'Stay_Latitude',
'Home_Address',
'Home_RT',
'Home_RW',
'Home_Village',
'Home_Distric',
'Home_Distric_Desc',
'Home_City',
'Home_City_Desc',
'Home_Province',
'Home_Province_Desc',
'Home_Postal',
'Home_Phone',
'Home_HP',
'Home_HP2',
'Home_Longitude',
'Home_Latitude',
'EMail',
'Email_Parent',
'Email_Parent2',
'ID_Cards',
'Distance',
'Time_HH',
'Time_MM',
'TransportID',
'TransportDesc',
'Remarks',
'NISN',
'ExamUNNo')
->orderBy('Reg_No')
->get();
foreach ($siswa_regNo as $s) {
DB::table('Registration')
->where('Reg_No', $s->Reg_No)
->update([
'F_Name' => $s->F_Name,
'N_Name' => $s->N_Name,
'Place' => $s->Place,
'Birthday' => $s->Birthday,
'BirthID' => $s->BirthID,
'Gender' => $s->Gender,
'Religion' => $s->Religion,
'Citizen' => $s->Citizen,
'FamilyID' => $s->FamilyID,
'Bloods' => $s->Bloods,
'Glass' => $s->Glass,
'Height' => $s->Height,
'Weight' => $s->Weight,
'Child_No' => $s->Child_No,
'Child_Qty' => $s->Child_Qty,
'School_Code' => $s->School_Code,
'School_Name' => $s->School_Name,
'School_Address' => $s->School_Address,
'School_Distric' => $s->School_Distric,
'School_Distric_Desc' => $s->School_Distric_Desc,
'School_City' => $s->School_City,
'School_City_Desc' => $s->School_City_Desc,
'School_Province' => $s->School_Province,
'School_Province_Desc' => $s->School_Province_Desc,
'School_NEM_Avg' => $s->School_NEM_Avg,
'School_STTB' => $s->School_STTB,
'Certificate_ID' => $s->Certificate_ID,
'Stay' => $s->Stay,
'Stay_Address' => $s->Stay_Address,
'Stay_RT' => $s->Stay_RT,
'Stay_RW' => $s->Stay_RW,
'Stay_Village' => $s->Stay_Village,
'Stay_Distric' => $s->Stay_Distric,
'Stay_Distric_Desc' => $s->Stay_Distric_Desc,
'Stay_City' => $s->Stay_City,
'Stay_City_Desc' => $s->Stay_City_Desc,
'Stay_Province' => $s->Stay_Province,
'Stay_Province_Desc' => $s->Stay_Province_Desc,
'Stay_Phone' => $s->Stay_Phone,
'Stay_HP' => $s->Stay_HP,
'Stay_Postal' => $s->Stay_Postal,
'Stay_Longitude' => $s->Stay_Longitude,
'Stay_Latitude' => $s->Stay_Latitude,
'Home_Address' => $s->Home_Address,
'Home_RT' => $s->Home_RT,
'Home_RW' => $s->Home_RW,
'Home_Village' => $s->Home_Village,
'Home_Distric' => $s->Home_Distric,
'Home_Distric_Desc' => $s->Home_Distric_Desc,
'Home_City' => $s->Home_City,
'Home_City_Desc' => $s->Home_City_Desc,
'Home_Province' => $s->Home_Province,
'Home_Province_Desc' => $s->Home_Province_Desc,
'Home_Postal' => $s->Home_Postal,
'Home_Phone' => $s->Home_Phone,
'Home_HP' => $s->Home_HP,
'Home_HP2' => $s->Home_HP2,
'Home_Longitude' => $s->Home_Longitude,
'Home_Latitude' => $s->Home_Latitude,
'EMail' => $s->EMail,
'Email_Parent' => $s->Email_Parent,
'Email_Parent2' => $s->Email_Parent2,
'ID_Cards' => $s->ID_Cards,
'Distance' => $s->Distance,
'Time_HH' => $s->Time_HH,
'Time_MM' => $s->Time_MM,
'TransportID' => $s->TransportID,
'TransportDesc' => $s->TransportDesc,
'Remarks' => $s->Remarks,
'NISN' => $s->NISN,
'ExamUNNo' => $s->ExamUNNo
]);
}
I am very confused, please help.
in second FOREACH, when you are getting data from DB you should add ->first() or ->get() in the last.
foreach ($siswa_regNo as $s) {
DB::table('Registration')
->where('Reg_No', $s->Reg_No)
->first() // this line added
->update([
'F_Name' => $s->F_Name,
'N_Name' => $s->N_Name,
'Place' => $s->Place,
.
.
.
]);
}
or if you want to use ->get() you should foreach to this also...
I'm currently adding filebeat support for services we provide;
For every service we have several log files I would like to track;
I have 1 common filebeat recipe and I'm distinguishing between the different services' logs in different attributes .rb files;
In those I have a separate definition per log;
All definitions have the same "fileds" configuration;
Can I add it to someplace to be used by all configurations?
My structure:
cookbooks
common
recipes
filebeat.rb
services
attributes
service1.rb
service2.rb
The content of servicesX.rb has the following definitions:
access_log = {
'paths' => ['TBD'],
'input_type' => 'log',
'fields' => {
'hostname' => node["opsworks"]["instance"]["hostname"],
'customer' => node["opsworks"]["instance"]["layers"][0],
'internal_ip' => node["opsworks"]["instance"]["private_ip"],
'ec2id' => node["opsworks"]["instance"]["aws_instance_id"],
'os' => node["opsworks"]["instance"]["os"],
'instance_type' => node["opsworks"]["instance"]["instance_type"] },
'fields_under_root' => true
}
audit_log = {
'paths' => ['TBD'],
'input_type' => 'log',
'fields' => {
'hostname' => node["opsworks"]["instance"]["hostname"],
'customer' => node["opsworks"]["instance"]["layers"][0],
'internal_ip' => node["opsworks"]["instance"]["private_ip"],
'ec2id' => node["opsworks"]["instance"]["aws_instance_id"],
'os' => node["opsworks"]["instance"]["os"],
'instance_type' => node["opsworks"]["instance"]["instance_type"]
},
'fields_under_root' => true
}
How can I extract
'fields' => {
'hostname' => node["opsworks"]["instance"]["hostname"],
'customer' => node["opsworks"]["instance"]["layers"][0],
'internal_ip' => node["opsworks"]["instance"]["private_ip"],
'ec2id' => node["opsworks"]["instance"]["aws_instance_id"],
'os' => node["opsworks"]["instance"]["os"],
'instance_type' => node["opsworks"]["instance"]["instance_type"]
Someplace in the same file (servicesX.rb) so to be used by all log files definitions?
Note: I'm a ruby novice :/
Thank you!!
After feedback and clarification in comments below, OP seems to want to DRY the code and re-use a fields definition.
Simplest is to store it in a variable and then use that:
fields = {
'hostname' => node["opsworks"]["instance"]["hostname"],
'customer' => node["opsworks"]["instance"]["layers"][0],
'internal_ip' => node["opsworks"]["instance"]["private_ip"],
'ec2id' => node["opsworks"]["instance"]["aws_instance_id"],
'os' => node["opsworks"]["instance"]["os"],
'instance_type' => node["opsworks"]["instance"]["instance_type"]
}
audit_log = {
'paths' => ['TBD'],
'input_type' => 'log',
'fields' => fields
}
This, however, may cause issues with how node is set. It really depends on the flow of the rest of your script. In chef (assuming this is about chef) a node is the context on which the script runs, so setting the fields too early might give issues when that node is used much later:
fields = { hostname: node["opsworks"]["instance"]["hostname"] }
# ... do lots of stuff, like fetching, preparing, connecting and whatnot.
fields # now contains the `node` values as set before connecting etc.
If this is an issue, a better option would be to define a method that returns the fields from a passed-in node:
def fields(node)
{
'hostname' => node["opsworks"]["instance"]["hostname"],
'customer' => node["opsworks"]["instance"]["layers"][0],
'internal_ip' => node["opsworks"]["instance"]["private_ip"],
'ec2id' => node["opsworks"]["instance"]["aws_instance_id"],
'os' => node["opsworks"]["instance"]["os"],
'instance_type' => node["opsworks"]["instance"]["instance_type"]
}
end
Or, cleaned up:
def fields(node)
instance = node["opsworks"]["instance"]
{
hostname: instance["hostname"],
customer: instance["layers"][0],
internal_ip: instance["private_ip"],
ec2id: instance["aws_instance_id"],
os: instance["os"],
instance_type: instance["instance_type"]
}
end
Then use that function:
audit_log = {
'paths' => ['TBD'],
'input_type' => 'log',
'fields' => fields(node)
}
After my research: The benefits of the implementation does not justify the time invested;
Leaving it;
So here is the code that I have:
resp = client.call(
:producer_query,
message: {
'cmn:Carrier' => '',
'cmn:ProducerCriteria' => { 'cmn:EntityType' => 'Individual',
'cmn:CustomerId' => 5555,
:attributes! => {'CustomerId' => {'type' => 'AGENTCD'}}},
'cmn:SectionConfiguration' => { 'cmn:SectionType' => 'Associations', :attributes! => {'cmn:SectionType' => {'activeOnly' => 'false'}}},
:attributes! => { 'cmn:Carrier' => { "id" => 55555 }}
}
) do
wsse_auth ENV['ID'], ENV['PASSWORD'], :digest
end
And it produces something that looks like:
<soapenv:Body>
<cmn:ProducerQuery>
<cmn:Carrier id="5555"/>
<cmn:ProducerCriteria>
<cmn:EntityType>Individual</cmn:EntityType>
<cmn:CustomerId>55555</cmn:CustomerId>
</cmn:ProducerCriteria>
<cmn:SectionConfiguration>
<cmn:SectionType activeOnly="false">Associations</cmn:SectionType>
</cmn:SectionConfiguration>
</cmn:ProducerQuery>
</soapenv:Body>
I've added in the 'cmn' to everything, but the ProducerQuery to make it match what I think it should be. However, I think it really should read 'tran' instead. I can control the 'cmn' for everything but the part that reads <cmn:ProducerQuery>. How can I make it read <cmn:ProducerQuery>?
I'm using the Axlsx gem (https://github.com/randym/axlsx) for generating excel files. I want to refactor my code so that I have a wrapper around the gem just in case I want to switch gems.
Going through this reminds me of the Adapter design pattern. However, there are just so many objects nested underneath the main Package object that I am getting confused as to how to actual create an adapter for it. Ex:
You create a Package object
You access the Workbook within this Package objet
You access the Sheet from the Workbook object, and vice versa
Here are some of my classes:
class ReportGenerator::Base
...
def create_workbook
...
#package = Axlsx::Package.new <---------------------------
#workbook = #package.workbook <---------------------------
#workbook.use_shared_strings = true
end
class Sheet::Base
def initialize(workbook, question, options = {})
...
#sheet = workbook.add_worksheet(:name => sheet_name) <---------------------------
end
def styles
#styles ||= {
"title" => #sheet.workbook.styles.add_style(:sz => 20, :b => true, :alignment => { :wrap_text => true }),
"bold" => #sheet.workbook.styles.add_style(:b => true),
"header" => #sheet.workbook.styles.add_style(:fg_color => "FFFFFF", :bg_color => "ff3333", :sz => 12, :b => true, :alignment => {:horizontal => :center}, :border => {:style => :thin, :color => "FFFFFF"}),
"subheader" => #sheet.workbook.styles.add_style(:fg_color => "FFFFFF", :bg_color => "ff3333", :sz => 12, :b => true, :alignment => {:horizontal => :center}),
"subheader_border_left" => #sheet.workbook.styles.add_style(:fg_color => "FFFFFF", :bg_color => "ff3333", :sz => 12, :b => true, :alignment => {:horizontal => :center}, :border => {:style => :thin, :color => "FFFFFF", :edges => [:left]}),
"blue_link" => #sheet.workbook.styles.add_style(:fg_color => '0000FF'),
"wrap_text" => #sheet.workbook.styles.add_style(:alignment => { :wrap_text => true, :horizontal => :left }),
"percentage" => #sheet.workbook.styles.add_style(:format_code => "0.00%")
}
end
Here's my first stab:
class ExcelWriter
def initialize
#package = Axlsx::Package.new
end
def workbook
#package.workbook
end
# starting to feel like it's not doable within one class..?
end
There are so many classes involved that it feels like I can't wrap everything into one adapter? Or maybe I'm doing it wrong? Any tips would be welcomed.
Focus on what you're actually using and not on existing infrastracture of Axlsx gem. This way you may combine work of several Axlsx objects into 1 method call.
I don't know what you're actually using, so it's hard for me to say which objects do you need.