Select all or single objects from collection_select in Rails - ruby-on-rails-3

I have an app that sends "pages" via actionmailer. In my view code I have it setup to select a particular unit which then has medics assigned who get the email/page. I want to include an option to page all units in my select statement but am not sure how to do it.
view/form code:
<%= form_for(#page) do |f| %>
<%= f.label :message %>
<%= f.text_field :message %>
<%= f.label 'Medic'%>
<%= f.collection_select(:unit_id, Unit.order("unit_name ASC"), :id, :unit_name, {}, {:class => 'select'})%>
<%= f.button :send, :class => 'btn btn-info' %>
<% end %>
controller code:
def create
#page = Paging.new(params[:paging])
unit = Unit.find(params[:paging][:unit_id])
message = params[:paging][:message]
if #page.save
PagingsMailer.paging(unit.incharge, unit, message).deliver
PagingsMailer.paging(unit.attendant, unit, message).deliver
redirect_to pagings_path, notice: "Page was successfully sent."
else
redirect_to pagings_path
end
end
The option can be in the select itself or as another select/checkbox so long as the original select is ignored.
Any help with this is appreciated.

I got some help on this and was able to resolve it by creating an array of arrays in the form and passing "all" to the controller to perform the individual mailings.
view code:
<%= f.select :unit_id, options_for_select(Unit.order.map{ |unit| [unit.unit_name, unit.id] } + [["All Medics", "all"]]), {}, {:class => 'select'} %>
controller code:
def create
message = params[:paging][:message]
if params[:paging][:unit_id] == "all"
Unit.all.each do |unit|
#page = Paging.new(params[:paging])
#page.unit_id = unit.id
if #page.save
PagingsMailer.paging(unit.incharge, unit, message).deliver
PagingsMailer.paging(unit.attendant, unit, message).deliver
flash.notice = "Page was successfully sent."
end
end
else
#page = Paging.new(params[:paging])
unit = Unit.find(params[:paging][:unit_id])
if #page.save
PagingsMailer.paging(unit.incharge, unit, message).deliver
PagingsMailer.paging(unit.attendant, unit, message).deliver
flash.notice = "Page was successfully sent."
end
end

Related

Custom Action causes "No route matches" Routing Error

I'm am trying to have a form submit to a custom action. The form won't even render, it just displays a error: 'No route matches'".
routes.rb
resources :users do
member do
post :add_foo
end
end
users_controller.rb
def add_foo
puts "!!! in add_new_foo .. params = " + params + " !!!"
end
users/new.html.erb
<%= simple_form_for(#user) do |f| %>
<%= button_to 'download', add_foo_user_path(#user) %>
<% end %>
I have also tried
<%= simple_form_for #user, :url => add_foo_user_path(#user), :method => :post do |f| %>
<%= f.submit "Add" %>
<% end %>
Any help would be appreciated!
Everything is defined correctly. The error is most likely raised because the #user instance is not present.

ActiveAdmin - Pass locals to form

In my photos.rb file I have:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo', :locals => { :events => Event.all }
end
In my _photo.html.erb file I want to be able to access the value of events, but it doesn't seem to be detectable. How can I do this?
As requested in a comment, here is my form:
<% if events.any? %>
<%= form_for [:admin, #photo], :validate => true do |f| %>
<!-- insert a bunch of standard field divs here -->
<div class="actions" style="margin-top: 20px">
<% if #photo.new_record? %>
<%= f.submit 'Create photo' %>
<% else %>
<%= f.submit 'Update photo' %>
<% end %>
</div>
<% end %>
<% else %>
<div style="font-size: 14px">
You cannot add photos until you have added at least one event.
</div>
<% end %>
The error message I am getting is around the events.any? line:
Completed 500 Internal Server Error in 108ms
ActionView::Template::Error (undefined local variable or method `events' for #<#<Class:0x007fdb8e841b80>:0x007fdb8a93e7a8>)
form do |f|
f.render partial: 'admin/forms/photo', locals: { f: f, events: Event.all }
end
Note that you will need to remove form_for, semantic_form_for, active_admin_form_for etc from your partial, since it will be covered by the form do part in the admin/photos.rb, otherwise there will be two nested forms.
Example partial:
# app/views/admin/forms/_photo.html.arb
if events.any?
f.inputs do
f.input :title, label: 'Etc'
f.input :file
end
f.actions
else
f.div 'You cannot add photos until you have added at least one event.',
style: 'font-size: 14px'
end
form do |f|
render partial: 'admin/forms/photo', locals: { value: 'random_data' }
end
You can use f.render or just render.
Note that partial: is required to send locals to the form
Example Partial
#app/views/admin/forms/_photo.html.arb
active_admin_form_for [:admin, resource] do |f|
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :name
f.input :random if (value == 'random_data')
end
f.actions
end
another thought on this, if you want to check only if there are any Events in db you can make any call directly on Class:
<% if Event.any? %>
do this
<% else %>
do that
<% end %>
without sending variables to partial, the above code result in:
2.0.0p0 :004 > Event.any?
(0.6ms) SELECT COUNT(*) FROM "events"
=> true
and leave the ActiveAdmin partial without locals:
ActiveAdmin.register Photo do
form :partial => 'admin/forms/photo'
end

How pass variable submitted in form into 'new' action

I am trying to send a message to another user. But when I leave a field blank, the controller renders another 'new' action.
Here is the view code that links to the first submit:
<%= link_to 'Send Mail', {:controller => 'messages', :action => 'new', :recipient_id => #profile.id}, :class => 'btn btn-large btn-primary' %>
Here is the message#new code:
def new
#message = Message.new
#recipient = Profile.find(params[:recipient_id])
end
Here is the message#new view code:
<%= simple_form_for #message do |f| %>
<%= f.input :title %>
<%= f.input :body %>
<%= f.input :recipient_id, :as => :hidden, :input_html => {:value => #recipient.id} %>
<%= f.input :sender_id, :as => :hidden, :input_html => {:value => #recipient.id} %>
<%= f.button :submit %>
<% end %>
Here is the message#create code:
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = "New message created"
redirect_to #message
else
flash[:error] = "Did not work"
#recipient = params[:recipient_id]
render action: "new"
end
end
How do I get the :recipient_id value submitted in the form and pass into the render new action?
When you rendering new method rails won't execute it codes instead it only renders the view(new.html.erb) of the new action and you already generating
a recipient_id which is enough for your form to pass the parameter
Try this
def create
#message = Message.new(params[:message])
if #message.save
flash[:notice] = "New message created"
redirect_to #message
else
flash[:error] = "Did not work"
#recipient = Profile.find(params[:message][:recipient_id])
render action: "new"
end
end
When rendering the new action we have to create the instances manually which is used in the view.
Note: If you want generate a new parameter use redirect_to method, where render uses the previous parameters until a new request is generated

Ruby on Rails - Multibutton combined with checkboxes and advanced search

Currently I have the situation that one button is add to the index-form. This workes perfectly in combination with the other functionalties as search and checkboxes which are also part of the index-form.
Code of the index.html.erb:
<%= form_tag order_path, :method => 'get' do %>
<p>
<%= submit_tag "Historical Search", :account_short => nil %>
<%= text_field_tag :search, params[:search] %>
</p>
<% end %>
<%= form_tag sendnext_order_path, :method => :put do %>
<%= submit_tag "Send to Desk" %><br/>
-- other code from index-form
<% end %>
Combined with the controller:
def sendnext
Order.update_all(["status_id = ? ", "2"], :id => params[:order_ids])
redirect_to order_path, notice: 'Order succesfully send to desk.'
end
Now I want to add a second button next to the Send to Desk button with another action than the excisting working one. Until now I'm not capable to realise this.
Please advice. Any feedback is welcome.
Use button_to
<%= button_to('Send to Desk', 'sendnext', :method => "put") %>
<%= button_to('Cancel Order', 'cancelorder ', :method => "put") %>
Will take care of the form for you. submit_tag is submitting the first form I believe.
For example
<%= button_to "New", :action => "new" %>
will generate
# => "<form method="post" action="/controller/new" class="button_to">
# <div><input value="New" type="submit" /></div>
# </form>"
Thanks for your help. I have found a working solution which realised my current requirements:
The index.html.erb looks like the following:
<%= form_tag updateorder_order_path, :method => :put do %>
<%= submit_tag "To Desk" %><br/>
<%= submit_tag "Cancel Order" %>
-- other code like data fields
<%end %>
The controller.rb looks like the following:
def updateorder
if params[:commit] == "To Desk"
Order.update_all(["status_id = ? ", "2"], :id => params[:order_ids])
redirect_to order_path, notice: 'Order(s) successfully send to desk.'
elsif params[:commit] == "Cancel Order"
Order.update_all(["status_id = ? ", "3"], :id => params[:order_ids])
redirect_to order_path, notice: 'Order(s) successfully cancelled.'
else
Order.update_all(["status_id = ? ", "5"], :id => params[:order_ids])
redirect_to order_path, notice: 'Order(s) successfully updated.'
end
end
The routes.rb contains the next code:
resources :orders do
put 'updateorder', :on => :collection
end

2 render templates (from devise) on one page (rails 3)

I've installed devise for my rails app, i can go to the sign in page or the sign up page. But I want them both on a welcome page...
So I've made a welcome_page_controller.rb with the following function:
class WelcomePageController < ApplicationController
def index
render :template => '/devise/sessions/new'
render :template => '/devise/registration/new'
end
end
But when i go to the welcome page i get this error:
NameError in Welcome_page#index
Showing /Users/tboeree/Dropbox/rails_projects/rebasev4/app/views/devise/sessions/new.html.erb where line #5 raised:
undefined local variable or method `resource' for #<#<Class:0x104931c>:0x102749c>
Extracted source (around line #5):
2: <% #header_title = "Login" %>
3:
4:
5: <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
6: <p><%= f.label :email %><br />
7: <%= f.email_field :email %></p>
8:
Does anybody knows a solution for this problem? Thanks in advance!
Does it have to do with the fact that it is missing the resource function? in the welcome_page controller? It's probably somewhere in the devise controller...?
Regards,
Thijs
Here's how I managed to did it.
I've put a sign up form in my home#index
My files:
view/home/index.html.erb
<%= render :file => 'registrations/new' %>
helper/home_helper.rb
module HomeHelper
def resource_name
:user
end
def resource
#resource = session[:subscription] || User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
def devise_error_messages!
return "" if resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t("errors.messages.not_saved",
:count => resource.errors.count,
:resource => resource_name)
html = <<-HTML
<div id="error_explanation">
<h2>#{sentence}</h2>
<ul>#{messages}</ul>
</div>
HTML
html.html_safe
end
end
You need that part because Devise works with something called resource and it should be defined so you can call your registration#new anywhere.
Like that, you should be able to register. However, I needed to display errors on the same page. Here's what I added:
layout/home.html.erb (the layout used by index view)
<% flash.each do |name, msg| %>
# New code (allow for flash elements to be arrays)
<% if msg.class == Array %>
<% msg.each do |message| %>
<%= content_tag :div, message, :id => "flash_#{name}" %>
<% end %>
<% else %>
# old code
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %> #don't forget the extra end
<% end %>
I found this code here
And here's something I created: I saved my resource object if invalid in a session so that the user hasn't to fill every field again. I guess a better solution exists but it works and it's enough for me ;)
controller/registration_controller.rb
def create
build_resource
if resource.save
if resource.active_for_authentication?
# We delete the session created by an incomplete subscription if it exists.
if !session[:subscription].nil?
session[:subscription] = nil
end
set_flash_message :notice, :signed_up if is_navigational_format?
sign_in(resource_name, resource)
respond_with resource, :location => redirect_location(resource_name, resource)
else
set_flash_message :notice, :inactive_signed_up, :reason => resource.inactive_message.to_s if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords(resource)
# Solution for displaying Devise errors on the homepage found on:
# https://stackoverflow.com/questions/4101641/rails-devise-handling-devise-error-messages
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages
# We store the invalid object in session so the user hasn't to fill every fields again.
# The session is deleted if the subscription becomes valid.
session[:subscription] = resource
redirect_to root_path #Set the path you want here
end
end
I think I didn't forget any code. Feel free to use whatever you need.
Also, you can add your sign in form in the same page (something like that:)
<%= form_for("user", :url => user_session_path) do |f| %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.submit 'Sign in' %>
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
<%= link_to "Forgot your password?", new_password_path('user') %>
<% end %>
Cheers !