Getting Formtastic in ActiveAdmin to use custom form input builder - ruby-on-rails

UPDATE: So, I've found this, and apparently that's why this old way of doing things isn't working, ActiveAdmin must use Formtastic 2.x. As directed, I've now created a file in app/inputs/date_picker_input.rb that looks like this:
class DatePickerInput
include Formtastic::Inputs::Base
def to_html
puts "this is my datepickerinput"
end
end
And my controller now looks like this:
f.input :open_date, :as => :date_picker
f.input :close_date, :as => :date_picker
But now I'm running into this error:
ActionView::Template::Error (undefined method 'html_safe' for nil:NilClass):
1: render renderer_for(:edit)
Any thoughts?
I've ran into a problem with Formtastic automatically formatting dates into a format I'm not wanting (Y-m-d h:i:s Z) when I try to render :as => string so I can use a datepicker on the field. In trying to solve this, I came across this solution.
It seems to make sense and is the exact same problem I am dealing with. However, I don't seem to be able to implement the fix, and I'm wondering if it's because Formtastic is being used through ActiveAdmin. So, here's what I've tried to do:
In the controller, I've changed the method as such:
f.input :open_date, :as => :date
I also tried this, though my problem is not even being able to get to this point:
f.input :open_date, :as => :date_input
I created a file at lib/datebuilder.rb with the following code:
class DateBuilder < Formtastic::SemanticFormBuilder
def date_input(method, options)
current_value = #object.send(method)
html_options ||= {:value => current_value ? I18n.l (current_value) : #object.send("#{method}_before_type_cast")}
self.label(method, options.delete(:label), options.slice (:required)) +
self.send(:text_field, method, html_options)
end
end
I'm not sure that will even fix the format as I want, but I assume if I can just get Formtastic to use this method I can alter it as needed (currently took this from the solution mentioned in link above).
This article mentions you need to add a line to your formtastic intializer to use this custom input:
Formtastic::SemanticFormHelper.builder = Formtastic::DateBuilder
I did not have this initializer file in config/initializers so I added it (config/initializers/formtastic.rb) with the line above. The problem I am now running into is this error when trying to startup the Rails app:
../config/initializers/formtastic.rb:1:in '<top (required)>': uninitialized constant Formtastic::SemanticFormHelper (NameError)
I have also tried this syntax in that file instead:
module Formtastic
module SemanticFormHelper
self.builder = DateBuilder
end
end
which gives me this error instead: ../config/initializers/formtastic.rb:3:in '<module:SemanticFormHelper>': uninitialized constant Formtastic::SemanticFormHelper::DateBuilder (NameError)
If I'm going about this in completely the wrong way please let me know, otherwise any help on getting Formtastic to use this custom input type would be amazing!

Alright, finally figured out the right way to do this.
My controller stayed the same as seen above in the update. However, here's what I changed the DatePicker custom input file (app/inputs/date_picker_input.rb) to look like:
class DatePickerInput < Formtastic::Inputs::StringInput
def to_html
"<li class='string input required stringish' id='question_#{method.to_s}_input'>" +
"<label class=' label' for='question_#{method.to_s}'>#{method.to_s.gsub!(/_/, ' ').titleize}*</label>" +
"<input id='question_#{method.to_s}' name='question[#{method.to_s}]' type='text' value='#{object.send(method)}' class='hasDatePicker'>" +
"</li>"
end
end
Hopefully this will help someone else running into the same problem! Btw, the hard-coded "question" and "required" is because I will only use this custom input on question objects. There is likely a way to dynamically get this information, but I decided against putting more work in to figure that out (this was enough of a headache on its own!)

Related

Call helper method from custom view Rails

In ApplicationHelper, I have method called finTime.
def finTime(time)
end
In delayed_job I have render_to_string function
class ExportJob < Struct.new(:time1,:time2, :survey_id)
def perform
ac = ActionController::Base.new()
html = ac.render_to_string(:template => "pages/exportPdf.html.erb",:layout => "layouts/exportPdf",:formats => :html
end
end
In exportPdf.html.erb I call the function finTime
<%= finTime(f.created_at) %>
I got the error: "ActionView::Template:Error: undefined method 'finTime' for #<#Class:0x6db8eb0>: 0x8321928>"
So I want to ask how I can call finTime method from exportPdf.html.erb in this case. I tried to use include and helper but it does not work.
Thank you!
There's not a lot of information to go on here, but one possibility could be that in your definition there are no arguments - it's just finTime
but in the call you give an argument of f.created_at - maybe that's causing the error, maybe not. what is the full error?
related, the general practice for method names is snake case, so finTime should be fin_time.
edit: Without seeing more of your code it's still difficult, for example
<%= finTime(f.created_at) %>
Is that what it's in your code? finTime() is a method, so it has to be called on a model - model.finTime(time)
there's also an end parenthesis missing from this line:
html = ac.render_to_string(:template => "pages/exportPdf.html.erb",:layout => "layouts/exportPdf",:formats => :html
if both of those things are only problems in your question, and not in your code, try replacing finTime() with inspect or methods in your partial and see what happens. If there's still an error, you'll know you have to look elsewhere, and if not you'll get some information that might help you sort out the trouble. Good luck!

Remove html tags from I18n "translation missing" messages

Consider the following code in a view:
<%= link_to 'Delete!', item , :confirm => t('action.item.confirm_deletion'), :method => :delete %>
It will normally come out as:
Delete!
But if the translation for action.item.confirm_deletion is missing for some reason (incomplete yml-file, typos, etc.) it comes out as:
Confirm Deletion</span>" data-method="delete" rel="nofollow">Delete!
which is invalid html, and user will see broken html tags on the homepage.
It may also be a security risk in some cases.
I know that I could use apply some escaping on every call to the I18n.t function, but that feels unnecessarily repetitive for the task.
So my question is:
Is there a way to make the "translation missing"-messages not contain html code.
There are multiple solutions for you.
You can alias the translation method to your own and call with the custom :default value (I would prefer this way):
module ActionView
module Helpers
module TranslationHelper
alias_method :translate_without_default :translate
def translate(key, options = {})
options.merge!(:default => "translation missing: #{key}") unless options.key?(:default)
translate_without_default(key, options)
end
end
end
end
Or you can overwrite the default value:
module I18n
class MissingTranslation
def html_message
"translation missing: #{keys.join('.')}"
end
end
end
In rails 4.2 you have to redefine the translate helper in the view:
https://github.com/rails/rails/blob/v4.2.5/actionview/lib/action_view/helpers/translation_helper.rb#L78
In rails 5 you can set in your application.rb:
config.action_view.debug_missing_translation = false

Dynamic Find By In Rails 3

So, I have a very simple bit of code that works great in Rails 2, but breaks in Rails 3.
In Rails 2 I have the following for displaying page contents using a viewer controller from the Page model:
class ViewerController < ApplicationController
show
#page = Page.find_by_name(params[:name])
end
My viewer show view has the following:
<%= #page.body %>
My routes.rb file has the following to handle this action:
map.view_page ":name", :controller => 'viewer', :action => 'show'
Here is the error I get in Rails 3 using this code:
undefined method `body' for nil:NilClass
Now, I know the routes have to be changed in Rails 3, but what else am I missing to make this simple code work in a Rails 3 app? I can't seem to find the answer anywhere. Thanks!
match ":name", :to => "viewer#show", :as => "view_page"
Not tested not sure if it's match "/:name" or if ":name" is ok too.
Ok, Rails 3 have got new routing sintax
get "/:name" => 'viewer#show'
Useful links:
http://railscasts.com/episodes/203-routing-in-rails-3
http://guides.rubyonrails.org/routing.html
http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/
UPD
Your error is because Rails can't find any Page with your :name:
There is no any Page with this name
There is no any :name at all in your params hash
Make sure your database has the body field filled with something and it should work just like you have it.
domain.com/viewer/show?name=home

How to render a Partial from a Model in Rails 2.3.5

I have a Rails 2.3.5 application and Im trying to render several Partials from within a Model (i know, i know -- im not supposed to). The reason im doing this is im integrating a Comet server (APE) into my Rails app and need to push updates out based on the Model's events (ex. after_create).
I have tried doing this:
ActionView::Base.new(Rails::Configuration.new.view_path).render(:partial => "pages/show", :locals => {:page => self})
Which allows me to render simple partials that don't user helpers, however if I try to user a link_to in my partial, i receive an error stating:
undefined method `url_for' for nil:NilClass
I've made sure that the object being passed into the "project_path(project)" is not nil. I've also tried including:
include ActionView::Helpers::UrlHelper
include ActionController::UrlWriter
in the Module that contains the method that makes the above "render" call.
Does anyone know how to work around this?
Thanks
We use the render_anywhere gem and have been happy with it.
From the README:
require 'render_anywhere'
class AnyClass
include RenderAnwhere
def build_html
html = render :template => 'normal/template/reference',
:layout => 'application'
html
end
end
Including these two modules should be enough. Maybe you forgot to set default_url_options[:host]? Without it you can use _path helpers, but not _url ones.
Include these modules and check out if it works in irb, maybe it will lead you to right solution.

Has namedspaced routing changed in Rails 2.3?

I have an admin namespace which gives me the usual routes such as admin_projects and admin_project, however they are not behaving in the usual way. This is my first Rails 2.3 project so maybe related I can't find any info via Google however.
map.namespace(:admin) do |admin|
admin.resources :projects
end
The strange thing is for a given URL (eg. /admin/projects/1) I don't have to pass in an object to get URL's it somehow guesses them:
<%= admin_project_path %> # => /admin/projects/1
No worries, not really a problem just not noticed this before.
But if I try and pass an object as is usual:
<%= admin_project_path(#project) %> # => admin_project_url failed to generate from {:controller=>"admin/projects", :action=>"show", :id=>#<Project id: 1, name: "teamc...>
":id" seems to contain the entire object, so I try passing the id directly and it works:
<%= admin_project_path(#project.id) %> # => /admin/projects/1
This would not be so bad but when it comes to forms I usually use [:admin, #object], however:
<%= url_for [:admin, #project.id] %> # => undefined method `admin_fixnum_path'
So I can't pass in an id, as it needs an objects class to work out the correct route to use.
<%= url_for [:admin, #project] %> # => Unfortunately this yields the same error as passing a object to admin_project_path, which is what it is calling.
I can't spot any mistakes and this is pretty standard so I'm not sure what is going wrong...
Interesting. What happens when you define a to_param method on Project? For instance
class Project < ActiveRecord::Base
def to_param
self.id
end
end
This should be the default and this shouldnt be necessary. But what happens if you make it explicit? Try adding the above method then going back to your original approach of only passing around #project
I wish I could help you on this one. We have a large application with several namespaced sections. Our routes are defined in the exact method you have described and we are calling our path helper with objects. No where in the application are we accessing using the id.
Our application started on Rails 2.1 and has transitioned through 2.2 and 2.3 with no significant changes to the routing. Sorry I couldn't be more help.
Peer

Resources