Rails simple_simple form, feature test failing to populate field/sometimes - ruby-on-rails

I have a finicky test(s).
I'm using simple_form and rails to create a pretty standard job/college type application for users to fill out.
Issue is: Sometimes in the feature test, when a user is editing the application(created via Factoryfirl), rails/simple_form fails to populate a datefield with some of the variables of the date. This also seems to only happen when include_blank: is true.
I know it's being created with a date. The field is failing to be populated with the date, sometimes and only the year column.
I don't think this is an issue with anything I wrote as the tests do work sometimes. Could be a config issue so:
rails-4.2.5.1
rspec-core-3.3.2
capybara-2.5.0
the call to the field:
= required_field_on_submit(f, :profile, :birthdate, as: :date, start_year: years_ago(100), end_year: years_ago(Application::MINIMUM_AGE - 1), include_blank: true, order: order(:m, :d, :y))
required_field_on_submit is just a custom wrapper for f.input, bc of the way applications are being validated. Nothing funky happening there, already checked.

As I mentioned in the comments - A usual cause of a date select not being correctly filled by a page during tests is the data being generated (factory, etc) being outside the acceptable range of the date select

Are you able to select the value for which is given by (years_ago(100)) from front end manually? If yes then make sure that the page is loaded properly, before passing the values. You can wait for an element or verify a message on the page.
You can also try debugging the failing cases, by adding "puts" statement to print the date in the console, so that it can be verified that whether the date is in correct range or not.

Related

Rails: Datagrid enum filter does not work when multiple or checkboxes options are true

I have a form that is using Datagrid for searching on a single table. The filters and searching work as expected, including this one:
filter(:location, :enum, :select => :locations)
However, when I try to make that filter show up as checkboxes, like so...
filter(:location, :enum, :select => :locations, :checkboxes => true)
...the checkboxes show up but the filter no longer works, and it returns the result set as though I never checked any of the checkboxes at all. This same unexpected behavior also happens when I try to use the :multiple option. According to the Datagrid gem documentation I don't see any other requirements for making a filter work with checkboxes or multiple select options.
When viewing the requests on my local server, I noticed that the location filter is not being added to the SQL query when :multiple or :checkboxes is set to true, but the values ARE being passed in the query string, like so (indicated by FBR and FBZ):
http://localhost:3000/searches/index?utf8=✓&searches_grid[name]=Foo&searches_grid[location][]=FBR&searches_grid[location][]=FBZ&commit=Search#searchAnchor
Here's what the working example (no multiples and no checkboxes) looks like:
http://localhost:3000/searches/index?utf8=✓&searches_grid[name]=Foo&searches_grid[location]=FBR&commit=Search#searchAnchor
I'm not sure if Datagrid is having trouble rendering parameters that are sent as arrays, or if there's some kind of issue with my versions of Rails/Ruby/etc, or what's going on. If anyone has any suggestions or workarounds I would greatly appreciate them, and if not I will try submitting a Gitlab issue for the gem.
I am using Datagrid 1.5.4, Rails 5.0.3, and Ruby 2.3.1p112.
After hours of dissecting everything in my code, I noticed that the location parameters of the search_params action in my controller was missing the square brackets to allow it to contain multiple values:
params.require(:searches_grid).permit(
:name,
...more params...
:order,
:descending,
location: [] # <-- Had to add brackets here
)
Now it's working as expected.

How to get value in controller of an bootstrap-multiselect-rails

I'm new to rails and web. I use the 'bootstrap-multiselect-rails' gem to create a select box and normal inputs.
When I click the submit button, I don't retrieve the select box informations in the params variable (the inputs are well retrieve).
This is probably due to the bootstrap-multiselect gem that overrides the behavior of the select box by replacing it with a ul,li system.
%select#select-type{:multiple => "multiple"}
- #list_of_type.each do |type|
%option{value: "#{type.label}"} #{type.label.upcase_first}
I have seen answers that explains in retrieving the information in javascript but how to perform treatments on its information in the controller?
In your select field I cannot see that you assigned a param to it. Usually select goes like this: <%= select :input, etc... where :input is the param you want to save into your model.
Rails docs give following example:
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { include_blank: true })
So the problem is that you did not specify the param. It is also not empty, it is not mentioned at all in your Parameters. Correct?! Than please check the basic docs again on how to create a select field and add the param as requested. Unfortunately, I do not know the exact syntax using your gem.
I am also not sure about the :multiples=>"multiple". or should it be multiple: true? But I think your version might work with the gem. However, your haml only creates the HTML select with #id and multiple: true. But what you want is something like this
<select name="post[category]" id="post_category">
So that the param is clear in the select.
Afterwards, when you have saved the param you can use it also in your controller action.
In conclusion: Add the param to your select field. I don't know how to do this with the gem but you might find some docs may be, or check basic rails docs which might help you out here for sure. Also SO has many questions on select with rails. Good luck!
Can you show the rails code for the multi form? You just need to add a value to each select option which will be stored by rails if you have permitted the params in controller and set up a column for it migrations.
If questions on how to add value to select_tag check out the rails docs. In your html markup i cannot see if the options have value.

rails if statement in controller - checking nil

I have an if statement in my update action in one of my controllers. It looks like this:
if !#bid.attributes.values.include?(nil)
build(#bid.id)
end
I am checking to see if there are any nil valued attributes in my Bid object before building a bid report. I know the build method works fine because it builds a report when not wrapped in the if statement. When it is wrapped in this if statement, it doesn't run. I have checked to make sure that there are no nil values in the object. I went into the rails console and all attributes have non-nil values. In addition, I am able to check this in the views to confirm that there are no nil values.
I have also tried writing as:
build(#bid.id) unless #bid.attributes.values.include?(nil)
and a couple other variations. None are allowing the build to run.
Your code seems fine, I'm betting it's your data that's the problem instead. Mostly likely, assuming this an active record instance, the attribute is id which will be nil until the new record gets saved.
What do you get in the terminal when you add this line right before your if?
puts #bid.attributes.to_yaml
You should be able to see what has values and what does not. And I'm pretty sure at least one of those values is nil.
I would recommend being more explicit about exactly which fields are required. And this is exactly what validations are for.
class Person < ActiveRecord::Base
validates :name, presence: true
end
You explicitly validate each field so that when it's absent you get a very specific error message about why: "Person name can't be blank." So instead of wondering why it wont save, you get told why at the point it fails to save.

Localizing a text field containing a number in Ruby on Rails

I am currently working on a project to internationalize one of our ruby-on-rails web applications so that it can be used in other countries (France will be the first one in this case).
A particular issue I haven't worked out yet is with the displaying of numeric fields. When displaying numbers for display purposes only, I do the following:
<%= number_to_percentage(tax.rate, :precision => 2)%>
In English, this shows 17.50, but in French it shows 17,50 (with a comma in place of the decimal point) which is as expected. The problem comes in the Edit form, when I show a text field
<%= f.text_field :rate, :size => 15 %>
When this renders a text box on the screen, the text box always shows 17.50 with a full stop rather than a comma for French. I am not sure that is correct.
When I tried doing the following:
<%= f.text_field :rate, :size => 15, :value => number_with_precision(f.object.rate, :precision => 2) %>
This did indeed show 17,50 in the text box for French, but when I click on the Update button to save the form, the Ruby validation kicks in and tells me that 17,50 is not a number (or rather it says "n'est pas un nombre"). I have to enter 17.50 to get it to save.
To be honest, I am not entirely sure on the correct thing to do here. Should all countries enter numbers with full stops in text boxes, or is there a way to get Ruby-on-Rails to display commas, and validate them appropriately?
TL;DR
This is the kind of things I hate to do over and over again (I'm serving french users, they're easily confused with dots as the decimal separator).
I exclusively use the delocalize gem now, which does the format translation automatically for you. You just have to install the gem and leave your forms as-is, everything should be taken care of for you.
I like to read, give me the long explanation
The basic conversion is quite simple, you have to convert back and forth between the following formats:
The backend one, which is usually English, used by your persistent storage (SQL database, NoSQL store, YAML, flat text file, whatever struck your fancy, ...).
The frontend one, which is whatever format your user prefers. I'm going to use French here to stick to the question*.
* also because I'm quite partial towards it ;-)
This means that you have two points where you need to do a conversion:
Outbound: when outputting your HTML, you will need to convert from English to French.
Inbound: When processing the result of the form POST, you will need to convert back from French to English.
The manual way
Let's say I have the following model, with the rate field as a decimal number with a precision of 2 (eg. 19.60):
class Tax < ActiveRecord::Base
# the attr_accessor isn't really necessary here, I just want to show that there's a database field
attr_accessor :rate
end
The outbound conversion step (English => French) can be done by overriding text_field_tag:
ActionView::Helpers::FormTagHelper.class_eval do
include ActionView::Helpers::NumberHelper
alias original_text_field_tag text_field_tag
def text_field_tag(name, value = nil, options = {})
value = options.delete(:value) if options.key?(:value)
if value.is_a?(Numeric)
value = number_with_delimiter(value) # this method uses the current locale to format our value
end
original_text_field_tag(name, value, options)
end
end
The inbound conversion step (French => English) will be handled in the model. We will override the rate attribute writer to replace every French separator with the English one:
class Tax < ActiveRecord::Base
def rate=(rate)
write_attribute(:rate, rate.gsub(I18n.t('number.format.separator'), '.')
end
end
This look nice because there's only one attribute in the example and one type of data to parse, but imagine having to do this for every number, date or time field in your model. That's not my idea of fun.
This also is a naïve* way of doing the conversions, it does not handle:
Dates
Times
Delimiters (eg. 100,000.84)
* did I already tell you I like French?
Enter delocalize
Delocalize is working on the same principle I outlined above, but does the job much more comprehensively:
It handles Date, Time, DateTime and numbers.
You don't have to do anything, just install the gem. It checks your ActiveRecord columns to determine if it's a type that needs conversion and does it automatically.
The number conversions are pretty straightforward, but the date ones are really interesting. When parsing the result of a form, it will try the date formats defined in your locale file in descending order and should be able to understand a date formatted like this: 15 janvier 2012.
Every outbound conversion will be done automatically.
It's tested.
It's active.
One caveat though: it doesn't handle client-side validations. If you're using them, you will have to figure out how to use i18n in your favourite JavaScript framework.
This is the gsub technique :
In your model :
before_validation :prepare_number
def prepare_number
self.rate.gsub(/,/, '.') if self.rate.match /,\S/
end

Select prompt option disappears when validation fails in Rails

Let me preface by saying I'm a noob to Rails and StackOverflow so please go easy on me. I'm using Rails 2.3.8 with sqlite3 on my dev box.
I have created a select pulldown in a form using the following:
<%= select( "communication", "gig_id", { "Add New Gig" => "new"}, {:prompt => "-- Select Gig --"}, :onchange => "toggle(this, 'gigInfo')") %>
However, when something else in the form fails validation and the "new" page is re-rendered, my prompt goes away and the only option left is the "Add New Gig" option. This is the case with ALL my forms and I can't seem to find any answer as to why.
My controller uses the basic scaffolding so I'm sort of at a loss. Any help would be greatly appreciated.
Your observation is accurate, and you astutely observed that :include_blank remains even when :prompt does not.
You can achieve the results you want by setting :include_blank to the string you were using for prompt (it doesn't need to be a boolean).
:prompt, it seems, only appears when there is no value for Rails to supply the given field. When your app re-renders the new view, there is a value to supply that field because it created an instance of your Communication model. (It failed to save that instance, but it looks as though that instance has its gig_id field set.)

Resources