Simple_form always sets pattern for email input element - ruby-on-rails

I use simple_form to display an email field:
= f.simple_fields_for :user do |f|
= f.input :email, wrapper: :append, pattern: false do
= f.input_field :email, type: "email"
Somehow it always set's the pattern for the input field but I want to use the HTML5 validation of the email input field instead.
Is there a way to prevent simpleform from setting the pattern?

You can monkey-patch SimpleForm:
module SimpleForm
module Components
module Pattern
def pattern
# Deactivated for good:
#input_html_options[:pattern] ||= pattern_source
nil
end
end
end
end
Now, pattern will no longer be generated from validations. You need to add pattern manually to each input that requires a pattern. Example:
= f.input :name, pattern: "[a-zA-Z]+"

Had the same problem ... found a workaround but its kind of hacky
add
:pattern => ".*"
to your field like this
<%= f.input_field :email, :autofocus => true, :pattern => ".*", :class => "span12", :placeholder => t('placeholder.email') %>

I would rather make a string_input.rb file in the app directory some where ... may be in a folder named 'inputs' then have this code
class StringInput < SimpleForm::Inputs::StringInput
def input
input_html_options[:class] = "input-xlarge #{input_html_options[:class]}"
unless string?
input_html_classes.unshift("string")
input_html_options[:type] ||= input_type if html5?
end
input_html_options[:pattern] = nil
add_size!
#builder.text_field(attribute_name, input_html_options)
end
end
This will have effect on all the pattern attributes so no need to put it in explicitly. of course you can also add a condition if the input type is email or not if you want to specify.
Happy coding :)

Related

validates :terms, acceptance: true not showing error

In my model I have the following validator:
validates :terms, acceptance: true, on: :create, allow_nil: false
attr_accessor :terms
and in my form I have:
= simple_form_for #reservation do |f|
= f.error_notification
= f.input :terms, as: :boolean
The problem is that when user not accept the terms it not showing any error, why?
Try this:
validates :terms, :acceptance => {:accept => true} , on: :create, allow_nil: false
Problem may have terms as an actual column in the table. In general validates_acceptance_of is used without such a column, in which case it defines an attribute accessor and uses that for its validation.
In order for validates_acceptance_of to work when it maps to a real table column it is necessary to pass the :accept option, like:
validates :terms, :acceptance => {:accept => true} , :on => :create , allow_nil: false
The reason for this has to do with typecasting in Active Record. When the named attribute actually exists, AR performs typecasting based on the database column type. In most cases the acceptance column will be defined as a boolean and so model_object.terms will return true or false.
When there's no such column attr_accessor :terms simply returns the value passed in to the model object from the params hash which will normally be "1" from a checkbox.
Via noodl
I may have had a similar problem (Rails 4.2.0). I created a checkbox, but it would be ignored and never report and error if unchecked. I found that adding the parameter to the .permit part of my Strong Parameters allowed it to be present.
In my view template for my _form I have something like this:
<div class="field">
<%= label_tag :tos, 'I accepts the TOS' %><br>
<%= f.check_box :tos %>
</div>
I generated my model using scaffold, so my create method start like this
def create
#thing = Thing.new(thing_params)
then near the bottom I have the following for thing_params
def thing_params
params.require(:thing).permit(:field1, :field2, :tos)
end
in my model I used the following:
validates_acceptance_of :tos
If I leave out ':toslike thisparams.require(:thing).permit(:field1, :field2) it will not pop up an error and allows it to continue. This seems counter-intuitive because if Strong Parameters is removing the :tos field then I would think the validate_acceptance would fail.
I had initially just create a checkbox without using f.check_box. Now, if I even try to call the new route without :tos" being listed as permitted, rails throws an error. There also seems to be some rails magic going on because if I remove the validates_acceptance_of from my model, I receive an NoMethodError error when rendering my view saying undefined methodtos'` for the line
<%= f.check_box :tos %>
Would be great if someone else could explain what exactly is going on as I just hacked this together from googling and guessing.

Rails form inputs using context validation

In my app I have a validation rule like this
validates_presence_of :name, :on => :custom_context
When I'm saving my data I use
#obj.save(:context => :custom_context)
So that my context validation rule is applied. This works fine. By in my form, the name field is not marked with asterisk. How can I tell my form helper that we are in the :custom_context context and the name field must be marked as required?
I did not understand what you are trying to do BUT understood the scenario.
You can use an attribute_accessor in your model say -
attribute_accessor :context
In your view(.html.erb file) do the following inside your <% form_for %>
<%= f.hidden_field :context, :value => "custom_context" %>
And in your model :
validates_presence_of :name, :if => Proc.new { |variable|
variable.context == "custom_context"}
I think this should help :D
OK, I guess there is no perfect way to do this. Eventually I did something like this:
<%= f.input :name, :required => required_in_context?(:name, :custom_context) %>
And I wrote a helper method:
def required_in_context? field, context
required = false
MyClass.validators.each do |v|
required = true if v.kind == :presence && v.attributes.include?(field) && v.options == {:on => context}
end
required
end

add checkbox with simple_form without association with model?

How I can add checkbox with simple_form without association with model?
I want to create checkbox which will handle some javascript events, but don't know?
Maybe I miss something in documentation?
Want't to use similar like following:
= simple_form_for(resource, as: resource_name, url: session_url(resource_name), wrapper: :inline) do |f|
.inputs
= f.input :email, required: false, autofocus: true
= f.input :password, required: false
= f.input :remember_me, as: :boolean if devise_mapping.rememberable?
= my_checkbox, 'some text'
You can add a custom attribute to the model:
class Resource < ActiveRecord::Base
attr_accessor :custom_field
end
Then use this field as block:
= f.input :custom_field, :label => false do
= check_box_tag :some_name
Try to find "Wrapping Rails Form Helpers" in their documentation https://github.com/plataformatec/simple_form
You could use
f.input :field_name, as: :boolean
The command proposed by huoxito does not work (at least not in Rails 4). As far as I figured out the error is caused by Rails trying to look up the default value for :custom_field, but because this field does not exists this lookup fails and an exception is thrown.
However, it works if you specify a default value for the field using the :input_html parameter, e.g. like this:
= f.input :custom_field, :as => :boolean, :input_html => { :checked => "checked" }
This question comes first on google with no appropriate answer.
Since Simple Form 3.1.0.rc1 there is a proper way of doing it explained on the wiki: https://github.com/plataformatec/simple_form/wiki/Create-a-fake-input-that-does-NOT-read-attributes
app/inputs/fake_input.rb:
class FakeInput < SimpleForm::Inputs::StringInput
# This method only create a basic input without reading any value from object
def input(wrapper_options = nil)
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
template.text_field_tag(attribute_name, nil, merged_input_options)
end
end
Then you can do <%= f.input :thing, as: :fake %>
For this specific question you have to change the second line of the method to:
template.check_box_tag(attribute_name, nil, merged_input_options)
For versions prior 3.1.0.rc1 admgc gave a solution that is adding the missing method merge_wrapper_options:
https://stackoverflow.com/a/26331237/2055246
Add this to app/inputs/arbitrary_boolean_input.rb:
class ArbitraryBooleanInput < SimpleForm::Inputs::BooleanInput
def input(wrapper_options = nil)
tag_name = "#{#builder.object_name}[#{attribute_name}]"
template.check_box_tag(tag_name, options['value'] || 1, options['checked'], options)
end
end
then use it in your views like:
= simple_form_for(#some_object, remote: true, method: :put) do |f|
= f.simple_fields_for #some_object.some_nested_object do |nested_f|
= nested_f.input :some_param, as: :arbitrary_boolean
i.e. The above implementation supports nested fields correctly. Other solutions I've seen do not.
Note: This example is HAML.
Here is another variation:
= f.label :some_param, class: "label__class" do
= f.input_field :some_param, class: "checkbox__class"
Label text

Customize error message with simple_form

I'm using the simple_form gem. I want to customize the error message displayed when a user fails validations. How can I accomplish this?
You can declare the content of the
error message in your model:
validates_length_of :name, :minimum => 5, :message => "blah blah blah"
You can set id or class for your
error tag:
<%= f.input :name, :error_html => { :id => "name_error"} %>
Then you can use CSS for the styling.
And you can use
<%= f.error :name, :id => "name_error" %>
and you'll get
<span class="error" id="name_error">is too short (minimum is 5 characters)</span>
I dont know if it is any different for simple_form gem.
For content of error messages to be changed, you can use the :message attribute in the model.
class User < ActiveRecord::Base
validates :email, {:presence => true, :message => "is not filled up."}
end
Now the validation message will be Email is not filled up. If you want the field name also to be changed(Email to E-mail address something like that ), the approach now is to define it in locales.rb file like this
# config/locales/en.yml
en:
activerecord:
attributes:
user:
email: "E-mail address"
See link for details on locales. Another approach is to define in the model, humanized attributes like this:
class User < ActiveRecord::Base
validates :email, {:presence => true, :message => "is not filled up."}
HUMANIZED_ATTRIBUTES = {
:email => "E-mail address",
...(other fields and their humanized names)
...
}
def self.human_attribute_name(attr, options={})
HUMANIZED_ATTRIBUTES[attr.to_sym] || super
end
end
For customizing style of validation message we will have to edit the style for
#errorExplanation and .fieldWithErrors,in the scaffold.css stylesheet.
You can easily change the default error message comes in the translation file, which is found in config/locales/simple_form.en.yml.
In the specific initializer, config/initializers/simple_form.rb you can overrule the default options how the html is generated.
Hope this helps.
For completeness, I would like to add that formtastic is an easier choice to start with, because it has a default layout. I like simple_form a lot, but it does not offer any formatting out of the box, but that is their intention. With Formtastic it is very hard (impossible) to change the generated html, and with simple_form can you can completely mold the generated html to your liking. This is especially useful if you have a designer, and the forms you generate have to generate the same html. So if you are getting started, formtastic will give you nicer-looking results quicker. Also note that it is quite easy to switch, because the syntax is almost identical.
There is another solution explained here that wasn't mentioned in the answers. You can directly override the error messages from the views, in the form itself. For example:
<%= f.input :last_name,
placeholder: 'last_name',
error: 'This is a custom error message',
required: true,
class: 'form-field',
autofocus: true,
input_html: { autocomplete: "last_name" } %>
It is however not advised as it is not DRY, you would need to override it in every field.

Rails form not saving 'Type:' field

I generated a simple Post scaffold which has title:string body:text category:string. I later added type:string (and performed the migration) to the model and added the selection fields in new.html.erb and edit.html.erb. I also added validation for all these fields.
<%= f.label :type %>
<%= f.select :type, Post::TYPES, :prompt => "Select post type" %>
When I try and create a post it gives me:
"There were problems with the following fields:
Type can't be blank
Type is not included in the list"
Even though I DO make a selection. Am I missing something obvious here?
Select code from Post class:
TYPES = [
["Job", "job"],
["Volunteer", "vol"]
]
validates_presence_of :title, :body, :category, :type
validates_inclusion_of :category, :in => CATEGORIES.map {|disp, value| value}
validates_inclusion_of :type, :in => TYPES.map {|disp, value| value}
The type field is a reserved field used for single table inheritance(STI). You have to rename the field.
Refer to this article for more details
Edit: Changed the link to point to the article provide by Matchu.
If you really want to, you can use field called type in Rails 4 by setting inheritance_column to something else:
class Product < ActiveRecord::Base
self.inheritance_column = :ruby_type
end
In Rails 3 and below, use method set_inheritance_column instead.

Resources