Nested rails form with checkboxes HASBTM - ruby-on-rails

I have form partial that allows the user to enter the subject and message that will be included in the outbound email. I want to allow the users to select the recipients of the email from the contacts that are associated with the invoice that the email belongs to. The email recipients that are selected through the nested form are to be stored in a separate table.
class EmailRecipient < ActiveRecord::Base
attr_accessible :contact_id, :email_id
belongs_to :email
end
class Email < ActiveRecord::Base
attr_accessible :subject, :message, :invoice_id, :email_recipients_attributes
belongs_to :invoice
has_many :email_recipients
accepts_nested_attributes_for :email_recipients
end
<%= simple_form_for [:invoice, #email], html: {class: "form-horizontal"} do |f| %>
<%= f.error_notification %>
<% #invoice.contacts do |c|%>
<%= f.fields_for :email_recipients do |builder| %>
<%= builder.input :contact_id, :as => :check_boxes %>
<%= c.name %><br/>
<% end %>
<% end %>
<%= f.input :subject, :as => "string" %>
<%= f.input :message, :input_html => { :class => 'span7', :rows => 10 } %>
<div class="form-actions">
<%= f.button :submit, "Send Invoice", :class => 'btn-warning' %>
<%= link_to 'Cancel', invoice_path(#invoice), :class => 'btn' %>
</div>
<% end %>

This isn't the prettiest answer, so I would love to see a better solution, but it gets the job done until my skills improve.
In the controller for the parent form I added:
#invoice.contacts.each { |c| #email.email_recipients.build(contact_id: c.id) }
This builds the records for all contacts whether they are needed or not. Then in the form partial I modified the nested form:
<%= simple_form_for [:invoice, #email], html: {class: "form-horizontal"} do |f| %>
<%= f.error_notification %>
<% count = 0 %>
<%= f.simple_fields_for :email_recipients do |email_recipients_form| %>
<%= email_recipients_form.input :_destroy, as: :boolean, :label => false do %>
<%= email_recipients_form.check_box :_destroy, {}, "false", "true" %>
<% contact = #invoice.contacts.find(#email.email_recipients[count].contact_id) %>
<%= contact.name + " (" + contact.email + ")" %>
<% end %>
<%= email_recipients_form.input :contact_id, as: :hidden %>
<% count += 1 %>
<% end %>

Related

Simple Form simple_fields_for only show last record

I have a nested simple form to edit a user. The user has a profile he/she can update, and a new record is written to the profile table.
simple_fields_for shows all profile records of a user due to the relationship user 1 to many profile records. However, I would like to only show the newest profile record in the form! How can I accomplish that?
<%= simple_form_for(#user) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :lang %>
<%= f.input :firstname %>
<%= f.input :lastname %>
<%= f.input :email %>
<%= f.input :born %>
<%= f.input :gender %>
<%= f.simple_fields_for :profile do |p| %> # the magic needed here
<%= p.input :postal_code %>
<%= p.input :core %>
<%= p.input :daytime %>
<%= p.input :style %>
<% end %>
<% if #is_new %>
<%= f.simple_fields_for :status do |s| %>
<%= s.input :entered, as: :hidden, input_html: { value: Time.current } %>
<% end %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Little late, but accepted answer is not 100% accurate. (Would just make this a comment, but no rep.) I would do this like so:
Assuming you have
class User < ActiveRecord::Base
has_many :profiles
...
def latest_profile
profiles.order(...) # query to get whatever record it is you want
end
end
your simple_fields_for can just be
<%= f.simple_fields_for :profiles, f.object.latest_profile do |p| %>
Note the pluralization of :profiles, and that we don't need to clutter the controller with an additional instance variable because you can access the object in the form. (Using the singular will work I believe, but you will not get params with a key in the form of :profiles_attributes, meaning even more code to account for unique params.)
The edit action:
class user > ApplicationController
...
def edit
#profile = #user.profile.order("saved DESC").first
end
...
end
The working form:
<%= simple_form_for(#user) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :lang %>
<%= f.input :firstname %>
<%= f.input :lastname %>
<%= f.input :email %>
<%= f.input :born %>
<%= f.input :gender %>
<%= f.simple_fields_for :profile, #profile do |p| %> # the magic needed here
<%= p.input :postal_code %>
<%= p.input :core %>
<%= p.input :daytime %>
<%= p.input :style %>
<% end %>
<% if #is_new %>
<%= f.simple_fields_for :status do |s| %>
<%= s.input :entered, as: :hidden, input_html: { value: Time.current } %>
<% end %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>

Rails Form Object Returns Object ID in mail

I have the below form which works absolute fine but when submitted the :event field returns an ID in the mailer, any ideas how to prevent this?
Form
<%= simple_form_for #sponsorship_inquiry, :method => :post do |f| %>
<%= f.input :spam, as: :hidden %>
<%= f.input :name %>
<%= f.input :phone %>
<%= f.input :email %>
<%= f.input :job_title %>
<%= f.input :company %>
<%= f.input :event, :collection => Event.where(:end_date.gt => Date.today, :is_live => 'true') %>
<%= f.input :message, as: :text, :input_html => { :cols => 5, :rows => 6 } %>
<%= f.button :submit %>
<% end %>
Mailer
Name: <%= #sponsorship_inquiry.name %>
Phone: <%= #sponsorship_inquiry.name %>
E-Mail: <%= #sponsorship_inquiry.email %>
Job Title: <%= #sponsorship_inquiry.job_title %>
Company: <%= #sponsorship_inquiry.company %>
Event: <%= #sponsorship_inquiry.event %>
Message: <%= #sponsorship_inquiry.message %>
Controller
def new
#sponsorship_inquiry = SponsorshipInquiry.new
end
def create
# Hidden field for bots/spiders
redirect_to new_inquiry_path and return if params[:spam].present?
#sponsorship_inquiry = SponsorshipInquiry.new(params[:sponsorship_inquiry])
if #sponsorship_inquiry.valid?
SponsorshipInquiryMailer.admin(#sponsorship_inquiry).deliver
redirect_to sponsorship_inquiries_path
else
render :new
end
end
Need your SponsorshipInquiry model.
If you have
class SponsorshipInquiry < ActiveRecord::Base
belongs_to :event
end
try send <%= #sponsorship_inquiry.event.name %> or whatever )
Or you need to parse needed value from the form if "event" is only field not associated with Event model.
IMHO
If your question is "can I modify the form so that I automatically (magically?) get an object as a param?", the answer is definetly no.
What you have to do is to search the event object in the database based on the received id.

How to submit a form using simple_form_for when what's being submitted isn't part of the model

I'm trying to submit a form that contains fields for both an event and an invitation to that event. Here is my form:
<%= simple_form_for(#event) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title %>
<%= f.input :description %>
<%= f.input :start_at %>
<%= f.input :end_at %>
<%= f.input :all_day %>
<%= f.hidden_field :owner_id, value: current_user.id %>
<% if false %>
<%= f.association :sitter, label_method: lambda { |s| "#{s.name}" }, collection: User.all %>
<%= f.association :group, label_method: lambda { |g| "#{g.group_name}" }, collection: Group.where(:owner_id => current_user.id) %>
<% end %>
<%= f.input :user_emails, as: :text %>
<%= form_tag event_invitations_path, :method => :post do %>_tag :user_emails %>
</div><div>
<%= label_tag "Your message:" %>
</div><div>
<%= text_area_tag :email_message %>
<% end %>
</div>
</br>
<div class="form-actions">
<%= f.button :submit, :class => 'btn-primary' %>
</div>
<% end %>
This is (perhaps obviously) not working. :user_emails is NOT part of the event or invitation model as it's a list of emails that will be used to create invitations. Basically I merged two forms, one that was accepting the email/send invitation piece and one that was accepting the event information. I think I have my controller and model set up properly to take care of this but how do i submit this information as part of the same form without getting an "undefined_method" error (since user_emails doesn't belong to events). Let me know if you want to see my model/controller.
Use FormTagHelper
<%= label_tag "User", "Email"%>
<%= text_area_tag "user_emails", "example#example.com"%>
See the documentation for more options on text_area_tag and label_tag

Conforming Rails form into Formtastic Equivalent

I have a Rails application where I am using Active Admin as the backend. Active Admin uses Formtastic and I am having trouble converting one of the input fields in my _form.html.erb for posts.
Here is the form...
<div class="container">
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :author %>
<%= f.collection_select :blog_id, Blog.all, :id, :name, prompt: "Select a blog" %>
</div>
<div class="field">
<p>
Categories:<br>
<%= hidden_field_tag "post[category_ids][]", nil %>
<% Category.all.each do |category| %>
<%= check_box_tag "post[category_ids][]", category.id, #post.category_ids.include?(category.id), id: dom_id(category) %>
<%= label_tag dom_id(category), category.name %>
<% end %>
</p>
</div>
<div class="field">
<%= f.hidden_field :status, value: "Draft" %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body, class: "redactor", id: "redactor" %>
</div>
<div class="field">
<%= f.label :published_on %><br />
<%= f.date_select :published_on %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</div>
Here is the portion that I am having trouble converting to formtastic specific code. It comes from Ryan's screencast on HABTM Checkboxes.
<div class="field">
<p>
Categories:<br>
<%= hidden_field_tag "post[category_ids][]", nil %>
<% Category.all.each do |category| %>
<%= check_box_tag "post[category_ids][]", category.id, #post.category_ids.include?(category.id), id: dom_id(category) %>
<%= label_tag dom_id(category), category.name %>
<% end %>
</p>
</div>
Here is the formcode that is in the admin/post.rb file for Active Admin. If I use this I continue to get a no method error for category. I know that the way it is currently listed is incorrect.
form do |f|
f.inputs "Details" do
f.input :blog, hint: "Select a blog"
f.input :title, hint: "Enter blog post title"
f.input :published_on, as: :date, include_blank: false, hint: "Select a date", :prompt => {:day => "Day", :month => "Month", :year => "Year"}, :start_year => Time.now.year
f.input :status, as: :select, collection: ["Draft", "Published"], include_blank: false, hint: 'Select "Draft" to save and post later, and "Publish" to post now'
f.input :categories, as: :check_boxes
f.input :body, input_html: { class: "redactor", id: "redactor" }
end
f.buttons
end
If anyone has any input I am most appreciated. I have looked at the formtastic documentation and watched Ryan's screencasts, but am still having issues converting.
Thanks!
EDIT: ABLE TO RESOLVE-SOLUTION BELOW
I was able to make this work after getting a little more familiar with Formtastic and Active Admin. Below is the relevant code in the form, show, and index views in Active Admin.
ActiveAdmin.register Post do
index do
column "Post Title", :title
column :blog
column :published_on
column :status
column "Category", :categories do |post|
post.categories.collect { |cat| cat.name }.join(", ")
end
default_actions
end
show do
h5 "Created by #{post.blog.name} on #{post.created_at.strftime('%B %-d, %Y')}"
h5 "Categories: #{post.categories.collect { |cat| cat.name }.join(", ")}"
h5 "Current Status: #{post.status}"
h5 "Published On Date: #{post.published_on.strftime('%B %-d, %Y')} - (will only be posted if marked with Publish as status)"
div do
simple_format post.body
end
end
form do |f|
f.inputs "Details" do
f.input :blog, hint: "Select a blog"
f.input :title, hint: "Enter blog post title"
f.input :published_on, as: :date, include_blank: false, hint: "Select a date", :prompt => {:day => "Day", :month => "Month", :year => "Year"}, :start_year => Time.now.year
f.input :status, as: :select, collection: ["Draft", "Published"], include_blank: false, hint: 'Select "Draft" to save and post later, and "Publish" to post now'
f.input :categories, as: :check_boxes, collection: Category.all
f.input :body, input_html: { class: "redactor", id: "redactor" }
end
f.buttons
end
end
I was able to construct the Formtastic version as shown below. It took a little more understanding of Formtastic and then making minor adjustments for Active Admin.
Below is the relevant code in the form, show, and index views in Active Admin.
ActiveAdmin.register Post do
index do
column "Post Title", :title
column :blog
column :published_on
column :status
column "Category", :categories do |post|
post.categories.collect { |cat| cat.name }.join(", ")
end
default_actions
end
show do
h5 "Created by #{post.blog.name} on #{post.created_at.strftime('%B %-d, %Y')}"
h5 "Categories: #{post.categories.collect { |cat| cat.name }.join(", ")}"
h5 "Current Status: #{post.status}"
h5 "Published On Date: #{post.published_on.strftime('%B %-d, %Y')} - (will only be posted if marked with Publish as status)"
div do
simple_format post.body
end
end
form do |f|
f.inputs "Details" do
f.input :blog, hint: "Select a blog"
f.input :title, hint: "Enter blog post title"
f.input :published_on, as: :date, include_blank: false, hint: "Select a date", :prompt => {:day => "Day", :month => "Month", :year => "Year"}, :start_year => Time.now.year
f.input :status, as: :select, collection: ["Draft", "Published"], include_blank: false, hint: 'Select "Draft" to save and post later, and "Publish" to post now'
f.input :categories, as: :check_boxes, collection: Category.all
f.input :body, input_html: { class: "redactor", id: "redactor" }
end
f.buttons
end
end

Select multiple categories in form (rails)

I've got this tripbuilder which i want to assign categories to. So I've set up the models as where a trip can have any(or more) categories that are in the category table in my database. However; i have no idea how i can set up the form allowing a user to select categories via checkbox. Since fields_for doesn't sound like a solid way to go in this case (Because i want to see all the categories with a checkbox and select as many categories as i want). Can anyone help me out?
I've tried this form:
<%= form_for #trip, :html => {:multipart => true} do |a| %>
<%= a.label :title, "Routetitel" %>
<%= a.text_field :title %>
<%= a.label :description, "Omschrijving" %>
<%= a.text_area :description %>
<%= a.fields_for :categories do |cat| %>
<%= cat.check_box :name %>
<% end %>
<%= a.submit 'Verstuur' %>
<% end %>
At first, you need to setup the relationship between trip and category like this:
class Trip < ActiveRecord::Base
has_and_belongs_to_many :categories
end
Then you can build the form like this:
<%= form_for #trip, :html => {:multipart => true} do |a| %>
<%= a.label :title, "Routetitel" %>
<%= a.text_field :title %>
<%= a.label :description, "Omschrijving" %>
<%= a.text_area :description %>
<% Category.all.each do |cat| %>
<%= check_box_tag "trip[category_ids][]", cat.id, #trip.catergory_ids.include?(cat.id)
<% end %>
<%= a.submit 'Verstuur' %>
<% end %>
Yes, it can be done by using select tag and multiple attribute of select tag.
<% = a.select :categories, Category.all.collect {|c| [c.name, c.id]}, :include_blank => true', :multiple => "multiple" %>
Please Modify your fields_for as described below and check !!!!
<%= a.fields_for "categories[]" do |cat| %>
<%= cat.check_box :name %>
<% end %>

Resources