How to assign column name from variable - ruby

I want to assign a value to a table column. The column selected needs to be based on a variable. How do you do this?
If #language = "german" than I want to assign #new_word.german = string
#new_word = Word.new
#new_word.german = string
#new_word.save
So how would I assign .german using #language? #new_word.#language :/

x = "german"
#new_word.send("#{x}=", "some value")
#new_word[x] = "some value" # may end up skipping overrides/callbacks, etc though. check the docs.

Related

Parameter options for User Defined Functions in PowerQuery

Hi i have been trying to make a user defined function that allows the user to select the values which the function will use from a list.
I have tried setting the parameter i want as a list to type list in my function but this only seems to accept columns rather than a list of values a user can select from.
let
ListOfDays = {1.1,0.5,2,3,1},
DayOfTheWeek = (Day as list, HoursWorked ) =>
let
Earnings = Day * HoursWorked
in
Earnings
in
DayOfTheWeek
What i would like is for me to allow the user to select a single value from the ListOfDays list. I used typed list within my function parameters so that it can give the user a dropdown list kind of option.
I believe this is the relevant documentation you are looking for:
github.com/microsoft/DataConnectors/docs/function-docs.md: Adding Function Documentation
In particular, look at the definition for Documentation.AllowedValues:
List of valid values for this parameter. Providing this field will change the input from a textbox to a drop down list. Note, this does not prevent a user from manually editing the query to supply alternate values.
This (and other Documentation fields) are part of the meta typing of the function arguments. Scroll down to the code snippet which shows how to use them:
[DataSource.Kind="HelloWorldWithDocs", Publish="HelloWorldWithDocs.Publish"]
shared HelloWorldWithDocs.Contents = Value.ReplaceType(HelloWorldImpl, HelloWorldType);
HelloWorldType = type function (
message as (type text meta [
Documentation.FieldCaption = "Message",
Documentation.FieldDescription = "Text to display",
Documentation.SampleValues = {"Hello world", "Hola mundo"}
]),
optional count as (type number meta [
Documentation.FieldCaption = "Count",
Documentation.FieldDescription = "Number of times to repeat the message",
Documentation.AllowedValues = { 1, 2, 3 }
]))
as table meta [
Documentation.Name = "Hello - Name",
Documentation.LongDescription = "Hello - Long Description",
Documentation.Examples = {[
Description = "Returns a table with 'Hello world' repeated 2 times",
Code = "HelloWorldWithDocs.Contents(""Hello world"", 2)",
Result = "#table({""Column1""}, {{""Hello world""}, {""Hello world""}})"
],[
Description = "Another example, new message, new count!",
Code = "HelloWorldWithDocs.Contents(""Goodbye"", 1)",
Result = "#table({""Column1""}, {{""Goodbye""}})"
]}
];
HelloWorldImpl = (message as text, optional count as number) as table =>
let
_count = if (count <> null) then count else 5,
listOfMessages = List.Repeat({message}, _count),
table = Table.FromList(listOfMessages, Splitter.SplitByNothing())
in
table;
They also provide a screenshot of what this should look like when invoked:
If the user is able to open up the Query Editor, then they can choose a Day parameter from a dropdown list and have this automatically apply to the query.
You would create the parameter from the Manage Parameters > New Parameter menu
The drop-down at the upper right of the image is how the user would select the choice.
Your User Defined Function fn_DayOfTheWeek would be the following:
let
DayOfTheWeek = (Day as number, HoursWorked as number) =>
let
Earnings = Day * HoursWorked
in
Earnings
in
DayOfTheWeek
Note that Day is a number, not a list. You want to choose from a list, not pass a list into the function.
Now you can invoke your function with your parameter to actually produce a result.
let
Source = fn_DayOfTheWeek(Day, <HoursWorked value here>)
in
Source
This result will update when you change the parameter.
As you can see, whether a user has access to the Query Editor is rather a critical question for this approach. I'm not sure if it's possible to somehow set a parameter directly within a custom connector dialog box or not but this should be equivalent in functionality.

one2many field get row number

I have a module contain one2many filed.
while I create data line in this o2m field, I'd like to append a row number to it.
I have try some method that I found in forum, like this link.
but since I have no function called _onchange_partner_id() , I don't know how to use it.
or this link .
but it seems like an old version method that I can't get well.
class YcWeight(models.Model):
_name = "yc.weight"
customer_detail_ids = fields.One2many("yc.weight.details", "name", "customer details")
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
the "no" is a field that I want to show number of row count.
my problem is :
how can I get get the number of rows?
since onchage decorated function can't get data from db.
I find a solution by myself and it is simple:
use depends decorator.
class YcWeightDetails(models.Model):
_name = "yc.weight.details"
name = fields.Many2one("yc.weight", "weight detail list", ondelete="cascade")
no = fields.Integer("row number")
compuute_no = fields.Integer("invisible field", compute= "_get_row_no")
create a field "compuute_no" to compute.
#api.depends("compuute_no")
def _get_row_no(self):
if self.ids:
count =1
for rec in self:
weight_id = self.env['yc.weight.details'].search([('id','=', rec.id)])
weight_id.write({'no': count})
count+=1
or overwrite create method
#api.model
def create(self, vals):
main_key = self.env["yc.weight"].search([], order="id desc", limit=1).id
item_key = vals["name"]
if item_key and main_key == item_key:
number = len(self.env["yc.weight.details"].search([("name", "=", item_key)]))
vals.update({"no": number + 1})
return super(YcWeightDetails, self).create(vals)
hope it can help you.

How can I create a complete_name field in a custom module for a custom hierarchy like used on product categories in Odoo?

I'm trying to create a field “complete_name” that displays a hierarchy name similar to whats done on the product categories grid but I can't seem to get it to work. It just puts Odoo in an endless loading screen when I access the relevant view using the new field "complete_name".
I have tried to copy the code used in addons/product/product.py and migrate to work with Odoo 9 API by using compute instead of .function type but it did not work.
Can someone help me understand whats wrong? Below is my model class which works fine without the complete_name field in my view.
class cb_public_catalog_category( models.Model ):
_name = "cb.public.catalog.category"
_parent_store = True
parent_left = newFields.Integer( index = True )
parent_right = newFields.Integer( index = True )
name = newFields.Char( string = 'Category Name' )
child_id = newFields.One2many( 'catalog.category', 'parent_id', string = 'Child Categories' )
complete_name = newFields.Char( compute = '_name_get_fnc', string = 'Name' )
def _name_get_fnc( self ):
res = self.name_get( self )
return dict( res )
Your compute function is supposed to define the value of an attribute of your class, not return a value. Ensure the value you are assigning complete_name is a string.
Also name_get() returns a tuple. I am not sure if you really want a string representation of this tuple or just the actual name value.
Try this
def _name_get_fnc( self ):
self.complete_name = self.name_get()[1]
If you really want what is returned by name_get() then try this.
def _name_get_fnc( self ):
self.complete_name = str(self.name_get())
If you are still having issues I would incorporate some logging to get a better idea of what you are setting the value of complete_name to.
import logging
_logger = logging.getLogger(__name__)
def _name_get_fnc( self ):
_logger.info("COMPUTING COMPLETE NAME")
_logger.info("COMPLETE NAME: " + str(self.name_get()))
self.complete_name = self.name_get()
If this does not make it apparent what the issue is you could always try statically assigning it a value in the off chance that there is a problem with your view.
def _name_get_fnc( self ):
self.complete_name = "TEST COMPLETE NAME"
After further review I think I have the answer to my own question. It turns out as with a lot of things its very simple.
Simply use "_inherit" and inherit the product.category
model. This gives access to all the functions and fields
of product.category including the complete_name field
and computes the name from my custom model data. I was
able to remove my _name_get_func and just use the inherited
function.
The final model definition is below. Once this
update was complete I was able to add a "complete_name" field
to my view and the results were as desired!
class cb_public_catalog_category( models.Model ):
_name = "cb.public.catalog.category"
_inherit = 'product.category'
_parent_store = True
parent_left = newFields.Integer( index = True )
parent_right = newFields.Integer( index = True )
name = newFields.Char( string = 'Category Name' )
child_id = newFields.One2many( 'catalog.category', 'parent_id', string = 'Child Categories' )

Ruby: Convert String to Symbol during String Interpolation

I am looping over a block of code, each time increasing variable "filter_index", from 1, to 2, to 3... etc.
I'd like to use this variable to access the different symbols:
filter1_field_name,
filter2_field_name,
filter3_field_name
#filter1_field_name = "Region"
#filter2_field_name = "Country"
#filter3_field_name = "City"
SELECT_STATEMENT = "GROUP BY "
numberOfFilters = 3
filter_index = 1
numberOfFilters.times do #Number of iterations
filter_field_name = "#filter#{filter_index.to_s}_field_name"
SELECT_STATEMENT.sub! "GROUP BY", "AND #{filter_field_name.to_sym} GROUP BY"
filter_index += 1
end
puts SELECT_STATEMENT
This results in
AND #filter1_field_name AND #filter2_field_name AND
#filter3_field_name GROUP BY
But the desired result is
AND Region AND Country AND City GROUP BY
I'm wondering why filter_field_name.to_sym is not working (or rather, what I'm doing wrong)?
You can use instance_variable_get function to get variable value.
Replace the line
filter_field_name = "#filter#{filter_index.to_s}_field_name"
with
filter_field_name = instance_variable_get("#filter#{filter_index.to_s}_field_name")
EDIT:
I think you can put the field names into an array and concat the values with join method.
fields = ['Region','Country','City']
fields.join(' AND ')
you can use instance_variable_get or eval
filter_field_name = instance_variable_get("#filter#{filter_index.to_s}_field_name")
or
filter_field_name = eval("#filter#{filter_index.to_s}_field_name")

Set array elements (string) as variable name in Ruby

I have the following array, that I use to later write the header on an Excel file.
fields = ["fileName", "type", "id"]
And then I have the following code that reads values from an XML:
filename = xml.xpath('//path/filename').text
type = xml.xpath('//path/type').text
id = xml.xpath('//path/id').text
The I iterate the initial array (fields) in order to set the Excel cells to the values extracted in the previous step:
row = 2
c = 1
fields.each do |content|
ws.Cells(row,c).Value = content
c = c + 1
I'm trying to have the array's (fields) contents to variable names instead of strings in order to be able to reuse the head fields.
Can anyone recommend a way of making it possible?
This sounds like you need to use a Hash to associate field names to the values you extracted:
fields = {
"fileName" => xml.xpath('//path/filename').text,
"type" => xml.xpath('//path/type').text,
"id" => xml.xpath('//path/id').text
}
row=2
c=1
fields.each do |key,value|
ws.Cells(row,c).Value = value
c=c+1
end

Resources