Active Admin: Customize only new form - ruby-on-rails

I'm using Active Admin to provide an admin to some models. I need to provide a customized new form for one of them, but leave the edit form as the default provided by Active Admin. Here's what I have. It works in that it is giving me the new form I want, but the edit form is also using the new form, which is not what I want:
ActiveAdmin.register Document do
form :partial => 'form'
end
I've tried this, but it gives an error that 'new' is an undefined method:
ActiveAdmin.register Document do
new do
form :partial => 'form'
end
end

If you just want to hide or show certain fields on the new form (e.g. a field that you generate automatically in the model using before_create), you can do this:
form do |f|
f.inputs "Member Details" do
f.input :first_name
f.input :last_name
f.input :email
if !f.object.new_record?
f.input :password
f.input :password_confirmation
end
end
f.button :Submit
end
This will hide the password fields when you create a new member in the event that you automatically generate passwords the first time the member is created.

I've figured out a way to do it with some logic in the view. Not the best way, to be sure, but it does what I want until I figure out a better way. Here's the logic I'm using:
<% if controller.action_name == 'new' %>
new form
<% else %>
edit form
<% end -%>

I am not sure it can be done directly with form. If you take a look at the code you'll see that only the last call is taken into account. On the other hand, you may try something like:
config.set_page_config :new do
form :partial => 'form'
end
But I would rather ask the developers for this feature.

If someone wants to render different partials for new and edit pages you have to:
#app/admin/document.rb
ActiveAdmin.register Document do
form partial: 'form'
end
#app/views/admin/documents/_form.html.erb
<% if #document.new_record? %>
<%= render partial: "form_new", resource: #document %>
<% else %>
<%= render partial: "form_edit", resource: #document %>
<% end %>
#app/views/admin/documents/_form_new.html.erb
<%= semantic_form_for [:admin, #document], builder: Formtastic::FormBuilder do |f| %>
<%= f.semantic_errors %>
<%= f.inputs do %>
<%= f.input :name %>
<% end %>
<%= f.actions %>
<% end %>

You could create a custom page that acts as the new form, render a partial there which contains arbitrary form code.
So, in your admin directory you make a file new_document.rb containing
ActiveAdmin.register_page "New Document" do
content do
panel "Create a new document" do
render :partial => "admin/documents/custom_form", :locals => {document: Document.new}
end
end
end
You then put your arbitrary formtastic form in admin/documents/custom_form and your arbitrary controller action aka collection_action in admin/documents.
So basically doing normal rails type stuff within the activeadmin framework.

Related

Update Attributes of a Specific Record

Let's say I have a bunch of cards listed on my wall show action. When you interact with a card (click it for example), I want to update that card's attributes.
I'm currently doing this by getting the card's attributes with Javascript, adding them to a card form and submitting the form remotely.
I have the card's ID, but how do I tell the form which card I want to update?
What should the form and controller update action look like?
This is what I have so far
Form
<%= form_for(#card, remote: true) do |f| %>
<%= f.text_field :list_id %>
<%= f.text_field :order %>
<% end %>
Controller
def update
#card = Card.find(params[:id])
if #card.update_attributes(shared_params)
redirect_to edit_card_path(#card, format: :html)
else
render :edit
end
end
You can use the same new template for edit too. The only requirement here is the object you wanted to edit.
So, first get you edit action ready in controller as
def edit
#card = Card.find(params[:id])
end
edit/new.html.erb
<%= form_for(#card, remote: true) do |f| %>
<%= f.text_field :list_id %>
<%= f.text_field :order %>
<% end %>
In the cards show page, add a link to the edit action as
<%= link_to "Edit", edit_card_path(card.id) %>

rails, form_for in a secon route, but on the same model

In a rails 4 application, I have a book resource, that is a Book model with its controller, views and route. It's what gets created by:
rails g scaffold book title
Now I want to have another set of views (and another controller) that allows to manage the same model, maybe dedicated to a different user.
I want both the creating function and the editing function to be available on this different route and view, .
Let's call it book2.
The views in the /book2 url should operate on the Book2sController.
form_for support
But the form_for guesses the submit route (and puts it in the action attribute) from the model class, that, being it always Book, lets rails guess that the submit url is /books/1 for edit or /books/ for new and not /book2s/1 for edit and /book2s/ for new as it should be.
So i found this solution, but i find it to be a bit cumbersome.
Is there anything better out there?
<%= form_for #book, :url => #book.new_record? ? url_for(book2s_path) : url_for(book2_path(#book)) do |f| %>
<%= f.text_field :title %>
<% end %>
You could set the url in your controller.
def new
# ...
#form_url = book2s_path
# ...
end
def edit
# ...
#form_url = book2_path(#book)
# ...
end
Then your view becomes:
<%= form_for #book, :url => #form_url do |f| %>
<%= f.text_field :title %>
<% end %>
I have also seen:
<%= form_for #book, :url => {:controller => 'book2s', :action => #action} do |f| %>
<%= f.text_field :title %>
<% end %>
and you just set #action in the controller (probably create or update).
Note that you don't need to include the url_for like you have.

Rails linking form submission to object

In a rails project I have two entities, Users and Institutions, they have a many-to-many relationship.
The views for them are set up to create new users and institutions but I want to have another view for linking the two.
In rails console all I have to do is
myuser.institutions << the_institution_i_just_created
The controller can do some of the work but how do I handle the submissions and the forms? I want to use a selection box so that the input is limited to the Institutions already in existence.
<select id="institution_selection" name="institution_sel">
<% selections = []
Institution.all.each do |institution|
pair = [institution.name, institution.id]
selections.concat([pair])
end
%>
<%= options_for_select(selections) %>
</select>
So the question in summary is how do I map this submission to an object so that in the controller I can do add it to the relation?
The solution was:
Alright, so this is the solution I came up with, I'm sure there is a better way to go about it and I'll continue to look into it but at least I got something close to what I was aiming for
def test
if !session[:user]
redirect_to users_path, notice: "Please login first"
end
if params[:institution]
#user = User.find(session[:user])
#institution = Institution.find(params[:institution][:id])
#user.institutions << #institution
redirect_to #user, notice: "Institution was successfully added "
end
end
and for the view
<%= form_tag("/users/test", :method => "post") do %>
<%= collection_select :institution, :id, Institution.all, :id, :name %>
<%= submit_tag("Search") %>
<% end %>
Use collection_select
<% from for #instancevar do |form| %>
<%= form.collection_select :institution_id, Institution.all, :id, :name %>
# Do other stuff....
<% end %>

Rails partial view set value of form field

Okay so I am quite new to Rails and am trying to do the following without success:
I have an Object (from my Active Record) containing a project, which contains n sub-projects, which contain n tasks. Now for each of these I want a partial view.
So I render from the project view the sub-project with the following code:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
Within my sub-project partial view called _subproject.rhtml (adding the code to a good ol Rails 1.2.3 project), so I can access the data like this:
<%= subproject.name %>
That will print out the name alright but when I try to generate a textfield this won't work:
<%= text_field 'subproject', 'name' %>
But this will:
<%= text_field 'subproject', 'name', :value => subproject.name %>
What am I doing wrong?
Edit: Changed title due to my problem is not passing the value but displaying it within a form field.
Edit2: As requested my controller code:
#project = Project.find(params[:id])
You can write this:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
as
<%= render :partial => #project.sub_projects %>
This will render every sub project with the sub_projects/_sub_project.html.erb partial. A little shortcut.
This:
<%= text_field 'subproject', 'name' %>
Says create a text_field called: subproject[name], but doesn't give it a value. You need to pass the value you want to set (the code that works).
The more idiomatic way of doing this now is with form_for:
<% form_for #subproject do |f| %>
<%= f.text_field :name %>
<% end %>
Or if you're using formtastic (https://github.com/justinfrench/formtastic), which is fantastic, you'd write:
<% semantic_form_for #subproject do |f| %>
<%= f.input :name %>
<% end %>
I hope this helps!

Rails: what is the “correct” (idiomatic) way to pass a parameter from new to create in a RESTful controller?

I have a very common situation and a solution, but I would like to ask the Rails experts out there if it can be improved.
I have a very typical RESTful controller where the user supplies some of the object attributes upon creation. There is a thing model, a ThingsController and various views, including new, create, and a _form partial.
A thing has two attributes,
a color, which is set when they hit a link to create it (i.e. a “Create Red Thing” link that encodes the ID of red as a URL parameter)
a description, which is entered by the user in the form view
I’m happy with the approach for dealing with an attribute like the description that that a user specifies in the form, but less confident about the way that I handle an attribute that is passed through via the URL parameters associated with the first click.
This is what I am doing right now (note that I have omitted error checking to simplify matters). First, my new and create methods in the controller are as follows:
def new
#thing = Thing.new
#thing.color = Color. find(params[:color])
end
def create
#thing = Thing.new(params[:thing])
#thing.color = Color. find(params[:color])
if #thing.save
flash[:notice] = "Successfully created thing."
redirect_to somewhere_url
else
render :action => 'new'
end
end
The new view just invokes the _form partial, which looks as follows:
<% form_for #thing do |f| %>
<%= f.error_messages %>
<%= hidden_field_tag "color", #thing.color.id %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.submit "Submit" %>
<% end %>
It seems a little messy to be passing the color ID through to the create method as a URL parameter by putting a hidden field in the form. Does this look reasonable, or is there another approach that would be better?
Normally in this situation, I would put a hidden field in the form, which will hold the color_id. The nice thing about this way is that you can get by with just setting the color of the object before you render the form. So your controller changes to:
def new
#thing = Thing.new
#thing.color = Color. find(params[:color])
end
def create
#thing = Thing.new(params[:thing])
if #thing.save
flash[:notice] = "Successfully created thing."
redirect_to somewhere_url
else
render :action => 'new'
end
end
and your form will change to
<% form_for #thing do |f| %>
<%= f.error_messages %>
<%= f.hidden_field :color_id %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.submit "Submit" %>
<% end %>
The color is then passed through both forms, and you only need to retrieve the color in the first form. (Don't forget to add validations your Thing model to make sure it has a valid color though).

Resources