My problem is that I don't have an idea to create a list of users with emails, and in the same list have a checkbox for every user, then at the end have a button 'Send' and send all the emails to the checked users, I solved temporaly with:
1)List (index view)
<table>
<tr>
<th>Name</th>
<th>Email</th>
<th>Correo</th>
<th>Send Email</th>
<th></th>
<th></th>
<th></th>
</tr>
<% var1 = []; i = 0 %>
<% #users.each do |user| %>
<tr id=<%= if user.value == 'No dispatched'
'c'
elsif user.value == 'Dispatched'
'a'
else
'b'
end%> >
<td><%= user.name %></td>
<td><%= user.email %></td>
<td><%= user.value %></td>
<td><% var1[i] = user.name; i=i+1 %>
<%= button_to 'Activate/Desactivate', edit_send_path(user.id), :method => :get %> </td>
</td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :method => :delete, :data => { :confirm => 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New User', new_user_path %>
<%= button_to 'Send', {:controller => :Send, :action => :send}, :method => :get, :value => 2 %>
2)Send controller
class SendController < ApplicationController
def send
#users = User.all
#users.each do |user|
if user.value == 'In Process'
UserMailer.registration_confirmation(user).deliver
user.value = 'Dispatched'
user.save
end
end
redirect_to :controller => :users, :protocol => 'http'
end
def edit
user = User.find(params[:id])
if user.value == 'In process'
user.value = 'No dispatched'
user.save
elsif user.value == 'No dispatched'
user.value = 'In process'
user.save
end
redirect_to :controller => :users, :protocol => 'http'
end
end
I'm using the flag 'value' to check if the email was sended
I did this for part of my senior project, here's how I did it:
For each user add a checkbox that is linked to each user's id inside the do loop, looks like:
<td><%= check_box_tag ':multiple_users[]', user.id %></td>
Add a submit_tag below the do loop, looks like, note that the name was simply to differentiate between differing actions we used when selecting users:
<%= submit_tag "Email Selected Users", :name => "selected" %>
Add the corresponding form tag somewhere at the top of the view, mine goes to the handler, but yours would go to your "send" action, the empty hash is important:
<%= form_tag handle_checkbox_handler_path({}) do %>
Generate a mailer, I did not do this and I do not know how, I'm sure Google does :) You will also need to make a config file for the mailer (again google this, I can't help you).
Once you have that mailer, create an action in it to email a user:
def email_user(email, subject, text_body)
#text_body = text_body
mail( :to => email, :subject => subject, :from => "monkey#feet.com")
end
Once you have the action, make a corresponding view for the email (mine is very simple it just puts the #text_body value.
<%= #text_body %>
In your send action send the email to multiple users, here's my code, I'm no Ruby expert but it worked for me. Also it's not very clean so I'll add some comments for your readability:
if not params[':multiple_users'].nil? # There are multiple users to email
# Split the passed string and loop through each ID in the string sending an email to each user listed
params[':users'].split.each do |u|
# Emailer is my mailer's name, :subject and :message I passed into the action as well. email_user is the name of my mailer action, defined above.
Emailer.email_user(User.find(u.to_i).email, params[:subject], params[:message]).deliver
end
redirect_to users_path, :notice => "Message was sent successfully"
else # there is only one user to email
if Emailer.email_user(params[:email], params[:subject], params[:message]).deliver # Try to send, if fails tell them so
redirect_to users_path, :notice => "Message was sent successfully"
else
redirect_to users_path, :alert => "Message failed to send"
end
end
end
I hope this is readable and at least gives you a starting point. You should also know that the check_box_handler I mentioned earlier does some checking to ensure that nothing bad happened.
Related
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
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
Okay so I have a post index and would like to link it to my slide index, but for some reason i keep getting this error
No route matches {:controller=>"slides"}
when i link with this
<%= link_to 'Show Slides', post_slides_path(#post) %>
If i use the same link above in my Posts Edit Viewer, it seems to work fine....any suggestions?
I would basically like to link to this....../posts/:id/slides from the my table in posts
ROUTES.RB
resources :posts do
resources :slides
end
POST MODEL
class Post < ActiveRecord::Base
attr_accessible :text, :title
has_many :slides, :dependent => :destroy
def self.search(search)
if search
where('Title Like ?' , "%#{search}%")
else
scoped
end
end
SLIDE MODEL
class Slide < ActiveRecord::Base
belongs_to :post
POST INDEX VIEW
<table id="posts" class="table table-striped table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= link_to 'Show Slides', post_slides_path(#post) %>
<td><%= link_to 'Edit', :action => :edit, :id => post.id %></td>
<td><%= link_to 'Destroy', { :action => :destroy, :id => post.id }, :method => :delete, :confirm => 'Are you sure?' %></td>
</tr>
<% end %>
<tbody>
<% end %>
</table>
POST CONTROLLER
class PostsController < ApplicationController
def new
#post = Post.new
end
def show
#post = Post.find(params[:id])
end
def index
#posts = Post.search(params[:search]).paginate(:per_page => 10, :page => params[:page])
end
def edit
#post = Post.find(params[:id])
end
SLIDE CONTROLLER
class SlidesController < ApplicationController
def index
#post = Post.find(params[:post_id])
#slides = #post.slides.all
end
def show
#post = Post.find(params[:post_id])
#slide = #post.slides.find(params[:id])
end
def new
#post = Post.find(params[:post_id])
#slide = Slide.new
end
def edit
#post = Post.find(params[:post_id])
#slide = Slide.find(params[:id])
end
The post_slides_path is looking for an id as the parameter to match to the /posts/:id/slides route. The reason it works in your edit page is because your #post variable is finding the id of the Post object ( #post = Post.find(params[:id]) ). In your index action of the Post controllers, you have the #posts instance variable pointing to the search params and paginating and you do not have a #post instance variable defined.
In your block try
post_slides_path(post.id)
I'm using a link_to to create an object in my Rails 3 app. Searching has given me the proper way to use link_to with the :post method, but I'm wondering if using link_to to pass in a name value for my object as well. Here is my link:
<%= link_to "Todo text", {:controller => "profiles", :action => "create_inside", :method => :post}, :class => "button white" %>
My profiles_controller.rb:
def create_inside
#todo = Insidetodo.new
#todo.save!
if #todo.save
redirect_to #profile.todo, :notice => 'Todo successfully added.'
else
render :action => 'new'
end
end
My todo.rb model:
class Todo < ActiveRecord::Base
has_and_belongs_to_many :profiles
validates :name, :presence => true
end
Is there a way to add in :name => "#{#user.profile.todotext}" to the link_to so that it passes and saves? I don't know if it's creating properly because at the moment when I click a link_to I get a validation error - Validation failed: Name can't be blank.
For passing name in the link_to
<%= link_to "Todo text", {:controller => "profiles", :action => "create_inside", :name => "#{#user.profile.todotext}", :method => :post}, :class => "button white" %>
and the controller must be
def create_inside
#todo = Insidetodo.new(:name => params[:name])
if #todo.save
redirect_to #todo.goal, :notice => 'Todo successfully added.'
else
render :action => 'new'
end
end
But the link_to will pass the name parameter in url only(like Todo text).
If you want the name not to be sent in the url, you might want to use a form and use a submit button instead of the link as it is representing an action and not a link.
<%= form_tag(:controller => "profile", :action => "create_profile") do -%>
<%= hidden_field_tag :name, #user.profile.todotext %>
<%= submit_tag "Todo Text" %>
<% end -%>
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 !