I'm using Mailboxer as my messaging gem in my rails app.
So the site's about classifieds. Every classified has a contact seller link , which i have implemented to route to the new_message form and write the message to the recipient fine!
Now i want to add some info about the classified that the contact form is made for!
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#user = User.find_by(id: params[:recipient_id])
end
def name
first_name
end
def mailboxer_email(object)
email
end
def create
recipients = User.find_by(id: params[:recipient_id])
conversation = current_user.send_message(recipients, params[:message][:body], params[:message][:subject]).conversation
flash[:success] = "Message has been sent!"
redirect_to conversation_path(conversation)
end
end
This is the view where i call new_message_path and then retrieve the user_id to define the recipient.
<div class="center-div">
<div class="col-lg-12" id="image">
<% #classified.photos.each do |p| %>
<h3 class="dark-grey"><%= #classified.title %></h3>
<h5 class="dark-grey">Loved by: <%= #classified.favorited_by.count %> </h5>
<%= image_tag p.image %>
<%end%>
</div>
<%= link_to "", new_message_path(:recipient_id => #classified.user_id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %>
<%if current_user.favorite_classifieds.collect(&:classified_id).include?(#classified.id) %>
<%= link_to "", favorite_classified_path(#classified, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %>
<%else%>
<%= link_to "", favorite_classified_path(#classified, type: "favorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#000000", method: :put %>
<%end%>
<%= link_to "", editlisting_path(#classified) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %>
<ul>
<h3 class="dark-grey">Model</h3>
<li><%= #classified.model %></li>
<h3 class="dark-grey">Description</h3>
<li><%= #classified.description %></li>
<li><%= link_to "Back", '/' , :class => "link" %></li>
<li><%= link_to #classified.user.first_name, profile_path(#classified.user_id) %></li>
</ul>
</div>
and this is my message_new view where i want to have the data of the classified
<div class="center-div">
<div class="messages-box">
<% page_header "Αποστολή μηνύματος" %>
<%= form_tag messages_path, method: :post do %>
<div class="form-group">
<%= label_tag 'message[subject]', 'Subject' %>
<%= text_field_tag 'message[subject]', nil, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= label_tag 'message[body]', 'Message' %>
<%= text_area_tag 'message[body]', nil, cols: 3, class: 'form-control', required: true %>
</div>
<div class="form-group">
<%= hidden_field_tag(:recipient_id, "#{#user.id}") %>
</div>
<%= submit_tag 'Send', class: 'btn btn-primary' %>
<% end %>
</div>
</div>
also for any solution a good explanation would help me a lot.
Thank you.
I ended up using nested routes.
resources :classifieds do
put :favorite, on: :member
resources :messages do
end
end
this is my view
<div class="center-div">
<div class="col-lg-12" id="image">
<% #classified.photos.each do |p| %>
<h3 class="dark-grey"><%= #classified.title %></h3>
<h5 class="dark-grey">Loved by: <%= #classified.favorited_by.count %> </h5>
<%= image_tag p.image %>
<%end%>
</div>
<%= link_to "", new_classified_message_path(:recipient_id => #classified.user_id , :classified_id => #classified.id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %>
<%if current_user.favorite_classifieds.collect(&:classified_id).include?(#classified.id) %>
<%= link_to "", favorite_classified_path(#classified, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %>
<%else%>
<%= link_to "", favorite_classified_path(#classified, type: "favorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#000000", method: :put %>
<%end%>
<%= link_to "", editlisting_path(#classified) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %>
<ul>
<h3 class="dark-grey">Model</h3>
<li><%= #classified.model %></li>
<h3 class="dark-grey">Description</h3>
<li><%= #classified.description %></li>
<li><%= link_to "Back", '/' , :class => "link" %></li>
<li><%= link_to #classified.user.first_name, profile_path(#classified.user_id) %></li>
</ul>
</div>
Got the value from the controller
class MessagesController < ApplicationController
before_action :authenticate_user!
def new
#user = User.find_by(id: params[:recipient_id])
#classified = Classified.find_by(id: params[:classified_id])
end
def name
first_name
end
def mailboxer_email(object)
email
end
def create
classifieds = Classified.find_by(id: params[:classified_id])
recipients = User.find_by(id: params[:recipient_id])
conversation = current_user.send_message(recipients, params[:message][:body], params[:message][:subject]).conversation
flash[:success] = "Message has been sent!"
redirect_to conversation_path(conversation)
end
end
and last rendered it in my messages_new view
<div class="center-div">
<div class="messages-box">
<% page_header "Αποστολή μηνύματος" %>
<%= form_tag messages_path, method: :post do %>
<div class="form-group">
<%= label_tag 'message[subject]', 'Αποστολή μηνύματος για την αγγελία : ' %>
<%= label_tag(:classified_id, "#{#classified.title}") %> <!-- integrate this -->
<%= text_field_tag 'message[subject]', nil, class: 'form-control', required: true %> <!-- integrate here -->
</div>
<div class="form-group">
<%= label_tag 'message[body]', 'Μύνημα στον χρήστη : ' %>
<%= label_tag(:recipient_id, "#{#user.first_name}") %>
<%= text_area_tag 'message[body]', nil,rows: 15, cols: 3, class: 'form-control', required: true %> <!-- integrate here -->
</div>
<div class="form-group">
<%= hidden_field_tag(:recipient_id, "#{#user.id}") %>
</div>
<%= submit_tag 'Send', class: 'btn btn-primary' %>
<% end %>
</div>
</div>
Related
I'm creating a prayer website with the ability to comment on a public prayer. When I try to create a comment on a prayer, it returns four errors:
Prayer must exist
User must exist
User can't be blank
Prayer can't be blank
And then every comment creation form on the page is automatically filled in with the text I put in the first comment box, and all of them have the same 4 errors on them. I tried to use the hidden_field_tag to put in the comment form for the right user id and prayer id but they aren't put into the hash for the new comment object, they are separate.
This is the debug stuff at the bottom of the page:
#<ActionController::Parameters {"authenticity_token"=>"abcdefg", "comment"=>#<ActionController::Parameters {"content"=>"Comment comment 1 2 3"} permitted: false>, "user_id"=>"1", "prayer_id"=>"301", "commit"=>"Comment", "controller"=>"comments", "action"=>"create"} permitted: false>
controllers/static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
if logged_in?
#prayer = current_user.prayers.build
#comment = current_user.comments.build
#feed_items = current_user.feed.paginate(page: params[:page])
end
end
end
controllers/comments_controller.rb
class CommentsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
#comment = Comment.create(comment_params)
if #comment.save
flash[:success] = "Comment created!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home', status: :unprocessable_entity
end
end
def destroy
#comment.destroy
flash[:success] = "Comment deleted"
redirect_back_or_to( root_url, status: :see_other )
end
private
def comment_params
params.require(:comment).permit(:content, :prayer_id, :user_id)
end
def correct_user
#comment = current_user.comments.find_by(id: params[:id])
redirect_to root_url, status: :see_other if #comment.nil?
end
end
models/comment.rb
class Comment < ApplicationRecord
belongs_to :prayer
belongs_to :user
default_scope -> { order( created_at: :desc) }
validates :user_id, presence: true
validates :prayer_id, presence: true
validates :content, presence: true, length: { maximum: 140 }
end
views/comments/_comment.html.erb
<li id="comment-<%= comment.id %>">
<%= link_to gravatar_for(comment.user, size: 30), comment.user %>
<span class="user"><%= link_to comment.user.name, comment.user %></span>
<span class="comment-content"><%= comment.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(comment.created_at) %> ago.
<% if current_user?(comment.user) %>
<%= link_to "delete comment", comment, data: { "turbo-method": :delete,
"turbo-confirm": "Are you sure?"} %>
<% end %>
</span>
</li>
views/prayers/_prayer.html.erb
<li id="prayer-<%= prayer.id %>">
<%= link_to gravatar_for(prayer.user, size: 50), prayer.user %>
<span class="user"><%= link_to prayer.user.name, prayer.user %></span>
<span class="content">
<%= prayer.content %>
<% if prayer.image.attached? %>
<%= image_tag prayer.image.variant(:display) %>
<% end %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(prayer.created_at) %> ago.
<% if current_user?(prayer.user) %>
<%= link_to "delete", prayer, data: { "turbo-method": :delete,
"turbo-confirm": "Are you sure?"} %>
<% end %>
</span>
<span>
<%= render 'shared/comment_form', prayer_id: prayer.id %>
</span>
<span>
<% if prayer.comments.any? %>
<ol class="comments">
<% prayer.comments.each do |comment| %>
<%= render comment %>
<% end %>
</ol>
<% end %>
</span>
</li>
** views/shared/_comment_form.html.erb * **
<%= form_with(model: #comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<center>
<div class="field">
<%= f.text_area(:content, placeholder: "Comment on this prayer...") %>
</div>
<div><%= hidden_field_tag :user_id, #user.id %></div>
<div><%= hidden_field_tag :prayer_id, prayer_id %></div>
<%= f.submit "Comment", class: "btn btn-primary" %>
</center>
<% end %>
views/shared/_error_messages.html.erb
<% if object != nil && object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
views/shared/_feed.html.erb
<% if #feed_items.any? %>
<ol class="prayers">
<%= render #feed_items %>
</ol>
<%= will_paginate #feed_items,
params: { controller: :static_pages, action: :home } %>
<% end %>
With help from Maxence, I discovered I need to use f.hidden_field versus hidden_field_tag
so I changed the views/shared/_comment_form.html.erb to the following:
<%= form_with(model: #comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<center>
<div class="field">
<%= f.text_area(:content, placeholder: "Comment on this prayer...") %>
</div>
<div><%= f.hidden_field :user_id, value: #user.id %></div>
<div><%= f.hidden_field :prayer_id, value: prayer_id %></div>
<%= f.submit "Comment", class: "btn btn-primary" %>
</center>
<% end %>
In my app, I can call a view ('edit.html.erb') using:
<%= link_to( tag.content, [object, tag], method: :patch) %>
What would be the equivalent if I would want to render it within an other view ?
How would I pass it the params?
Edit
In effect I have a view of the parent, in which I want to list the children (editable). These I could edit separately too. Simple solution is that I, create a _partial which I render from the parent's view as well as from edit.html.erb.
I can call this edit.html.erb (or update) using the link:
<%= link_to( tag.content, [object, tag], method: :patch) %>
This works. Now question is how to render that partial (let's call it _update.html.erb) using render? Still need to pass the parent (i.e. object) and child (tag) params. How do I do that using <% render partial "tags/update" PARAMS %>?
Edit for full example
What I am trying to achieve (in short) - allow editing of tags (child) in annotate view (parent).
For an existing record of model/ object "Annotation", I want to add tags for an attached PDF. I do this in a page/view named "Annotate", that I open from the Annotation edit view (using 'link_to'). This "Annotate" page has 2 columns (see screenshot below):
left pane: 2 sections - 1 to quickly add the tag(s) and - 2 to edit existing tags (listed in a table)
right pane: the PDF
Tags and Annotation have polymorphic relationship (set up as per this question)
_form.html.erb for Annotation
<div class="row">
<div class="col-md-6">
<%= simple_form_for #annotation, html: { class: 'form-horizontal', multipart: true },
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| %>
<div class="btn-toolbar btn-group", role="toolbar">
<%= f.button :submit, 'Save', :class => "btn btn-xs btn-default" %> <%= link_to 'List' , annotations_path, :class => "btn btn-xs btn-default" %> <% unless #annotation.file.blank? %>
<%= link_to 'Annotate', annotate_path(#annotation), :class => "btn btn-xs btn-default" %>
<% end -%>
</div>
<h4>Annotation</h4>
<%= f.error_notification %>
<% if #annotation.file.blank? %>
<%= f.input :file, as: :file, input_html: { accept: ('application/pdf') } %>
<% else %>
<% end -%>
<%= f.input :name, placeholder: 'Enter name' %>
<%= f.input :description, placeholder: 'Description', :input_html => { :rows => 3 } %>
<%= f.association :documenttype, :collection => Documenttype.active.order(:name), prompt: 'Select document type' %>
<%= f.association :sender, label: 'Submitted by' , prompt: 'Select sender' %>
<%= f.association :receiver, label: 'Specific to', prompt: 'Select recipient' %>
<%= f.input :active, as: :boolean %>
<% end -%>
</div>
<% unless #annotation.file.blank? %>
<div class="col-md-6">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "770px", frameBorder: "0" %>
</div>
<% end %>
</div>
<% unless #annotation.new_record? %>
<div class="row">
<hr>
<div class="col-md-6">
<%= render #annotation.comments %>
</div>
<div class="col-md-6">
<%= render 'comments/form', :object => #annotation %>
</div>
</div>
<% end -%>
Annotate view annotate.html.erb
<div class="row">
<div class="col-lg-5">
<div class="btn-toolbar btn-group" role="toolbar">
<%= link_to 'Close', annotation_path(#annotation), :class => "btn btn-xs btn-default" %> <%= link_to 'List' , annotations_path, :class => "btn btn-xs btn-default" %>
</div>
<h4>Annotate document</h4>
<div data-spy="affix">
<%= render 'tags/form', :object => #annotation %>
<br>
<div class="panel panel-default" id="annotationResults">
<%= render 'tags/tag_list', :object => #annotation %>
</div>
</div>
</div>
<div class="col-lg-7" id="file">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "875px", frameBorder: "0" %>
</div>
</div>
tag list _tag_list.html.erb
<table id="tags" class="table table-hover" style="background-color: white; word-wrap: break-word; font-size: 0.9em;" >
<thead>
<tr>
<th>Tagged content</th>
<th>as</th>
<th>in</th>
<th></th>
</tr>
</thead>
<tbody>
<% object.tags.each do |tag| %>
<% unless tag.content.blank? %>
<tr data-tag-id='<%= tag.id %>', class='show-tag'>
<td style="word-wrap: break-word;"><%= link_to( tag.content, [object, tag], method: :patch) %>
<td><%= tag.tagtype.name %></td>
<td><%= tag.tagtype.typeoftag %></td>
<td><%= link_to '', [object, tag], method: :delete, data: { confirm: 'Please confirm!' }, :class => "glyphicon glyphicon-trash" %></td>
</tr>
<tr data-tag-id='<%= tag.id %>', class='edit-tag'>
<td colspan="4"><%= render partial: 'shared/tester' %><%#= render partial: 'tags/update', object: #tag.tagable, tag: #tag %></td>
</tr>
<% end -%>
<% end -%>
</tbody>
</table>
tag update form _update.html.erb
<%= simple_form_for [object, tag], html: { class: 'form-horizontal', multipart: true },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
boolean: :horizontal_boolean
} do |f| %>
<div class="btn-toolbar btn-group" role="toolbar">
<%= f.button :submit, 'Save', :class => "btn btn-xs btn-default" %>
</div>
<%= f.error_notification %>
tag id = <%= #tag.id %>
<%= f.input :content, placeholder: 'Tagged content'%>
<%= f.association :tagtype, prompt: 'Select tag type', :collection => Tagtype.active.order(:name).where(:documenttype => #tag.tagable.documenttype_id) %>
<%= f.input :location, prompt: 'add as: x1, y1, x2, y2' %>
<% end -%>
Routes
Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users
concern :tagable do
resources :tags, only: [:new, :index, :create, :edit, :update]
end
resources :users, :documenttypes, :tagtypes, :business_partners
resources :tags, only: [:show, :edit, :destroy, :index]
resources :documents do
resources :comments
resources :tags, concerns: :tagable
get "pdf", on: :member
end
resources :annotations do
resources :comments
resources :tags
get "pdf", on: :member
end
get "annotations/:id/annotate" => "annotations#annotate", as: 'annotate'
Tags controller
class TagsController < ApplicationController
def index
#tags = Tag.all.order(:tagable)
end
def show
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
end
def edit
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
#tag.update(tag_params)
end
def create
tagable = detect_tagable
tagable.tags.create(tag_params)
redirect_to tagable_path(tagable)
end
def update
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
render 'edit'
# #tag.save
#tag.update(tag_params)
end
def destroy
tagable = detect_tagable
#tag = tagable.tags.find(params[:id])
#tag.destroy
redirect_to tagable_path(tagable)
end
private
def tagable_path(tagable)
case tagable
when Document
document_path(tagable)
when Annotation
annotate_path(tagable)
else
fail 'Unknown tagable'
end
end
def detect_tagable
if params[:annotation_id]
Annotation.find(params[:annotation_id])
elsif params[:document_id]
Document.find(params[:document_id])
else
fail 'Tagable not found'
end
end
def tag_params
params.require(:tag).permit(:content, :location, :tagtype_id, annotation_attributes: { annotation_ids:[] }, document_attributes: { document_ids:[] })
end
end
This is what I have made - if there is a better way in Rails (which I can image) more then willing to learn.
The approach taken here should be to use nested forms, accepts_nested_attributes_for with allow_destroy: true and reject_if for the validations.
to destroy nested records, use accepts_nested_attributes_for :tags, allow_destroy: true and ensure that (besides :id) also :_destroy
is added to strongparams
to use validations for nested fields, use
accepts_nested_attributes_for :tags, allow_destroy: true,
reject_if: :something_to_check
I have 2 models.
Scoreboard Model : can have many teams
Team Model : belongs to Scoreboard
Teams has the follow columns:
name: string
win,loss,tie: integer
On the Team#Index view, I have a collection of all the teams associated to the Scoreboard. Also on that page, I can render an edit form on top of each team object and update it through ajax. Here is the relevant code:
Team#Index View:
<div class="team-list">
<%= render #teams.reject(&:new_record?) %>
</div>
_team.html.erb
<div class="row team-div" id="team_<%=team.id%>">
<%= link_to (scoreboard_team_path(#scoreboard, team)) do %>
<div class="col-xs-4 team-div-1"> <%= team.name %> </div>
<% end %>
<%= link_to (edit_scoreboard_team_path(#scoreboard, team)), remote: true, class: "team-edit-link" do %>
<div class="col-xs-6 team-data">
<div class="row">
<div class="col-xs-4 team-div-2"><%= team.win %> </div>
<div class="col-xs-4 team-div-2"><%= team.loss %> </div>
<div class="col-xs-4 team-div-2"><%= team.tie %></div>
</div>
</div>
<% end %>
</div>
As you can see, I have an edit link available which renders an edit form in place of the team object in question through ajax. The edit form only updates the win,loss,tie columns.
Edit form rendered:
<%= form_for [#scoreboard, #team], remote: true do |f| %>
<div class="row team-edit-form">
<div class="col-xs-4 edit-team-1">Placeholder</div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :win, min: 0, max: 9999, class: "form-control", placeholder: "0" %></div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :loss, min: 0, max: 9999, class: "form-control", placeholder: "0" %></div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :tie, min: 0, max: 9999, class: "form-control", placeholder: "0" %></div>
<div class="col-xs-2 edit-team-3"> <%= f.submit "Done", :data => {:disable_with => "Saving..."}, class: "btn btn-primary" %></div>
</div>
<% end %>
Team#update Controller Method(which by ajax reloads the newly edited team object div):
def update
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#team = #scoreboard.teams.find(params[:id])
if #team.update_attributes(team_params)
respond_to do |format|
format.html {redirect_to scoreboard_teams_path(#scoreboard)}
format.js
end
else
respond_to do |format|
format.html {redirect_to scoreboard_teams_path(#scoreboard)}
format.js { render action: "update_error" }
end
end
end
Now for my problem. All the above happens on the team#index view by ajax.
On the team#show view, I would like to edit only the team name without ajax.
So far, this is what the team#show view looks like:
Team#show View
<h3> <%= #team.name %> <h3>
<%= form_for [#scoreboard, #team] do |f| %>
<div class="col-xs-4"><%= f.text_field :name, required: true, maxlength: 30, class: "team-name-field form-control", placeholder: "Enter name" %></div>
<div class="col-xs-1"> <%= f.submit "Update", :data => {:disable_with => "Saving..."}, class: "btn btn-primary" %></div>
<% end %>
Upon submission, I would like to update the name and then redirect the page back to the team#show(no ajax required). Currently, this form also routes to the same update method. Is it possible to use the same update method but execute different response code for the team#show view? If not, how can I have a customized update code executed when I submit the form on the team#show page?
I'm not sure you can use a different respond_to as you can only redirect or render once in an action.
One approach would be to create a new route / controller method for updating the team name.
routes
resources :teams do
member { post 'update_name' }
end
show.html.erb
In the view, you can post to the above route and in the controller, create a method for the new route.
<%= form_for #team, :url => update_name_team_path(#team)
teams_controller
def update_name
#team = Team.find(params[:id])
redirect_to team_path(#team)
end
Yes, you can do this by checking the request type or sending a flag/keyword to check for the response to render, I would do it like :
Add hidden_field for request param in edit form like :
<%= form_for [#scoreboard, #team], remote: true do |f| %>
<div class="row team-edit-form">
<div class="col-xs-4 edit-team-1">Placeholder</div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :win, min: 0, max: 9999, class: "form-control", placeholder: "0" %>
<%= f.hidden_field :request, 'js' %> </div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :loss, min: 0, max: 9999, class: "form-control", placeholder: "0" %></div>
<div class="col-xs-2 edit-team-2"><%= f.number_field :tie, min: 0, max: 9999, class: "form-control", placeholder: "0" %></div>
<div class="col-xs-2 edit-team-3"> <%= f.submit "Done", :data => {:disable_with => "Saving..."}, class: "btn btn-primary" %></div>
</div>
<% end %>
Add hidden_field for request param in name edit form in show page like :
<%= form_for [#scoreboard, #team] do |f| %>
<div class="col-xs-4"><%= f.text_field :name, required: true, maxlength: 30, class: "team-name-field form-control", placeholder: "Enter name" %>
<%= f.hidden_field :request, 'http' %> </div>
<div class="col-xs-1"> <%= f.submit "Update", :data => {:disable_with => "Saving..."}, class: "btn btn-primary" %></div>
<% end %>
Team#Update Method will be like :
def update
#scoreboard = Scoreboard.find(params[:scoreboard_id])
#team = #scoreboard.teams.find(params[:id])
if #team.update_attributes(team_params)
redirect_to scoreboard_teams_path(#scoreboard) if params[:request] == 'http'
render "" if params[:request] == 'js'
else
redirect_to scoreboard_teams_path(#scoreboard) if params[:request] == 'http'
render action: "update_error" if params[:request] == 'js'
end
end
I'm following this tutorial to set up Devise integration with Stripe: http://www.jaredrader.com/blog/2013/12/18/a-stripe-integration
I have successfully setup Stripe as detailed and created the various controllers, models and views.
However, the forms are creating an ArgumentError in Users::Registrations#new
Here's the error code:
ArgumentError in Users::Registrations#new
Showing /home/action/workspace/mediadb/app/views/devise/registrations/new.html.erb where line #62 raised:
First argument in form cannot contain nil or be empty
The form:
<div class="panel panel-default">
<div class="panel-heading">
<% if params[:plan] == "2" %>
<h1>Sign up with premium!</h1>
</div>
<div class="panel-body">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'plan', params[:plan] %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: "form-control" %>
</div>
<h2>Payment</h2>
<%= f.hidden_field :stripe_card_token %>
<div class="form-group">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, name: nil, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :card_code, "Security Code on Card (CVV)" %>
<%= text_field_tag :card_code, nil, name: nil, class: "form-control" %>
</div>
<div class="form-group">
<%= label_tag :card_month, "Card Expiration" %>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"}%>
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"}%>
</div>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
<div class="form-group">
<%= f.submit "Sign up", class: "btn btn-lg btn-success" %>
</div>
<% end %>
</div>
<% else %>
<h1>Sign up for free</h1>
</div>
<div class="panel-body">
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), html: { id: "free_plan"}) do |f| %>
<%= devise_error_messages! %>
<%= hidden_field_tag 'plan', params[:plan] %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, autofocus: true, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :email %>
<%= f.email_field :email, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: "form-control" %>
</div>
<div class="form-group">
<%= f.submit "Sign up", class: "btn btn-lg btn-primary" %>
</div>
<% end %>
<% end %>
</div>
</div>
The routes.rb file:
Rails.application.routes.draw do
resources :lists
resources :publications
resources :contacts
devise_for :users, controllers: { registrations: 'users/registrations' }
devise_scope :user do
get '/sign_up', to: 'users/registrations#new', as: :sign_up
get '/sign_in', to: 'devise/sessions#new', as: :sign_in
get '/:id/edit', to: 'users/registrations#edit', as: :edit
put 'users/update_plan', :to => 'users/registrations#update_plan'
put 'users/cancel_plan', :to => 'users/registrations#cancel_plan'
end
resources :users, only: [:index, :show]
# root should always be last
root to: 'pages#home'
end
The Registration controller:
class Users::RegistrationsController < Devise::RegistrationsController
def new
unless (params[:plan] == '1' || params[:plan] == '2')
flash[:notice] = "Please select a plan to sign up."
redirect_to root_url
end
end
def update_plan
#user = current_user
#user.update_attributes(plan_id: params[:plan], email: params[:email], stripe_card_token: params[:user][:stripe_card_token])
if #user.plan_id == 2
#user.save_with_payment
redirect_to edit_user_registration_path, notice: "Updated to premium!"
else
flash[:error] = "Unable to update plan."
render :edit
end
end
def cancel_plan
#user = current_user
if #user.cancel_user_plan(params[:customer])
#user.update_attributes(stripe_customer_token: nil, plan_id: 1)
flash[:notice] = "Canceled subscription."
redirect_to edit_user_registration_path
else
flash[:error] = "There was an error canceling your subscription. Please notify us."
render :edit
end
end
private
def build_resource(*args)
super
if params[:plan]
resource.plan_id = params[:plan]
if resource.plan_id == 2
resource.save_with_payment
else
resource.save
end
end
end
def setup
plans = Plan.all
plans.each do |plan|
unless plan.id == 1
#startup_plan = plan
end
end
end
end
Any idea what's wrong?
Update Users::RegistrationsController#new as follows
def new
if (params[:plan] == '1' || params[:plan] == '2')
super
else
flash[:notice] = "Please select a plan to sign up."
redirect_to root_url
end
end
Validation for the create action are not working, I have made validation for the field to be present, but if I keep the fields empty and press submit, I get routing error, if I fill in the complete fields, It works perfectly fine. Also, the validation works perfectly fine for the update action.
Here is the view:
<%= stylesheet_link_tag 'gmaps4rails' %>
<%= form_for #estate, :html => { :class => 'form-horizontal',:multipart => true } do |f| %>
<% if #estate.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#estate.errors.count, "error") %> prohibited this estate from being saved:</h2>
<ul>
<% #estate.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<script>
function enableDisable(bEnable, textBoxID)
{
document.getElementById(textBoxID).disabled = !bEnable
}
</script>
<div class="control-group">
<%= f.label :Name, "Property/Tenant Name", :class => 'control-label' %>
<div class="controls">
<%= f.text_field :Name, :class => 'text_field', :placeholder => "e.g., Saxbys Coffee" %>
</div>
</div>
<div class="control-group">
<%= f.label :Address, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :Address, :class => 'text_area', :cols => '10', :rows => '10', :placeholder => "e.g., 1236 36th Street NW Washington, DC 20007" %>
</div>
</div>
<div class="control-group">
<%= f.label :asset, "Upload Picture", :class => 'control-label' %>
<div class="controls">
<%= f.file_field :asset %>
</div>
</div>
<% if #estate.asset.present? %>
<div class="control-group">
<%= f.label "Delete Existing Picture", :class => 'control-label' %>
<div class="controls">
<%= f.check_box(:delete_asset) %>
</div>
</div>
<% end %>
<!-- <div class="control-group">
<%= f.label :Mgmt, "Would you like to share this property with your Real Estate Management Company?", :class => 'control-label' %>
<div class="controls">
<input type="checkbox" id="chkbox" onchange="document.getElementById('txtBox').disabled=!this.checked;" checked="checked" />
</div>
</div> -->
<% if current_user.Company.nil? %>
<div id="flip"><a>Would you like to share this property with your Management Company?</a></div>
<br />
<div id="panel">
<div class="control-group">
<%= f.label :Mgmt, "Company Name", :class => 'control-label' %>
<div class="controls">
<%= f.text_field :Mgmt, :class => 'text_field', :id => 'txtBox'%>
</div>
</div>
<div class="control-group">
<%= f.label :companyemail, "Company Email", :class => 'control-label' %>
<div class="controls">
<%= f.text_field :companyemail, :class => 'text_field', :id => 'txtBox'%>
</div>
</div>
</div>
<% end %>
<div class="form-actions">
<% if current_page?(controller:"estates", action:"edit", :id => params[:id] || 0)%>
<%= f.submit "Update Property Details", :class => 'btn btn-info' %>
<% else %>
<%= f.submit "Upload Property Details", :class => 'btn btn-info' %>
<% end %>
<% end %>
<script>
$(document).ready(function(){
$("#flip").click(function(){
$("#panel").slideToggle("slow");
});
});
</script>
Here is the controller:
def create
# #estate = Estate.new(params[:estate])
if current_user.Company.nil?
#estate = current_user.estates.build(params[:estate])
else
serve = User.find(##key)
#estate = Estate.new(params[:estate])
#estate.user_id = serve.id
#estate.Mgmt = current_user.Company
end
respond_to do |format|
if #estate.save
if current_user.Company.nil?
if #estate.companyemail = ''
#
else
EstateMailer.company_confirmation(#estate).deliver
end
end
format.html { redirect_to #estate, notice: 'Property details were successfully updated.' }
format.json { render json: #estate, status: :created, location: #estate }
else
format.html { render action: "new" }
format.json { render json: #estate.errors, status: :unprocessable_entity }
end
end
end
Error message:
No route matches {:action=>"show", :controller=>"estates", :id=>#<Estate id: nil, Name: "", Address: "", created_at: nil, updated_at: nil, user_id: 5, asset_file_name: nil, asset_content_type: nil, asset_file_size: nil, asset_updated_at: nil, Mgmt: "", companyemail: "", latitude: nil, longitude: nil, gmaps: nil>}
routes.rb
resources :feedbacks
root to: 'home#index'
devise_for :users, path_names: {sign_in: "login", sign_out: "logout"},
controllers: {omniauth_callbacks: "omniauth_callbacks"}
resources :profiles
resources :estates do
resources :records do
resources :documents
end
end
get 'faq/faqs'
match '/records',to: 'estates#record'
get 'management/index'
match 'management/show', to: 'management#show'
match 'management/showrecord', to: 'management#showrecord'
after a little chat with Hrishikesh Sardar the bug was fixed, the problem was in if block of the create action:
if current_user.Company.nil?
#estate = current_user.estates.build(params[:estate])
else
serve = User.find(##key)
#estate = Estate.new(params[:estate])
#estate.user_id = serve.id
#estate.Mgmt = current_user.Company
end
this line:
#estate = current_user.estates.build(params[:estate])
had to be replaced by:
#estate = Estate.new(params[:estate])
#estate.user_id = current_user.id
somehow current_user.estates.new(params[:estate]) didn't worked, even if the relation between estate and user was built as required.