Rails mailboxer gem cannot send message - ruby-on-rails

I am using Mailboxer gem for the messaging function, but as I am very new I am not very sure how to use it. Basically I created the following message controller:
class MessagesController < ApplicationController
before_action :set_message, only: [:new, :create]
def new
#message = Message.new
end
def create
current_user.send_message(#recipient, message_params(:body, :subject))
redirect_to conversations_path
end
private
def set_message
#recipient = User.find(params[:recipient_id])
end
def message_params
params.require(:message).permit(:body, :subject)
end
end
Then my view:
<h1>New Message</h1>
<%= simple_form_for(#message, html: {class: "form-horizontal"}) do |f| %>
<%= f.error_notification %>
<%= f.input :subject %>
<%= f.input :body, as: :text, input_html: { rows: "3"} %>
<div class="form-actions">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
<% end %>
But I can't send message...
(BTW I can send message is the console, and also replace part of the message controller with "current_user.send_message(#recipient, "test", "test")", but definitely not what I want)

Use form_tag instead of form_for
Instead of using form_for, try using form_tag, as this has worked for me:
<%= form_tag("/messages/send_message", method: "post", url: send_message_path) do %>
<%= hidden_field_tag :user_id, "#{#user.id}" %>
<%= text_field_tag :subject, nil, :class => 'form-control', :placeholder => "Subject" %>
<%= text_area_tag :message, nil, :class => 'form-control', :placeholder => "Message" %>
<%= submit_tag "Submit", :class => "btn btn-primary" %>
<% end %>
This would have an action you messages controller like this:
def send_message
#user = User.find(params[:user_id])
#message = params[:message]
#subject = params[:subject]
current_user.send_message(#user, "#{#message}", "#{#subject}")
redirect_to root_path
end
And something like this in you routes file:
post '/messages/send_message', :to => "messages#send_message", :as => "send_message"
Really hope this helps!

Related

Ruby on Rails: No routes match for[POST] '/contacts/new'

Rails 5. keep getting the error that route could not be found. What did I do wrong here?
App/views/contacts/new.html.erb
<%= form_for "#contact" do |f| %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.text_field :email, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :comments %>
<%= f.text_area :comments, class: 'form-control' %>
</div>
<%= f.submit 'Submit', class: 'btn btn-default' %>
<% end %>
routes.rb file
Rails.application.routes.draw do
root to: 'pages#home'
get '/about', to: 'pages#about'
resources :contacts
end
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
redirect_to new_contact_path, notice: "Message sent."
else
redirect_to new_contact_path, notice: "Error occured."
end
end
private
def contact_params
params.require(:contact).permit(:name, :email, :comments)
end
end
contact.rb (model file, blank for now)
class Contact < ActiveRecord::Base
end
I can't figure out why. Thanks in advance.
You have quotes around your #contact variable in your form, try just using the plain #contact variable.

Routing error - No route matches [POST]

Have read many questions / answers on this issue, yet do not seem to find my fix.
Here is the issue: I am following the getting started for Rails to create a simple register of annotations. My forms work - can add new & update annotations. Yet when I add links to the index, I get a routing error:
This: <%= button_to "Details", annotation_path(annotation), :class => "btn btn-primary btn-xs"%> results in: No route matches [POST] "/annotations/5"
This: <%= button_to "Add Annotation", new_annotation_path, :class => "btn btn-primary btn-xs"%> to No route matches [POST] "/annotations/new"
Thanks for help
Routes.db:
Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users
resources :users, :annotations
Controller:
class AnnotationsController < ApplicationController
def index
#annotations = Annotation.all
end
def show
#annotation = Annotation.find(params[:id])
end
def new
#annotation = Annotation.new
end
def edit
#annotation = Annotation.find(params[:id])
end
def create
#annotation = Annotation.new(annotation_params)
#annotation.save
redirect_to #annotation
end
def update
#annotation = Annotation.find(params[:id])
if #annotation.update(annotation_params)
redirect_to #annotation
else
render 'edit'
end
end
def destroy
#annotation = Annotation.find(params[:id])
#annotation.destroy
redirect_to annotations_path
end
private
def annotation_params
params.require(:annotation).permit(:name, :description)
end
end
And the form (= partial)
<%= simple_form_for #annotation, url: annotations_path, html: { class: 'form-horizontal' },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
file: :horizontal_file_input,
boolean: :horizontal_boolean
} do |f| %>
<%= f.error_notification %>
<%= f.input :name, placeholder: 'Enter name' %>
<%= f.input :description, placeholder: 'Description' %>
<%= f.input :file, as: :file %>
<%= f.input :active, as: :boolean %>
<%= f.input :choice, as: :check_boxes,
collection: [
'Option one ...',
'Option two ...'] %>
<%= f.input :documenttype, as: :radio_buttons,
collection: ['Type1', 'Type2'] %>
<%= f.button :submit %>
<% end %>
Note on the form: to no avail, I tried using <%= simple_form_for :annotation, url: annotations_path,
The issue is because the button_to helper actually generates a form at code level and thus is POSTing said form, however the route for a new resource must be a GET.
The button_to tag really should not be used for GET requests so I would use a link_to with CSS classes instead (you already have the necessary classes), but you can do it using the below if you wanted:
<%= button_to "Details", annotation_path(annotation), class: "btn btn-primary btn-xs", method: :get%>
The better approach however is:
<%= link_to "Details", annotation_path(annotation), class: "btn btn-primary btn-xs" %>
Read doc here button_to
The method is by default :post change it using :method param
<%= button_to "Details", annotation_path(annotation), :class => "btn btn-primary btn-xs", method: :get%>
<%= button_to "Add Annotation", new_annotation_path, :class => "btn btn-primary btn-xs", method: :get%>

Got error from devise user and wicked rails gem

I got error from browser after sign up with email and password.
class UserStepsController < ApplicationController
steps :personal
def show
#user = current_user
render_wizard
end
def update
#user = current_user
#user.update_attributes(user_params)
render_wizard #user
end
def finish_wizard_path
flash[:notice] = "You have successfully Registered With The Wizard."
user_path(current_user)
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :degree_level, :role, :email, :password )
end
end
On RegistrationsController < Devise::RegistrationsController
class RegistrationsController < Devise::RegistrationsController
def new
super
end
def create
super
end
protected
def after_sign_up_path_for(resource)
'/user_steps'
end
end
I allready added routes resources :user_steps, devise_for :users, :controllers => { :registrations => "registrations" }
my devise/registrations/new
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :email, required: true, autofocus: true %>
<%= f.input :password, required: true %>
<%= f.input :password_confirmation, required: true %>
</div>
<div class="form-actions">
<%= f.button :submit, "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
Added personal.html.erb first name, last name and degree_level
<%= form_for(#user, :url => wizard_path, :method => :put) do |f|%>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_field :degree_level %>
<%= f.submit 'submit', :class => "btn btn-primary" %>
<%end%>
user model added validates presence.
This error show after sign up with email and password
error message is Please review the problems below:
Sorry i want add include Wicked::Wizard

Rails Mailboxer - Create Conversation from Button

I'm using the mailboxer gem to implement user messaging on an app. Currently, i've got it set up based on this https://github.com/RKushnir/mailboxer-app. Users can enter an email address, subject and message into a form, and start a conversation.
I'd like a user to be able to start a conversation without having to enter another users email address - for instance clicking a button on a relevant page where I can pass a #user in as the recipient.
Here is my current controller:
class ConversationsController < ApplicationController
authorize_resource
helper_method :mailbox, :conversation
def create
recipient_emails = conversation_params(:recipients).split(',')
recipients = User.where(email: recipient_emails).all
conversation = current_user.
send_message(recipients, *conversation_params(:body, :subject)).conversation
redirect_to conversation
end
def reply
current_user.reply_to_conversation(conversation, *message_params(:body, :subject))
redirect_to conversation
end
def trash
conversation.move_to_trash(current_user)
redirect_to :conversations
end
def untrash
conversation.untrash(current_user)
redirect_to :conversations
end
private
def mailbox
#mailbox ||= current_user.mailbox
end
def conversation
#conversation ||= mailbox.conversations.find(params[:id])
end
def conversation_params(*keys)
fetch_params(:conversation, *keys)
end
def message_params(*keys)
fetch_params(:message, *keys)
end
def fetch_params(key, *subkeys)
params[key].instance_eval do
case subkeys.size
when 0 then self
when 1 then self[subkeys.first]
else subkeys.map{|k| self[k] }
end
end
end
end
and corresponding _form:
<%= form_for :conversation, url: :conversations do |f| %>
<%= f.text_field :recipients %>
<%= f.text_field :subject %>
<%= f.text_field :body %>
<div class="form-actions">
<%= f.button :submit, class: 'btn-primary' %>
<%= submit_tag 'Cancel', type: :reset, class: 'btn btn-danger' %>
</div>
<% end %>
I've got all the views and actions working relating to replying to conversations with messages, display all users conversations etc, but just not how to start it without having to type the address in.
Thanks for any help
Added: I don't mind editing the above form etc and losing the capability for a user to enter another's email, as I don't want them to be able to do that. The buttons in question will be named along the lines of 'ask the client a question', or 'ask the venue a question', rather than just sending messages to random users.
EDITED TO ADD:
Thanks for that, makes sense and I am nearly there...
I've ended up adding a copy of the original conversation form i'm using (in my _form file):
<%= form_for :conversation, url: :conversations do |f| %>
<%= f.text_field :recipients %>
<%= f.text_field :subject %>
<%= f.text_field :body %>
<div class="form-actions">
<%= f.button :submit, class: 'btn-primary' %>
<%= submit_tag 'Cancel', type: :reset, class: 'btn btn-danger' %>
</div>
<% end %>
This works fine from the correct view that I need it in, and does everything as expected - however, when I try to hide the recipients text field and pass in the users email address (rather than having to manually type it in, I am getting problems:
<%= form_for :conversation, url: :conversations do |f| %>
<%= hidden_field_tag :recipients, "#{#enquiry.client.user.email}" %>
<%= f.text_field :subject %>
<%= f.text_field :body %>
<div class="form-actions">
<%= f.button :submit, class: 'btn-primary' %>
<%= submit_tag 'Cancel', type: :reset, class: 'btn btn-danger' %>
</div>
<% end %>
This is throwing an error in the controller:
undefined method `split' for nil:NilClass
def create
recipient_emails = conversation_params(:recipients).split(',')
recipients = User.where(email: recipient_emails).all
conversation = current_user.
If I 'view source' on Firefox before I hit submit on the form, I can see that there is a field there with the users email address passed in correctly, but it's just not going to the controller for some reason?
Something that may help - If I change the hidden_field_tag back to a normal field, and pass in the email address as above, the view won't even load. It is saying
'undefined method `merge' for "user#user.com":String
and highlighting that row in the code.
Thanks
In mailboxer, you do not send a message to an email address, rather you send it to a model which has acts_as_messageable on it, such as user. The following code is a rough implementation of how I have done it, with the #user variable being set in the controller, as this is on the profile page.
<%= form_tag("/messages/send_message", method: "post", url: send_message_path) do %>
<%= hidden_field_tag :user_id, "#{#user.id}" %>
<%= text_field_tag :subject, nil, :class => 'form-control', :placeholder => "Subject" %>
<%= text_area_tag :message, nil, :class => 'form-control', :placeholder => "Message" %>
<%= submit_tag "Submit", :class => "btn btn-primary" %>
<% end %>
This would have an action you messages controller like this:
def send_message
#user = User.find(params[:user_id])
#message = params[:message]
#subject = params[:subject]
current_user.send_message(#user, "#{#message}", "#{#subject}")
redirect_to root_path
end
Or, in your case, if you wanted email addresses, you can just find the recipients by there email address which you have in the database:
def send_message
#user = User.find_by_email(params[:user_email])
#message = params[:message]
#subject = params[:subject]
current_user.send_message(#user, "#{#message}", "#{#subject}")
redirect_to root_path
end
And something like this in you routes file:
post '/messages/send_message', :to => "messages#send_message", :as => "send_message"
Really hope this helps!

How to create three records using one form? And how to show validation errors for them?

Bassicaly my problem what to do if i have 3 forms and one submit button.
I want to create a form which sends email to each recipient and then create new record in free_registration_coupons table.
I need validation of email for this form.
Model FreeRegistrationCoupon: recipient_email, token, sender_id
For now i have this:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = [params[:recipient_email_1], params[:recipient_email_2], params[:recipient_email_3]]
emails.reject!{ |e| e.eql?("") }
if emails.present?
emails.each do |e|
FreeRegistrationCoupon.create(:recipient_email => e, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
redirect_to(:back)
end
end
end
class FreeRegistrationCoupon < ActiveRecord::Base
before_save :generate_token
attr_accessor :recipient_email, :sender_id
validates :recipient_email, :presence => true, :email => true
def generate_token
self.token = SecureRandom.hex
end
end
This is form which is in other controller CarsController#confirm:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<!-- errors -->
<%= label_tag :recipient_email_1 %>
<%= text_field_tag :recipient_email_1 %>
<%= label_tag :recipient_email_2 %>
<%= text_field_tag :recipient_email_2 %>
<%= label_tag :recipient_email_3 %>
<%= text_field_tag :recipient_email_3 %>
<%= submit_tag %>
<% end %>
I think you should have defined your form using:
<%= form_tag :controller => 'free_registration_coupons', :action => "send_invitations" do %>
<%= #error_message %>
<%= label_tag "recipient_email[1]" %>
<%= text_field_tag "recipient_email[1]" %>
<%= label_tag "recipient_email[2]" %>
<%= text_field_tag "recipient_email[2]" %>
<%= label_tag "recipient_email[3]" %>
<%= text_field_tag "recipient_email[3]" %>
<%= submit_tag %>
<% end %>
This way it will be easier to treat all email address on your controller and you can track those errors to display them afterwards:
class FreeRegistrationCouponsController < ApplicationController
def send_invitations
emails = params[:recipient_email]
emails.reject!{ |param, value| value.eql?("") }
errors = []
if emails.any?
emails.each do |param, value|
validation_result = FreeRegistrationCoupon.save(:recipient_email => value, :sender_id => current_user.id)
#MAILER
end
redirect_to root_path, :notice => "You just send #{emails.size} invitations!"
else
#error_message = "You have to include, at least, one e-mail address!"
render :name_of_the_action_that_called_send_invitations
end
end
end
I didnt test this code. Hope it helps!

Resources