Using tr as label-input wrapper in simple-form - ruby-on-rails-3

I may be old school,and I've been through many div/span attempts and swore off tables at one time, but there are just some good uses for tables, one of them, imho, is a form. I prefer to shade my label fields with a different background color. I've tried may ways, but if the input (actually either) side overflows the width, it will mess up the label background. I'd look at another attempt, but I really prefer a table approach.
In 2.x I set my configuration to:
config.wrappers :tag => :tr, :class => :input,
:hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
b.use :label, :wrap_with => {:tag => :td, :class => :label}
b.use :input, :wrap_with => {:tag => :td, :class => :input}
b.use :hint, :wrap_with => { :tag => :span, :class => :hint }
b.use :error, :wrap_with => { :tag => :caption, :class => :error }
Works great!, except for errors. I first had it as a span and it went to the top of the table. I then set it to caption and, at least in Safari, it ends tbody and puts in the caption and starts another tbody - but it screws up the table flow.
Is there a way I can force the error to be in the input wrapper? Or any other approach? I'd even accept (and maybe this is what I should do) putting the error in the main message like the scaffold approach. Didn't think about that until I started to write this, but I guess I could not use simple forms error stuff and go back to the scaffold approach.
At least I think you can do that. For instance, I didn't know (and could not find in documentation - but I didn't look real hard!) that you could use regular form_for input (e.g., f.text_field) mixed with f.input. Great for things like putting City, St, Zip on one row.

I guess I should answer my own question. I ended up not using Simple Forms error notification and went back to the scaffold method.
I configured my wrappers as follows:
config.wrappers :tag => :tr, :class => :input,
:hint_class => :field_with_hint, :error_class => :field_with_errors do |b|
b.use :label, :wrap_with => {:tag => :td, :class => :label}
b.use :input, :wrap_with => {:tag => :td, :class => :input}
Wrote a helper method for errors:
def show_form_errors(instance)
if instance.errors.any?
errors = content_tag(:h2, pluralize(instance.errors.count, "error") +"prohibited this project from being saved:")
list = content_tag :ul do
e = ""
instance.errors.full_messages.each do |msg|
e <<"<li>#{msg}</li>"
end
e.html_safe
end
return content_tag(:div, (errors + list),:id => "error_explanation").html_safe
end
end
# instead of
# = f.error_notification
# I used
# = show_form_errors(#event)
Had to tweak the CSS for error_explanation because of how I had borders defined on my table rows (just border-bottom) and add !important to wrap the tr with a red border:
.field_with_errors {
padding: 2px;
border:solid 3px red!important;
background-color:pink;
}
Works fine and I am content with this method.

Related

How to display only the value in edit page in Active Admin

I have a edit form in Active Admin. I need some field as read only.
My current edit page is like
I need the page look like this
How can this be done. My code for the edit form page is like
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.input :current_address, :label => 'Current Address', :as => :string
end
end
Please help.
As Alex said, set to disabled. You could then use css to get the visual you wanted, if you can live with the semantics of that.
The syntax was slightly different for me to get this to work.
in your admin form:
f.input :finish_position, input_html: { disabled: true }
in your CSS active_admin.css
input[disabled="disabled"],
input[disabled] {
background-color: #F4F4F4;
border: 0px solid #F4F4F4 !important;
}
For a cleaner form definition within your ActiveAdmin.register{} block you may as well want to define a "readonly" input type to be used within active admin using formtastic:
Form block syntax is for activeadmin version 1.0.0.pre at 0becbef0918a.
# app/admin/inputs/readonly_input.rb
class ReadonlyInput < Formtastic::Inputs::StringInput
def to_html
input_wrapping do
label_html <<
template.content_tag('div', #object.send(method))
end
end
end
# app/admin/your_model.rb
ActiveAdmin.register YourModel do
# ...
form do |f|
# ...
input :current_address, as: :readonly
# ...
end
end
I was facing the same issue and tried using :disabled but it did not solve my problem as I wanted field value to be included in params object while sending it to the server. When you mark a form input as :input_html => {:disabled => true} , it does not include this field value in params.
So, instead I used :input_html => {:readonly => true} which solved both of my problems:
Does not allow user to edit
Includes the value in params
I hope this will help.
How about this?
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.li do
f.label :current_address
f.span f.object.current_address
end
end
end
Try to add , :disabled => true for address input field.
The trick is to use "object". Here is how you should code it:
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.label :current_address, f.object.current_address
end
end

Rails 3: How can I make Paperclip-FFMPEG work?

I have Rails 3.0.3 with these gems:
delayed_job 2.1.4
delayed_paperclip 0.7.1
paperclip 2.3.16
paperclip-ffmpeg 0.7.0
(This combination is very specific. Some newer gems will not work with others.)
Here's my Video model:
class Video < Upload
has_attached_file :file, :default_style => :view, :processors => [:ffmpeg],
:url => '/system/:class/:attachment/:id/:style/:basename.:extension',
:path => ':rails_root/public/system/:class/:attachment/:id/:style' \
+ '/:basename.:extension',
:default_url => '/images/en/processing.png',
:styles => {
:mp4video => { :geometry => '520x390', :format => 'mp4',
:convert_options => { :output => { :vcodec => 'libx264',
:vpre => 'ipod640', :b => '250k', :bt => '50k',
:acodec => 'libfaac', :ab => '56k', :ac => 2 } } },
:oggvideo => { :geometry => '520x390', :format => 'ogg',
:convert_options => { :output => { :vcodec => 'libtheora',
:b => '250k', :bt => '50k', :acodec => 'libvorbis',
:ab => '56k', :ac => 2 } } },
:view => { :geometry => '520x390', :format => 'jpg', :time => 1 },
:preview => { :geometry => '160x120', :format => 'jpg', :time => 1 }
}
validates_attachment_content_type :file, :content_type => VIDEOTYPES,
:if => Proc.new { |upload| upload.file.file? }
process_in_background :file
end
When creating a new Video object with attachment, the original is saved, but no conversion will be done. Even calling Video.last.file.reprocess! won't to a thing except returning true. (Not sure what "true" means in this case as it didn't work.)
I tried hardcoding the path to ffmpeg in Paperclip::options[:command_path]. I even tried deleting the paperclip-ffmpeg.rb file and replacing it with a blank file. Really thinking I'd get an exception by doing the later, instead, I simply got "true" again.
It feels like the paperclip-ffmpeg.rb is being loaded, because it is required by config/application.rb, but nothing is called in it when trying to generate a thumbnail or convert a video.
Can anyone help me with this? Thanks in advance!
Looks like I solved this problem myself, and it was caused by something I did.
I wrote my own script to import files and the database from an older app to Rails. The files were in place, but someone I updated the database with the wrong file extensions (in this case, ".jpg" instead of ".MOV").
Paperclip will verify first to see if the original file exists before calling any processor, based on the file name stored in the database. As it didn't, Paperclip just didn't do anything. Once I had the data corrected, everything ran as expected. (I had problems with FFMPEG, but that's a different issue.)
My apologies if I wasted anyone's time. Hope this can be helpful for someone.
I use a similar configuration for one of my project (but Rails 3.1.1) and everything works fine. I added paperclip-ffmpeg to my Gemfile not with config/application.rb. Maybe this helps!?

Share resources between layouts in Rails 3

OK, so Ive set up my mailer in Rails which works fine, but I wanted to make a new action (or maybe just a view?) to have a slimmed down contact form in a lightbox. I can do that all fine and dandy but it would use the default layout which I dont want. So I added:
render :layout => 'lightbox'
to the action so that I could use a new layout. Unfortunately that seems to block off my access to the model as I get this error when the lightbox pops up
undefined method `model_name' for NilClass:Class
#on this line
<% form_for #contact, :url => {:action => "create"}, :html => {:method => :post} do |f| %>
So by using a different layout I cant use the resources I set up in my routes which is here:
resources :contacts, :only => [:new, :create], :as => :contacts
#Im passing in a name to the email form
match "contacts/direct/:name" => "contacts#direct", :as => :direct_email
I hope that made sense. But what do I do?

assigning parameters to a model in a link_to helper

if am trying to pass a parameter through a link and assign it to a specific model. here is the code i'm working with:
<%= link_to ( image_tag("item.png", :size => "50*50", :border=> 0, :alt => "item", :title => "item"), {:action => 'initialize_order', :frame_id => 1 }) %>
right now :frame_id is getting passed through as:
{"frame_id"=>"1"}
i want the parameter to be assigned to the model :order, returning:
"order"=>{"frame_id"=>"1"}
i know the answer must be simple but i've searched for a while now.
try this in your url args:
{:action => 'initialize_order', :order => {:frame_id => 1 }}
alternatively, since you only have one parameter, just pass it as :id and assign it in the controller.
Even better, build your app using RESTful routes, with an orders_controller and an initialize method. If orders and frames have a parent-child relationship, then nest them in your resources. That way you can use all the path generators.

Rails 3 routing

Ok, I'm relatively new to rails and am working through the book Rails for PHP programmers. To make things interesting I'm using Rails 3 and haml to work through the book, and the book is written using Rails 2.X and erb so some of the examples are outdated.
To the question:
The route example in the book is
map.presentation 'meetings/:meeting_id/presentations/:action/:id',
:controller => "presentations",
:action => "show",
:meeting_id => /\d+/
So that was a pre-Rails 3 route. My adaptation of the above into a Rails 3 route is:
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations#show', :constraints => {:id => /\d/}
My adaptation works for the destroy action, but not for the edit action... and due to my inexperience I don't know what I'm doing wrong. From the article here (http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/) it looks like I'm doing it right, but something isn't right.
The link_to helpers that produce the urls are as follows
= link_to 'edit', :controller => 'presentations',
:action => 'edit',
:meeting_id => presentation.meeting.id,
:id => presentation.id
# Incorrectly Produces: http://localhost:3000/presentations/edit?meeting_id=2&id=1
= link_to 'destroy', { :controller => 'presentations',
:action => 'destroy',
:meeting_id => presentation.meeting.id,
:id => presentation.id },
:confirm => 'Are you sure?',
:method => :delete
# Correctly Produces: http://localhost:3000/meetings/2/presentations/destroy/1
Your help would go a long way to clearing up my routing haziness. Thanks so much!
EDIT
Here's the non-working routes.rb file in its entirety:
UserGroup::Application.routes.draw do
get "presentations/new"
get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
#default route
match ':controller(/:action(/:id(.:format)))'
end
EDIT 2
Thanks to codykrieger I took a look at the rest of the routes file (I know, duh right?). Apparently, all those get "..." routes are added when using the rails generator and help to make some default connections in the app. I commented out the get "presentations/edit" line and, wonder of wonders, my routing adaptation actually does work.
This works:
UserGroup::Application.routes.draw do
get "presentations/new"
#get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
#default route
match ':controller(/:action(/:id(.:format)))'
end
I played around with the order of the routes in the file and also found that if I put my route above all the auto-generated routes, without commenting out the get "presentations/edit" line, my route still has the intended effect.
This also works:
UserGroup::Application.routes.draw do
match 'meetings/:meeting_id/presentations/:action/:id', :to => 'presentations', :constraints => {:id => /\d/}
get "presentations/new"
get "presentations/edit"
get "sessions/new"
get "users/index"
get "users/show"
get "users/new"
get "users/edit"
get "meetings/index"
match '/meetings/show/:id', :to => 'meetings#show', :as => 'meeting'
match '/meetings/new', :to => 'meetings#new', :as => 'new_meeting'
match '/meetings/edit/:id', :to => 'meetings#edit', :as => 'edit_meeting'
#default route
match ':controller(/:action(/:id(.:format)))'
end
I'm thinking that the latter is the better way to go and I should make my custom routing declarations above the standard generated ones, but I'm not sure. If someone out there wants to comment on which practice is better, or if it's better to entirely remove the generated ones if I want to specify my own, I'd love to hear it.
Thanks all :)
Routing is done on a first match basis (top to bottom) in the routes.rb file.
So you can keep all routes as you have done above if you want, and Rails will use the first one that matches. However, its messy, potentially buggy and totally unnecessary. So the "match..." lines in your code should be enough, and you can remove the "get..." lines.
Furthermore, your "match...presentations...." line has a bug, it should be
...{:id => /\d+/}
else it will validate only 1-digit length ids.
Finally, as far as your overall routes.rb is concerned, you do not need to do
link_to 'edit', :controller => 'presentations',
:action => 'edit',
:meeting_id => presentation.meeting.id,
:id => presentation.id
Instead, you should use edit_meeting_path, new_meeting_path etc. For instance
<%= link_to "New meeting", new_meeting_path %>
<%= link_to "Edit meeting", edit_meeting_path(#meeting) %>
Finally, you should read Rails Routing from the Outside In for best practices on how to design nested routes etc.