Customize datetime field in Rails using simple_form - mysql

I am using Rails 3.2.14, MySQL and simple_form for my application.
I have notification_time column field set to datetime and I customized it as text field like this in _create_form.erb
<%= f.input :notification_time, :input_html => { :value => DateTime.now.strftime("%d/%m/%Y - %H:%M %p")}, :as => :string %>
This results to 08/10/2013 - 13:50 PM on the browser.
I have an _update_form.erb with just <%= f.input :notification_time, :as => :string %>, and it results to 2013-10-08 13:50:00 -0400
How to make sure I can get 08/10/2013 - 13:50 PM when I update the form too??

Well, you're never setting how it looks.
In your first block of code, you're doing DateTime.now.strftime("%d/%m/%Y - %H:%M %p"), but you're never doing that anywhere in your second block of code.
I would assume in your _update_form.erb you have a variable that corresponds to the form you're updating.
So let's call that #form.
Then you can just do this: <%= f.input :notification_time, :value => #form.notification_time.strftime("%d/%m/%Y - %H:%M %p"), :as => :string %>... or something of that sort.

Related

Remove newline in textarea generated by HAML / Form Builder

I have a very simple Rails form.:
= form_for #object :remote => true do |form|
= form.text_area :text, :class => 'form-control'
For a new object, with a nil text attribute, this generates:
<textarea class="form-control" name="object[text]" id="object_text"> </textarea>
The blank space in that is a newline:
(byebug) form.text_area :text, :class => 'form-control'
"<textarea class=\"form-control\" name=\"user_deactivation[reason_text]\" id=\"user_deactivation_reason_text\">\n</textarea>"
I strip out the leading and trailing spaces on save, so data wise, its not a big deal, but when the user clicks on this field, it appears indented.
Relevant software versions:
Rails 5.02
haml-4.0.7
The text area is in a bootstrap 3 dialog
Why is this newline being generated and how can I stop it?
You can use the '~' operator, which is like the '=' operator, but automatically runs find_and_preserve on the output.
Like this:
= form_for #object :remote => true do |form|
~ form.text_area :text, :class => 'form-control'
This is not an ideal answer, but it does work. I would like something better:
= find_and_preserve(form.text_area :text, :class => 'form-control')
Can that be automatic? Is there a way to have the text_area helper not insert a newline?

"No route matches" : Nightmare with routing rails namespace

I'm geting crazy with a namespace URL that leads to incorrect action 'show' instead of 'new'.
When I'm using this URL : admin/admin_utilisateurs/new
I get this error :
Routing Error
No route matches {:action=>"show", :controller=>"admin/admin_utilisateurs"}
Try running rake routes for more information on available routes.
This is the link_to I'm using in my index page :
link_to 'Nouveau', new_admin_admin_utilisateur_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
These are my rake routes :
root / welcome#index
pub_responsables GET /catalogs/managers(.:format) pub_responsables#index
POST /catalogs/managers(.:format) pub_responsables#create
new_pub_responsable GET /catalogs/managers/new(.:format) pub_responsables#new
edit_pub_responsable GET /catalogs/managers/:id/edit(.:format) pub_responsables#edit
pub_responsable GET /catalogs/managers/:id(.:format) pub_responsables#show
PUT /catalogs/managers/:id(.:format) pub_responsables#update
DELETE /catalogs/managers/:id(.:format) pub_responsables#destroy
new_admin_utilisateur_session GET /admin_utilisateurs/sign_in(.:format) devise/sessions#new
admin_utilisateur_session POST /admin_utilisateurs/sign_in(.:format) devise/sessions#create
destroy_admin_utilisateur_session DELETE /admin_utilisateurs/sign_out(.:format) devise/sessions#destroy
admin_utilisateur_password POST /admin_utilisateurs/password(.:format) devise/passwords#create
new_admin_utilisateur_password GET /admin_utilisateurs/password/new(.:format) devise/passwords#new
edit_admin_utilisateur_password GET /admin_utilisateurs/password/edit(.:format) devise/passwords#edit
PUT /admin_utilisateurs/password(.:format) devise/passwords#update
cancel_admin_utilisateur_registration GET /admin_utilisateurs/cancel(.:format) admin_utilisateurs/registrations#cancel
admin_utilisateur_registration POST /admin_utilisateurs(.:format) admin_utilisateurs/registrations#create
new_admin_utilisateur_registration GET /admin_utilisateurs/sign_up(.:format) admin_utilisateurs/registrations#new
edit_admin_utilisateur_registration GET /admin_utilisateurs/edit(.:format) admin_utilisateurs/registrations#edit
PUT /admin_utilisateurs(.:format) admin_utilisateurs/registrations#update
DELETE /admin_utilisateurs(.:format) admin_utilisateurs/registrations#destroy
admin_utilisateur_confirmation POST /admin_utilisateurs/confirmation(.:format) devise/confirmations#create
new_admin_utilisateur_confirmation GET /admin_utilisateurs/confirmation/new(.:format) devise/confirmations#new
GET /admin_utilisateurs/confirmation(.:format) devise/confirmations#show
admin_utilisateur_unlock POST /admin_utilisateurs/unlock(.:format) devise/unlocks#create
new_admin_utilisateur_unlock GET /admin_utilisateurs/unlock/new(.:format) devise/unlocks#new
GET /admin_utilisateurs/unlock(.:format) devise/unlocks#show
admin_admin_utilisateurs GET /admin/admin_utilisateurs(.:format) admin/admin_utilisateurs#index
POST /admin/admin_utilisateurs(.:format) admin/admin_utilisateurs#create
new_admin_admin_utilisateur GET /admin/admin_utilisateurs/new(.:format) admin/admin_utilisateurs#new
edit_admin_admin_utilisateur GET /admin/admin_utilisateurs/:id/edit(.:format) admin/admin_utilisateurs#edit
admin_admin_utilisateur GET /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#show
PUT /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#update
DELETE /admin/admin_utilisateurs/:id(.:format) admin/admin_utilisateurs#destroy
For info, I'm using Devise on a users table which I called "admin_utilisateurs".
Devise is working great with options : :database_authenticatable, :confirmable, :recoverable, :registerable, :trackable, :timeoutable, :validatable, :lockable
The point is that I setup another controller for admin purpose on the admin_utilisateurs table.
So here it is my config/routes.rb
root :to => 'welcome#index'
resources :pub_responsables, :path =>'/catalogs/managers'
devise_for :admin_utilisateurs, :controllers => {:registrations => 'admin_utilisateurs/registrations'}
namespace :admin do
resources :admin_utilisateurs
end
So my admin controller is located in app/controllers/admin/admin_utilisateurs_controller.rb
Here is the action of my 'new' controller's action :
class Admin::AdminUtilisateursController < ApplicationController
before_filter :authenticate_admin_utilisateur!
...
def new
#admin_utilisateur = AdminUtilisateur.new
respond_with(#admin_utilisateur)
end
...
end
The view for that controller are located in app/view/admin/admin_utilisateurs/
But the issue is really connected to the route because the other path for 'show', 'edit' and 'update' are working properly.
And if I delete my controller app/controllers/admin/admin_utilisateurs_controller.rb, Rails is not complaining about missing controller, she's still complaining about the "no route for show action".
I'm really lost. Could anyone advise please ?
Thanks in advance
===== UPDATE 1 =====
Here it is the log related to my URL request :
Started GET "/admin/admin_utilisateurs/new" for 127.0.0.1 at 2012-10-25 12:55:05 +0200
Processing by Admin::AdminUtilisateursController#new as HTML
Rendered shared/_main_title.html.haml (0.4ms)
Rendered admin/admin_utilisateurs/_form.html.haml (17.2ms)
Rendered admin/admin_utilisateurs/new.html.haml within layouts/application (31.7ms)
Completed 500 Internal Server Error in 45ms
ActionController::RoutingError (No route matches {:action=>"show", :controller=>"admin/admin_utilisateurs"}):
app/views/admin/admin_utilisateurs/_form.html.haml:1:in `_app_views_admin_admin_utilisateurs__form_html_haml___780348754_85631840'
app/views/admin/admin_utilisateurs/new.html.haml:9:in `_app_views_admin_admin_utilisateurs_new_html_haml__296364877_85537950'
app/controllers/admin/admin_utilisateurs_controller.rb:51:in `new'
It seems that it is properly routed but then there is a problem in the view.
I retried to remove the controller file admin_utilisateurs_controller.rb but this time restart my web server (sudo service apache2 restart) and the error was different.
I got this time a "Routing error uninitialized constant Admin::AdminUtilisateursController".
So this confrim there is an issue in my view...
digging deeper...
OK, I found the issue.
The issue was coming from my partial form view which I use for my 'edit' action and for my 'new' action : /app/views/admin/admin_utilisateurs/_form.html.haml
= form_for #admin_utilisateur, :url => admin_admin_utilisateur_path, :html => {:class => "formulaire-standard"} do |f|
= render :partial => 'shared/error_message', :locals => { :element => #admin_utilisateur, :debut_erreur => 'Cet utilisateur ne peut ĂȘtre enregistrĂ©'}
.groupe-champs
.champ
= f.label :nom
= f.text_field :nom, :class => 'input-width-8-col', :required => 'required'
.champ
= f.label :prenom
= f.text_field :prenom, :class => 'input-width-5-col', :required => 'required'
.champ
= f.label :telephone
= f.telephone_field :telephone, :class => 'input-width-5-col', :required => 'required'
.champ
= f.label :mobile
= f.telephone_field :mobile, :class => 'input-width-5-col'
.champ
= f.label :email
= f.email_field :email, :class => 'input-width-8-col', :required => 'required'
.groupe-champs
= render :partial => 'shared/checkboxes_admin_utilisateur', :locals => { :resource => #admin_utilisateur }
.groupe-champs
.champ-1
= f.check_box :approved
.champ-5
= f.label :approved
.checkbox-explication
= t('activerecord.attributes.admin_utilisateur.explanations.active')
.separator
.groupe-actions
= f.submit 'Enregistrer', :class => 'btn-text btn-dimensions btn-encrusted metal'
= link_to 'Annuler', admin_admin_utilisateur_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
I was using the form_for tag incorrectly. Because my form is used within a namespace, I must add the namespace into its arguments, and remove the :url option because otherwise this form will only work with the 'edit' action :
= form_for [:admin, #admin_utilisateur], :html => {:class => "formulaire-standard"} do |f|
This code lets Rails guess what path to use wether it's for a new record or to edit an existing record. So I don't need to specify the :url and the :method.
The second mistake was (a classical one) the link_to at the bottom of the form.
I forgot the 's' at the end of the route helper (admin_admin_utilisateurSSSS_path):
= link_to 'Annuler', admin_admin_utilisateurs_path, :class => 'btn-text btn-dimensions btn-encrusted metal'
The moral of the story :
ALLWAYS CHECK YOUR /log/development.log FILE ! ;-)

Rails content_tag inserts extra "<" and ">" characters

When doing this:
def user_log
if logged_in? == false
form_tag session_path, :id => "mform" do
content_tag(:span, content_tag(text_field_tag :email, "email#domain.com"), :class => "memail")+
content_tag(:span, content_tag(password_field_tag :password, "12345678912"), :class => "mpass")+
content_tag(:span, content_tag(submit_tag 'Login'), :class => "mbutton")
end
else
...
end
end
end
I get this:
stack overflow doesn't let me post pictures
Since I don't want the extra "<" and ">", what am I doing wrong?
EDIT: As extra information, on my view I am just doing:
<%= user_log %>
The fundamental problem is that you are using content_tag twice when you don't need to. content_tag essentially calls content_tag_string. Here's content_tag_string's source:
def content_tag_string(name, content, options, escape = true)
tag_options = tag_options(options, escape) if options
"<#{name}#{tag_options}>#{content}</#{name}>".html_safe
end
Calling content_tag(text_field_tag :email, "email#domain.com") looks like:
"<#{text_field_tag :email, "email#domain.com"}>"
and text_field_tag already produces a full HTML tag (it includes the "<" and ">").
All you need to do to get rid of the extra angled brackets is to leave out the second content_tag:
content_tag(:span, text_field_tag(:email, "email#domain.com"), :class => "memail")+
Though I haven't tried it locally, the problem is likely that Rails is html escaping your handy helper method. To see if I'm right, try throwing this in your view:
<%= raw(user_log) %>
If that works, you can throw raw in your helper method instead:
def user_log
if logged_in? == false
raw(form_tag session_path, :id => "mform" do
content_tag(:span, content_tag(text_field_tag :email, "email#domain.com"), :class => "memail")+
content_tag(:span, content_tag(password_field_tag :password, "12345678912"), :class => "mpass")+
content_tag(:span, content_tag(submit_tag 'Login'), :class => "mbutton")
end)
else
...
end
end
raw tells Rails that this code is safe and doesn't need to be html escaped.
As a first guess, I might try something like:
if logged_in? == false
...
else
...
end.html_safe
Update: Ok, back to the drawing board.
As a second guess, try this. (And note the extra parameter to content_tag, which required putting the hash in explicit { }...)
def user_log
if logged_in? == false
form_tag session_path, :id => "mform" do
(
content_tag(:span, content_tag(text_field_tag :email, "email#domain.com"), {:class => "memail"}, false)+
content_tag(:span, content_tag(password_field_tag :password, "12345678912"), {:class => "mpass"}, false)+
content_tag(:span, content_tag(submit_tag 'Login'), {:class => "mbutton"}, false)
).html_safe
end
else
...
end
end
end

How does the HTML5 multiple file upload field map to a nested model in Rails 3?

I'm trying to use the HTML5 multiple attribute on a file field in a nested form.
The models are as follows:
class Album < ActiveRecord::Base
has_many :album_images
has_many :images, :through => :album_images
accepts_nested_attributes_for :images
end
class Image < ActiveRecord::Base
has_many :album_images
has_many :albums, :through => :album_images
mount_uploader :filename, ImageUploader
validates_presence_of :filename
end
The view:
<%= semantic_form_for #album, :url => upload_path do |f| %>
<%= f.inputs do %>
<%= f.input :name, :label => 'Album title' %>
<% end %>
<%= f.input :images, :as => :file, :input_html => {:multiple => true} %>
<%= f.buttons do %>
<%= f.commit_button 'Upload' %>
<% end %>
<% end %>
When I use for the file field:
<%= f.input :images, :as => :file, :input_html => {:multiple => true} %>
I get:
<input id="album_images" multiple="multiple" name="album[images][]" type="file">
Which doesn't doesn't seem right since I think I want to set the filename on the object directly, but I'm not sure about this. When I try to upload with this field, the incoming params look like:
"album"=>{"name"=>"2011-01-09", "images"=>["IMG_0052.JPG", "IMG_0053.JPG", "IMG_0054.JPG", "IMG_0055.JPG"]}
However, I get the following error:
ActiveRecord::AssociationTypeMismatch (Image(#2157004660) expected, got String(#2151988680)):
OK, that error is probably due to the fact that it just received a filename and not an image object. So instead, I use for the file field:
<%= f.input :images, :as => :file, :input_html => {:multiple => true, :name => 'album[images][][filename]'} %>
for which Formtastic generates:
<input id="album_images" multiple="multiple" name="album[images][][filename]" type="file">
The incoming params look like:
"album"=>{"name"=>"2011-01-09", "images"=>[{"filename"=>"IMG_0052.JPG"}, {"filename"=>"IMG_0053.JPG"}, {"filename"=>"IMG_0055.JPG"}]}
But then I get this error:
Image(#2153868680) expected, got ActiveSupport::HashWithIndifferentAccess(#2158892780)
So how does one go about setting up this multiple file input filed mapping in Rails?
Thanks.
You need to include :html => { :multipart => true } in your form_for (or in your case semantic_form_for) call so that your <form> tag is set to support file uploads.
Then revert back to your original syntax for f.input and you should be right then.

Including a manual Rails tag in my form's parameters

This question is related to this other question:
Change rails text_field form builder type
I have a JQuery Tools Range in my form, and making it work requires that the input field be of the type "date". Rails doesn't easily allow me to do this so I've used a manual tag as follows:
<% form_for #customer, :url => {:action => "update", :id => #customer} do |f| %>
...
<%= tag(:input, {:type => :range, :value => f.object.travel, :name => "travel", :min => "0", :max => "100" }) %>
...
<% end %>
This tag shows the range slider. It also displays the right value from the database. However, when I submit a change, the "travel" attribute is sent as a general attribute and not under "customer". So, my database doesn't update.
How can I rewrite the tag so it gets included as a "customer" attribute?
Try:
<%= tag(:input, {:type => :range, :value => f.object.travel, :name => "customer[travel]", :min => "0", :max => "100" }) %>