Rails getter and setter method issue? - ruby-on-rails-4.1

inside user.rb model
before_save :update_stripe
def update_stripe
if customer_id.nil? #line 1
if !stripe_token.present? #line 2
raise "Stripe token not present. Can't create account."
end
customer = Stripe::Customer.create(
:email => email, #line 3
:card => stripe_token, #line 4
)
self.role = "owner" #line 5
end
end
when i do 'role = "owner"' it doesn't sets 'role' setter but doing 'self.role = "owner"' sets it, in 'line 5', How ? Also 'customer_id', 'stripe_token', 'email' and 'stripe_token' getter works to get value without 'self' keyword in 'line 1', 'line 2', 'line 3' and 'line 4' resp. How ?

doing setter_method = val, means, you actually create a local variable inside your method and not accessing your setter, as mentioned in the link provided by Frederick Cheung.

Related

Whats the correct key/value Syntax to convert this Array with Symfony/XmlEncoder?

im building my request data as an array structure and want to use the symfony XmlEncoder to encode my Array to XML.
so i guess i got the fundamental part right, it looks like that for example:
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
];
the syntax im looking for encodes in the following format, with attribute and value:
<amount currency="EUR">1.99</amount>
i have the possiblity to use the # sign on an array key, but how to also fit in the value?
$request_object = [
"acc-id" => $all_credentials,
"req-id" => $request_guid,
"tran-type" => "spec-url"
"am" => ["#attr"=>"attrval"]
];
this should be
<am attr="attrval"/>
but how to write it that i can also set the value? like:
<am attr="attrval">VALUE</am>
help is much appreciated
Use '#' as the index for the scalar value.
I found it by looking through the tests for the encoder.
#src:https://github.com/symfony/serializer/blob/master/Tests/Encoder/XmlEncoderTest.php
#line: 196
public function testEncodeScalarRootAttributes()
{
$array = [
'#' => 'Paul',
'#eye-color' => 'brown',
];
$expected = '<?xml version="1.0"?>'."\n".
'<response eye-color="brown">Paul</response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}
...
#line: 234
public function testEncodeScalarWithAttribute()
{
$array = [
'person' => ['#eye-color' => 'brown', '#' => 'Peter'],
];
$expected = '<?xml version="1.0"?>'."\n".
'<response><person eye-color="brown">Peter</person></response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($array, 'xml'));
}

Why carbon helper not working and giving date-time error?

This application built in Lavavel 5. I had a table with day, month and year of birth value. I query the table using this query:
$tarikh = DB::table('itemregistrations')
->select('itemregistrations.lahir_dd', 'itemregistrations.lahir_mm', 'itemregistrations.lahir_yy')
->get();
dd($tarikh); produce this output:
Collection {#709 ▼
#items: array:1123 [▼
0 => {#681 ▼
+"lahir_dd": 9
+"lahir_mm": "June"
+"lahir_yy": 1979
}
1 => {#670 ▶}
2 => {#680 ▶}
3 => {#713 ▶}
I want to calculate the age using carbon and insert into the collection as age using array map:
$tarikh->map(function ($detail) {
$detail->age = \Carbon\Carbon::parse($detail->lahir_yy)->diffInYears();
return $detail;
});
But this error appear:
DateTime::__construct(): Failed to parse time string (0) at position 0 (0): Unexpected character
it is highlighting this code:
parent::__construct($time, $timezone);
if (isset($locale)) {
setlocale(LC_NUMERIC, $locale);
}
A friend had helped me using this fiddle and works fine ..but in the application, the error appear.
https://implode.io/i1GanD
Does anybody knows what is the cause of this conflict error? Tried to search on the same problem but still no solution. Thanks
The error had been erased by changing the code to:
$tarikh->map(function ($detail) {
$detail->Umur = \Carbon\Carbon::createFromFormat('Y',$detail->lahir_yy)->diffInYears();
return $detail;
});

Save geofield programmatically in Drupal 8

I have read in a lot of sources that I should use the geofield_compute_values() function when trying to programmatically save coordinates in Drupal.
However it does not work for me, that function is undefined in the Drupal 8.5.2 that I am using.
I've installed geofield using composer and I can use it as usual in the admin area and there are no problems with saving there.
Here are some examples I've tried with, the first example gives me undefined function geofield_compute_values() :
$geofield_data = geofield_compute_values([
'lat' => $lat,
'lon' => $lon,
], GEOFIELD_INPUT_LAT_LON);
$cbisProduct->set('field_koordinater', $geofield_data);
I have also tried this out with no successful result and no errors :
$geofield = [
'geom' => "POINT (" . $lon . " " . $lat . ")",
'geo_type' => 'point',
'lat' => $lat,
'lon' => $lon,
'left' => $lon,
'top' => $lat,
'right' => $lon,
'bottom' => $lat,
];
$cbisProduct->set('field_koordinater', $geofield);
Seems like you're trying to use the geofield_compute_values() function which was available in 7.x version, but not in 8.x
You should look into the wkt_generator service. i.e.
<?php $wktGenerator = \Drupal::service('geofield.wkt_generator'); ?>
I haven't tried this, but something like this should work:
<?php
$point = [
'lat' => $request->get('lat'),
'lon' => $request->get('lon'),
];
$value = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($point);
$node->field_koordinater->setValue($value);
Also, WktGeneratorTest.php and GeofieldItemTest.php files could be a good start to see how to use the service in your implementation.
This function is not available in Drupal 8. You have to rely on the basic GeofieldItem class that extends FieldItemBase. Also, as mentioned by oman, you can use WktGenerator to easily build points, polygons, etc.
Here a working example. Let's say your have an entity $cbisProduct with a multivalued geofield field_koordinater, and you want to set the first item with arbitrary lat/lon coordinates :
// Get geofield item
$geofield = $cbisProduct->get('field_koordinater')->get(0);
// Generate a point [lat, lon]
$coord = ['45.909621', '6.127147'];
$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);
// Calling this function will compute values AND assign geodata to the field instance
$geofield->setValue($point);
// You can read the computed geodata from the field
$geodata = $geofield->getValue();
//dpm($geodata);
// Explicitly set field data (needed if $geofield is not a reference)
$cbisProduct->set('field_koordinater', [$geodata]);
// Save entity
$cbisProduct->save();
Under the hood, GeofieldItem::setValue calls another method responsible to directly assign the computed values to the field instance :
# \Drupal\geofield\Plugin\Field\FieldType\GeofieldItem
protected function populateComputedValues() {
/* #var \Geometry $geom */
$geom = \Drupal::service('geofield.geophp')->load($this->value);
if (!empty($geom)) {
/* #var \Point $centroid */
$centroid = $geom->getCentroid();
$bounding = $geom->getBBox();
$this->geo_type = $geom->geometryType();
$this->lon = $centroid->getX();
$this->lat = $centroid->getY();
$this->left = $bounding['minx'];
$this->top = $bounding['maxy'];
$this->right = $bounding['maxx'];
$this->bottom = $bounding['miny'];
$this->geohash = substr($geom->out('geohash'), 0, GEOFIELD_GEOHASH_LENGTH);
$this->latlon = $centroid->getY() . ',' . $centroid->getX();
}
}
Note : You don't necessarily need WktGenerator for building points, as long as you know the geofield type and how geophp should handle it. For example, the following 2 statements are equivalent :
$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);
// is equivalent to
$point = GEOFIELD_TYPE_POINT . '(' . implode(' ', $coord) . ')');
But it is safer to rely on the WktGenerator especially with more complex data types.

Rails - Show/hide CSS class when parameter exist in URL

In my view I've a form where I only want to show inputs when its parameters appear in the URL:
= form_tag search_path, :method => :get do
= select_tag 'search[type]', options_for_select([['Publishers', 'publishers'], ['Editions', 'editions'], ['Contributors', 'contributors']], selected = (params[:search][:type] rescue nil)), prompt: "Search type", :required => "true"
= select_tag 'search[filter]', options_for_select([['Filter by', 'filter_by'], ['All', 'all']], selected = (params[:search][:filter] rescue nil)), prompt: "Select filter", :required => "true"
- invisible = params[:search][:value].present? ? '' : 'invisible'
= text_field_tag 'search[value]', (params[:id] || params[:search][:value] rescue nil), :required => "true", :class => "#{invisible}", :placeholder => "Type search"
My idea was control it showing a CSS class called "invisible" with display: none;, as above. But when I render the view it returns this Rails error in the line where I declare the "invisible":
undefined method `[]' for nil:NilClass
What's wrong?
This is because when the form is loading params[:search] is nil, and you're trying to call [:filter] on it, hence undefined method [] for nil.
There's various solutions, some nice, some not so nice, pick your favourite:
invisible = params[:search].try(:[], :value) ? '' : 'invisible'
invisible = params[:search] && params[:search][:value] ? '' : 'invisible'
invisible = (params[:search] || {})[:value] ? '' : 'inivisble'
invisible = (params[:search][:value] rescue nil) ? '' : 'invisible'
It is because params[:search] is nil and you are calling params[:search][:filter]
Try:
invisible = params[:search].present? ? (params[:search][:filter].present? ? '' : 'invisible') : ''
...
- invisible = params[:search].try(:[], :filter).blank? ? 'invisible' : ''
...

Drupal: Add onchange code to option_widgets in form_alter?

Do anyone know how I can add the following to form_alter?
Currently I've got two integer cck fields which are populated from sql using the php values command.
One field is for make, and the other is for model. Both makes and models are their own node types. Model has a node reference to make.
What I want to do on the Make drop down (CCK: INTEGER : SELECT), is on change, modify the contents of the model field. I've made my own bespoke form up, but it's too wieldy and want to use the basic drupal node edit forms.
Ideally I want to be able to pass this into the mix.
'#attributes' => array ('onchange'=> 'populatemodels(this,\'edit-field-model\')')
Does any one know of a way of doing this in the code?
In my form_alter adding the attribute doesn't produce any onchanges in the code:
#field_make (Array, 14 elements)
*
#type (String, 20 characters ) optionwidgets_select
*
#default_value (Array, 1 element)
o
0 (Array, 1 element)
+
value (String, 1 characters ) 8
*
#required (String, 1 characters ) 1
*
#columns (Array, 1 element)
o
0 (String, 5 characters ) value
*
#title (String, 4 characters ) Make
*
#description (String, 0 characters )
*
#delta (Integer) 0
*
#field_name (String, 10 characters ) field_make
*
#type_name (String, 3 characters ) car
*
#tree (Boolean) TRUE
*
#weight (String, 2 characters ) -1
*
#access (Boolean) TRUE
*
#count (Integer) 9
*
#attributes (Array, 1 element)
o
onchange (String, 39 characters ) populatemodels(this,'edit-field-model')
Thanks - Matt
I think I've had a break through.
cck/options_widgets.module
optionwidgets_select_process($element, $edit, &$form_state, $form) {
Additionally in my form_alter code, I added
drupal_add_js('sites/all/modules/adaptive/adaptive.js');
Which holds the populatemodels script
I've modded this code so that it passes attributes onto the next step
$element[$field_key] = array(
'#type' => 'select',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => isset($element['#required']) ? $element['#required'] : $field['required'],
'#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['multiple'],
'#options' => $options,
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
>>> '#attributes' => isset($element['#attributes']) ? $element['#attributes'] : NULL, <<
);
By adding '#attributes' => isset($element['#attributes']) ? $element['#attributes'] : NULL, the onchange now appears in the rendered code.

Resources