DataMapper: Set default validations on custom types - datamapper

I just wrote a custom DM type to help me with this thing. Inherits from String, and all that jazz. Just now I'd like to have a default validation. So, something that I as a user don't need to define, it is just implicitly there. For instance, for an attribute of Boolean type, if you pass something other than true or false, it invalidates it's object. I'd like to have something like that. Do you know whether this is possible, and where in the architecture to insert it at best?

I think you can add it in the dump method, for example
def dump(value)
if valid_type?(value)
value
else
raise "Invalid type specified"
end
end
def valid_type?(value)
#your validation code
end
Other way is using one of the dm-validations
In your case it would be
#Skipping class Definition
property :something, Your_dm_type
validates_with_block :something do
if condition
true
else
[false, "Invalid property specified"]
end
Or other validations as per the requirement

Related

Passing parameters from form to controller using RoR

I am new to RoR development and am a little confused about how parameters are passed from a HTML view to the controller. I have seen a few examples online which use a private method like this:
private
def message_params
params.require(:message).permit(:content)
end
I have been looking for some clarification online as to what this method does and how it works, but I only encounter posts/articles which use the method rather than explain what it does.
I was hoping someone could explain how the method takes(/filters?) values passed via the form via a POST request, what the require and permit keywords mean and how would i change this method to fit my own use.
For example if i needed to get data about a new book would i do this:
private
def book_params
params.require(:book_name).require(:ISBN).require(:Author).permit(:Illustrator)
end
Would the above be valid given that my book object has those fields?
Any clarification would be appreciated.
Thank you.
here is some info (I'm using your sample model Book and BookController), that probably can help you more understand
when you submit form, rails automatically called create method, inside create method you will see Book.new(book_params), book_params will call private method and will check which field allowed, if there is another field that submitted but not listed inside your permit block then it will be not passed along to save command
class BooksController < ApplicationController
def create
#book = Book.new(book_params)
if #book.save
flash[:success] = 'Data save successfully'
redirect_to books_path
else
render :new
end
end
private
def book_params
params.require(:book).permit(
:book_name,
:isbn,
:author,
:illustrator)
end
end
This kind of function is used to whitelist params - ie say you have a message model, and through the controller actions you should only be able to change the content. Maybe there is also an author field - but even if someone were to pass that through the form, you would not want to update it.
params.require(:message)
Will return to you params[:message]. permit means you are allowing only the content field through.
See: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters
I would need to see your model setup, but I would assume given a book model you'd want something more akin to:
params.require(:book).permit(:illustrator, :author, :isbn)

Boolean not working in Logic App condition

What is the proper way to use booleans in Logic Apps conditions? If the bool is set to true, the workflow should continue in the YES branch but I allways end up with this error-message :
ActionBranchingConditionNotSatisfied. The execution of template action 'HTTP' skipped: the branching condition for this action is not satisfied.
{
"reservations": {
"sendBooking": true
}}
If you switch to "Advanced mode" in the condition card, you should see the expression looks like #equals(triggerBody()?['sendBooking'], 'true')
Update it to #equals(triggerBody()?['sendBooking'], true) and your logic should work.
This is because, by default, we treat true as a string, but in this case it needs to be a Boolean.
Workaround above should unblock you, I will discuss with the team to see how can be better handle this scenario.
The workaround was to remove the '' in code view, then I was able to save the logic app. But the error still exists in the designer.

Mysql VB.NET: Hiding column from datagridview null exception error (column is not null)

I have a datagridview that is populated with the data I retrieved from the database (mysql)
When I try to hide the column or change the column header text, this exception was thrown:
Object reference not set to an instance of an object.
or
Index was out of range. Must be non-negative and less than the size of
the collection. Parameter name: index
with this simple code:
gridjobs.Columns(0).Visible = False
gridjobs.Columns("JOB_NO").HeaderText = "JOB NO."
I can tell you that the datagrid is not null, it was working before but suddenly this error popped up. I tried searching the net but still no luck in fixing this error. Everything is working, except this. Is there something wrong with my code?
based on google
Object reference not set to an instance of an object. exactly what it says, you are trying to use a null object as if it was a properly referenced object. ... Most of the time, when you try to assing value into object, and if the value is null, then this kind of exception occur.
This one is common sense here is your code.
gridjobs.Columns(0).Visible = False
gridjobs.Columns("JOB_NO").HeaderText = "JOB NO."
the first column is Visible = False then you assigned a header text? How can I assign a value in an Object that Invisible?
Just a wild guess.
and also why do u need to assign a header that will be visible = false also? anyway try this
gridjobs.Columns(0).Visible = False
gridjobs.Columns(0).HeaderText = "JOB NO."

Why is the first element always blank in my Rails multi-select, using an embedded array?

I'm using Rails 3.2.0.rc2. I've got a Model, in which I have a static Array which I'm offering up through a form such that users may select a subset of Array and save their selection to the database, stored in a single column in Model. I've used serialize on the database column which stores the Array and Rails is correctly converting the users' selections into Yaml (and back to an array when reading that column). I'm using a multi-select form input to make selections.
My problem is that, the way I currently have it, everything works as I would expect except that the user's subset array always has a blank first element when it's sent to the server.
This isn't a big deal, and I could write code to cut that out after the fact, but I feel like I'm just making some kind of syntactical error as it doesn't seem to me that the default Rails behaviour would intentionally add this blank element without some reason. I must have missed something or forgot to disable some kind of setting. Please help me understand what I'm missing (or point me in to some good documentation that describes this with more depth than what I've been able to find on the intertubes).
MySQL Database Table 'models':
includes a column named subset_array which is a TEXT field
Class Model includes the following settings:
serialize :subset_array
ALL_POSSIBLE_VALUES = [value1, value2, value3, ...]
Form for editing Models includes the following input option:
f.select :subset_array, Model::ALL_POSSIBLE_VALUES, {}, :multiple => true, :selected => #model.subset_array
PUT to server from client looks something like this:
assuming only value1 and value3 are selected
"model" => { "subset_array" => ["", value1, value3] }
Database update looks like this:
UPDATE 'models' SET 'subset_array' = '--- \n- \"\"\n- value1\n- value3\n'
As you can see, there's this extra, blank, element in the array being sent and set in the database. How do I get rid of that? Is there a parameter I'm missing from my f.select call?
Much thanks appreciated :)
EDIT: This is the generated HTML code from the f.select statement. It looks as though there is a hidden input being generated which may be the cause of my issue? Why is that there?
<input name="model[subset_array][]" type="hidden" value>
<select id="model_subset_array" multiple="multiple" name="model[subset_array][]" selected="selected">
<option value="value1" selected="selected">Value1</option>
<option value="value2">Value2</option>
<option value="value3" selected="selected">Value3</option>
<option...>...</option>
</select>
In Rails 4:
You will be able to pass :include_hidden option. https://github.com/rails/rails/pull/5414/files
As a quick fix for now: you can use right now in your model:
before_validation do |model|
model.subset_array.reject!(&:blank?) if model.subset_array
end
This will just delete all blank values at model level.
The hidden field is what is causing the issue. But it is there for a good reason: when all values are deselected, you still receive a subset_array parameter. From the Rails docs (you may have to scroll to the right to see all of this):
# The HTML specification says when +multiple+ parameter passed to select and all options got deselected
# web browsers do not send any value to server. Unfortunately this introduces a gotcha:
# if an +User+ model has many +roles+ and have +role_ids+ accessor, and in the form that edits roles of the user
# the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So,
# any mass-assignment idiom like
#
# #user.update_attributes(params[:user])
#
# wouldn't update roles.
#
# To prevent this the helper generates an auxiliary hidden field before
# every multiple select. The hidden field has the same name as multiple select and blank value.
#
# This way, the client either sends only the hidden field (representing
# the deselected multiple select box), or both fields. Since the HTML specification
# says key/value pairs have to be sent in the same order they appear in the
# form, and parameters extraction gets the last occurrence of any repeated
# key in the query string, that works for ordinary forms.
EDIT: The last paragraph suggests that you shouldn't be seeing the empty one in the case when something is selected, but I think it is wrong. The person who made this commit to Rails (see https://github.com/rails/rails/commit/faba406fa15251cdc9588364d23c687a14ed6885) is trying to do the same trick that Rails uses for checkboxes (as mentioned here: https://github.com/rails/rails/pull/1552), but I don't think it can work for a multiple select box because the parameters sent over form an array in this case and so no value is ignored.
So my feeling is that this is a bug.
In Rails 4+ set :include_hidden on select_tag to false
<%= form.grouped_collection_select :employee_id, Company.all, :employees, :name, :id, :name, { include_hidden: false }, { size: 6, multiple: true } %>
Another quick fix is to use this controller filter:
def clean_select_multiple_params hash = params
hash.each do |k, v|
case v
when Array then v.reject!(&:blank?)
when Hash then clean_select_multiple_params(v)
end
end
end
This way can be reused across controllers without touching the model layer.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-check_box
Gotcha
The HTML specification says unchecked check boxes or selects are not successful,
and thus web browsers do not send them. Unfortunately this introduces
a gotcha: if an Invoice model has a paid flag, and in the form that
edits a paid invoice the user unchecks its check box, no paid
parameter is sent. So, any mass-assignment idiom like
#invoice.update(params[:invoice]) wouldn't update the flag.
To prevent this the helper generates an auxiliary hidden field before
the very check box. The hidden field has the same name and its
attributes mimic an unchecked check box.
This way, the client either sends only the hidden field (representing
the check box is unchecked), or both fields. Since the HTML
specification says key/value pairs have to be sent in the same order
they appear in the form, and parameters extraction gets the last
occurrence of any repeated key in the query string, that works for
ordinary forms.
To remove blank values:
def myfield=(value)
value.reject!(&:blank?)
write_attribute(:myfield, value)
end
In the controller:
arr = arr.delete_if { |x| x.empty? }
I fixed it using the params[:review][:staff_ids].delete("") in the controller before the update.
In my view:
= form_for #review do |f|
= f.collection_select :staff_ids, #business.staff, :id, :full_name, {}, {multiple:true}
= f.submit 'Submit Review'
In my controller:
class ReviewsController < ApplicationController
def create
....
params[:review][:staff_ids].delete("")
#review.update_attribute(:staff_ids, params[:review][:staff_ids].join(","))
....
end
end
I make it work by writing this in the Javascript part of the page:
$("#model_subset_array").val( <%= #model.subset_array %> );
Mine looks more like following:
$("#modela_modelb_ids").val( <%= #modela.modelb_ids %> );
Not sure if this is going to get me headache in the future but now it works fine.
Use jQuery:
$('select option:empty').remove();
Option to remove blank options from drop down.

ms-access localization and default boolean values

Our access client generates on the fly SQL inserts, update and delete instructions to be sent on a MS-SQL Server. Most users have the runtime version of Access 2007, and a few use the complete MS-Access version, 2003 or 2007. This morning one of our new users abroad, using a french/complete version of Access 2003, was unable to update data containing boolean fields.
It appeared that these fields are, in the french version of Access, populated with "Vrai/Faux" instead of "True/False" values. The problem was solved by installing the 2007 access runtime.
But I'd like to find a permanent solution, where I'd be able to read from somewhere which localized version of Access is in use and 'translate' the localized True/False values to standard True/False. I already checked the regional settings of the computer without success, so it is somewhere else. Any idea?
EDIT: Following JohnFX proposal, it is effectively possible to convert from local True/False to universal True/False with this simple function:
Function xBoolean(xLocalBooleanValue) as Boolean
if cint(xLocalBooleanValue) = -1 Then
xBoolean = True
endif
if cint(xLocalBooleanValue) = 0 Then
xBoolean = False
endif
end function
EDIT: following #David's comments, I changed the favorite solution. His proposal is smarter than mine.
EDIT: I am getting the Vrai/Faux values by reading the value of a field in a recordset:
? debug.print screen.activeForm.recordset.fields(myBooleanField).value
Vrai
True is NOT FALSE, or NOT 0, in all cases, no matter the localization or the database format.
So, if you replace all tests for True with NOT 0 and all tests for False with =0, then you've avoided the issue of localization of the Access keywords (I'm surprised that VBA and the Jet and Access expression services would not still understand True/False, though), as well as whichever convention your database engine uses for storing Boolean values.
In general, your data access layer ought to be abstracting that away for you. Both ODBC and ADO do it automatically, so you work with the Boolean values you know and it's taken care of for you transparently, in my experience.
I'm also still puzzled about the question, as it sounds like a display/formatting issue, but use NOT 0 and =0 for True and False avoids the problem entirely in all cases.
EDIT: In regard to the function edited into Philippe's question:
Is there a reason you've implicitly defined your function's parameter as a variant? Is that what you mean? If it's passed a Null, it's going error out on the first CInt(), as CInt() can't accept a Null.
Also, there's a logic problem in that in VBA any number but 0 is supposed to return True. It's also completely redundant code. This is simpler and returns the correct result in all cases:
Function xBoolean(xLocalBooleanValue As Vriant) as Boolean
If CInt(xLocalBooleanValue) <> 0 Then
xBoolean = True
End If
End Function
Or, pithier still:
Function xBoolean(xLocalBooleanValue As Variant) as Boolean
xBoolean = (CInt(xLocalBooleanValue) <> 0)
End Function
And to handle Nulls passed in the parameter:
Function xBoolean(xLocalBooleanValue As Variant) as Boolean
xBoolean = (CInt(Nz(xLocalBooleanValue, 0)) <> 0)
End Function
I'm not sure that's necessary in the context you're currently using it, but I always hate writing code where I can imagine a case where it will error out -- even if I know it can't break in its present context, you never know where it might end up getting used, so should you anticipate a condition that can be handled, you should handle it.
Premature optimization?
No -- it's putting a safety lock on a weapon that keeps it from being misused.
(on the other hand, if it took more lines of code to handle the antipated error than the function started out with, I'd think twice about it)
Have you considered using -1/0 (Access is weird about booleans) instead of true/false in your update and delete queries?
Math is the universal language, yaknow.
Also, to avoid having to localize the UI so much, why not use check-boxes instead of a text field for booleans on your UI?
Simple:
Function xBoolean(bool As Variant) As Boolean
xBoolean = Abs(Nz(bool, 0))
End Function