How can I use a datepicker in ActiveAdmin without rewriting the create form? - ruby-on-rails-5

My ActiveAdmin model creation forms (ie. /admin/<model>/new) are using an awkward set of dropdowns for dates and datetimes.
I'd like to use pickers instead. But all the documentation I've found about using a datetime picker appears to require rewriting the whole form. There doesn't seem to be a way to change just one input, nor an equivalent of preserve_default_filters!.
I'd like to either change the default for all date and datetime columns, something like...
config.datepicker = ...
Or per column, like...
column :signed_up, as: :datetime_picker
EDIT
By default I get new and edit forms equivalent to this.
form do |f|
f.semantic_errors
f.inputs
f.actions
end
If I want to change signed_up to use a datepicker, I have to repeat all the columns supplied by default just to change the input type of one column.
ActiveAdmin.register Thing do
form do |f|
t.semantic_errors
t.input :name
t.input :this
t.input :that
t.input :signed_up, as: :datepicker
t.input :other
t.input :thing
t.input :left
t.input :right
t.actions
end
end
That's a lot of unnecessary repetition, and the formatting doesn't come out right. I'm looking for a way to change the input presentation of one column, or one type, without having to manually write the whole form every time.

Try the DateNTimePickerActiveAdmin Rubygem. It works really well and is customisable according to your project.
You can find the documentation here: https://github.com/NikhithaGraceJosh/date_n_time_picker_activeadmin
From the docs:
Gemfile
gem 'date_n_time_picker_activeadmin'
Code Sample (In your form)
f.input :column_name, as: :datetimepicker
CSS
In active_admin.scss, add the line,
#import date_n_time_picker_activeadmin
JS
In active_admin.js, add the line,
//= require date_n_time_picker_activeadmin
Hope it's useful!

I managed to monkey patch Active Admin behavior, to use :datepicker instead of :date_select.
In your config/application.rb, add following patches
Bundler.require(*Rails.groups)
// Start patch
module ActiveAdminFormBuilderPatch
def default_input_type(*_args, **_kwargs)
ret = super
ret == :date_select ? :datepicker : ret
end
end
ActiveAdmin::FormBuilder.include ActiveAdminFormBuilderPatch
// end patch
module YourApp
class Application < Rails::Application
// configs
end
end
Note
Confirmed this to be working on activeadmin version 2.9.0.

I used activeadmin_addons which does a lot of useful things, including using DateTimePicker for input, but not filters.
To get filters I use active_admin_datetimepicker which makes jQuery DateTimePicker available for inputs (:date_time_picker) and filters (:date_time_range). Then I monkey patched ActiveAdmin to use it by default.
# config/initializers/active_admin.rb
# Make the default filter type for a DateTime to be the DateTimeRange picker.
class ActiveAdmin::Filters::FormBuilder
protected
alias_method :original_default_input_type, :default_input_type
def default_input_type(method, options = {})
case column_for(method)&.type
when :datetime
return :date_time_range
end
original_default_input_type(method, options)
end
end

Related

How can I use the method (helper) defined in a view in another view?

Let's say I have a form defined in View
module Admin
module Views
module Dashboard
class New
include Admin::View
def form
form_for :link, routes.links_path do
text_field :url
submit 'Create'
end
end
...
Am I missing something? since example below doesn't work:
module Admin
module Views
module Dashboard
class Index
include Admin::View
include Dashboard::New
...
You can't to share code from one view to another this way.
Your snippet does not work because Ruby does not allow to include classes in to another classes. So, if you want to do this - you should to use helper module. For your case it should looks like this:
module Admin
module Helpers
module Dashboard
def form
form_for :link, routes.links_path do
text_field :url
submit 'Create'
end
end
end
end
end
and include it in your view
module Admin
module Views
module Dashboard
class New
include Admin::View
include Admin::Helpers::Dashboard
# ...
end
end
end
end
or include it globally in your app
# apps/admin/application.rb
view.prepare do
include Hanami::Helpers
include Admin::Helpers::Dashboard
end
documentation: https://guides.hanamirb.org/helpers/custom-helpers/

Cannot find FakeInput

I am trying add a fake input to simple_form using the following suggestion (rails simple_form fields not related to the model), but it does not work for me.
This is my HAML code for adding a fake input field.
= f.input :agrees_to_terms, :as => :fake
I put the following class in 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
template.text_field_tag(attribute_name, nil, input_html_options)
end
end
I get the following runtime error
No input found for fake
I have two initializers that were generated by Rails Composer: simple_form.rb and simple_form_bootstrap.rb
How can I make Rails find my FakeInput class?
I had the same issue, and a server restart resolved it.

Can we force rspec stub_model to populate created_at column to Time:now

Am using twitter bootstrap gem to generate the views which displays the created_at column in the index page. The rspec tests which are generated along with the scaffolds use stub_model to test the index view. These test fails because created_at column in nil.
Just as stub_model generates as dummy id, can it also set the created_at column as Time.now. can that be done via config. or do we need to specify it each time while creating a stub.
Judging from the source code, this doesn't seem to be possible by default. This leaves you with a few options:
1. Specify the created_at value each time you create a model stub:
m = stub_model(MyModel, :created_at => Time.now)
2. Create your own helper method which sets the created_at attribute after initializing the stub:
module Helpers
def stub_model_with_timestamp(model_class, stubs={})
stub_model(model_class, { :created_at => Time.now }.merge(stubs))
end
end
Then just include the module in spec_helper.rb so it is available in all specs:
RSpec.configure do |config|
include Helpers
...
end
3. If you really want to use stub_method as-is, you could monkey-patch rspec-rails to make it work the way you want by re-opening the module and aliasing the original method:
module RSpec::Rails::Mocks
def stub_model_with_timestamp(model_class, stubs={})
stub_model_without_timestamp(model_class, { :created_at => Time.now }.merge(stubs))
end
alias_method_chain :stub_model, :timestamp
end
Put this in a file in spec/support/ and it will load automatically, so when you stub a model it will automatically set the created_at timestamp.
As a final note, I think this is useful functionality that others might also want to use, so you might consider actually making a pull request to rspec-rails that adds the default setting as a config option. (I think if you do, you'd probably want to also set updated_at as well, for completeness.)
Hope that helps!
I added the following to my spec_helper.rb:
module RSpec::Rails::Mocks
def stub_model_with_timestamp(*args)
stub_model_without_timestamp(*args).tap{|o| o.created_at ||= Time.now }
end
alias_method_chain :stub_model, :timestamp
end
The other solution had trouble with "*args, :created_at => Time.now", as it adds an additional parameter to the stub call.

RoR 3.0.9 - Passing a variable from routes.rb to application_controller.rb or viceversa

I have a multi site project that changes from one to another by changing two variables, one is inside routes.rb and the other in application_controller.rb. Is it possible to pass variables between these files so that I only have to change a parameter to achieve the change required?
On my routes.rb file I use this variable to assign the correct controller the routes it should use. For example:
def showsite
"mysite1"
end
root :to => "#{showsite}#index"
And on application_controller.rb I use the same parameter to get the domain of the site, some layouts it should use and another things. For example:
before_filter :set_defaults
def showsite
"mysite1"
end
def set_defaults
if "#{showsite}" == "mysite1"
#domain = 'mysite1.com'
elsif "#{showsite}" == "mysite2"
#domain = 'mysite2.com'
else
#domain.nil?
end
end
def special_layout
"#{showsite}"
end
Every time I want to show a different version of the project I need to change two variables. I know its not a lot but I have to do it many times a day. Im pretty new on RoR, if there is a better solution please guide me to it. Thanks!
Why not use a Rails Initializer. E.g. the following:
File: `config/initializers/showsite.rb`
with the following content:
MyApp::Application.config.showsite = 'mysite1'
Then you should be able to use:
def showsite
MyApp::Application.config.showsite
end
and similar in your routes file.

How to user defined friendly URLs in Rails 3?

Now i have something like this
http://myapp.com/pages/1
http://myapp.com/pages/2
http://myapp.com/pages/3
http://myapp.com/pages/4
And each page belong to one user
What i need is to each user to set it's own custom name for the page.
I was thinking of using the friendly_id gem http://norman.github.com/friendly_id/
but I don't find any method to directly edit the slug to set a custom friendly url
how should i proceed?
FriendlyID is a great gem.
It shouldn't be hard to implement user defined page URL.
Create table pages with user_id and link
class User < ActiveRecord::Base
has_many :pages
class Page < ActiveRecord::Base
belongs_to :user
has_friendly_id :link # link is name of the column whose value will be replaced by slugged value
On the page#new you add an input for the link attribute.
Alternatively, you could set friendly_id on title or something else with :use_slug => true option. This way FriendlyID will take the title and modify it so it doesn't have and restricted characters. It will use it's own table to store slugs. Use cached_slug to increase performanse.
Updated
To give users a choice whether they wan't to set a custom link, you could do this:
Set friendly_id on the link field without slugs..
Make a virtual attribute permalink so you could show it in your forms.
In the before_filter, check whether the permalink is set.
If it is, write it to the link field.
If it's not, write title to the link field.
FriendlyID uses babosa gem to generate slugs. If you decide to use it as well, this is how your filter could look like:
protected
def generate_link
#you might need to use .nil? instead
self.link = self.permalink.empty? ? make_slug(self.title) : make_slug(self.permalink)
end
def make_slug(value)
value.to_slug.normalize.to_s #you could as well use ph6py's way
end
Adding to_param method to one of the models should help:
def to_param
"#{id}-#{call_to_method_that_returns_custom_name.parameterize}"
end
Hope this is what you are looking for :)
I am not using the friendly_url gem and am not sure whether my way is efficient. But it works fine for me.
I have a model called Node with id and friendly url field called url_title.
My routes.rb file:
resource 'nodes/:url_title', :to => 'Nodes#view'
nodes_controller.rb
class NodesController <ActiveController
def view
#node = Node.find_by_url_title(:params(url_title))
end
end
And use the #node variable to populate your view.
Now, whenever I type www.example.com/nodes/awesome-title , it takes me to the proper page. One argument against this can be need to create an index on a non-primary field. But I think that might be required for better performance even in the friendly_url gem. Also, the non-primary field url_title needs to be unique. Again, this might be required even for correct working for friendly_url .
Feel free to correct me if I am wrong in these assumptions.
There are a variety of ways, you can achieve this-
1) using Stringex
2) sluggable-finder
3) friendly_id
A complete step by step methodology with reasons for each to be used can be found out here. Happy reading!