Rails: Access parameters in view after form submission - ruby-on-rails

In my Rails 3.2 project, I have a form to create a new site in new.html.erb in app/views/sites/
<%= form_for(#site) do |site_form| %>
...
<div class="field">
<%= site_form.label :hash_name %><br />
<%= site_form.text_field :hash_name %>
</div>
...
<div class="actions">
<%= site_form.submit %>
</div>
<% end %>
Then the create function in sites_controller.rb
def create
#site = Site.new(params[:site])
respond_to do |format|
if #site.save
format.html { redirect_to #site }
else
format.html { render action: "new" }
end
end
end
Then after the user submits, I want to show the hash_name that the user just submitted, in show.html.erb
You just put in <%= params[:hash_name] %>.
But accessing params[:hash_name] doesn't work. How can I access it?

You're redirecting to a different action - this will reset all the parameters you passed to the create action.
Either pass hash_name as a parameter like the other answer suggests, or just fetch it straight from the #site object.

Just append them to the options:
redirect_to #site, :hash_name => params[:hash_name]

Related

Allow user to complete form with a delay, error : undefined method `errors' for nil:NilClass

I try to allow user to fill the form with a delay between each user,
The delay is set to 100 between the last user registered in my database and the new one
Here is what I do in my controller :
class EmailsController < ApplicationController
def index
redirect_to root_path
end
def new
#email = Email.new
end
def create
if Time.now - Email.last.created_at < 100
respond_to do |format|
format.html{render :new, notice: "Wait !"}
end
else
respond_to do |format|
#email = Email.create(email_params)
if#email.persisted?
format.html {redirect_to invoice_index_path, notice: 'Email validated '}
else
format.html{render :new}
end
end
end
end
private
def email_params
params.require(:email).permit(:email, :id_user)
end
end
My view :
<div class="container">
<% if flash[:notice].present?%>
<center><p id="notice" class="alert alert-success"><%= flash[:notice] %></p></center>
<%end%>
<center><h1>Nouvelle Connection </h1></center>
<%= form_with model: #email, local: true do |form|%>
<% if #email.errors.any? %>
<div id="error explanation" class="alert alert-danger">
<p>Erreur(s) : </p>
<ul>
<% #email.errors.full_messages.each do |message|%>
<li><%=message%></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= label_tag :email %> :
<%= form.email_field :email, placeholder: "Insérez votre email", class: "form-control" %>
</div>
<div class="form-group">
<%= form.submit class: "btn btn-primary btn-lg btn-block", value: "Se connecter" %>
</div>
<%end%>
</div>
When I fill the form, nothing happen, just the url change from http://localhost:3000/ to http://localhost:3000/emails and when I re-click on Validate, it goes to http://localhost:3000/emails/53 with the error The action 'update' could not be found for EmailsController but I guess I have this error because I don't have any update/edit in my controller.
Do you know how to fix that to allow me a delay between each user ?
Edit : I now have the error undefined method errors for nil:NilClass in my view at the line <% if #email.errors.any? %>. I understand this is because my #email is nil but I tried to integrate this in my view :
<% if #email.nil?%>
<%= Wait for the moment %>
<%end%>
Also tried : <% if #email&.errors&.any? %> why so, I return to the URL : http://localhost:3000/emails
But still have the same error, do you know how to fix it ?
First off, in your view you check for notice.present? and that should be flash[:notice].present?. So then the error will be shown.
Secondly, in your controller you are actually first creating the email, and only then checking if it should be created, and then not even removing it? So the only result is that people will see a notice, but the email would still be created.
So instead do something like:
def create
if Time.now - Email.last.created_at < 100
respond_to do |format|
#email = Email.new(email_params)
format.html do
flash[:notice] = 'Wait! You cannot enter emails so quickly!'
render :new
end
end
else
respond_to do |format|
#email = Email.create(email_params)
if #email.persisted?
format.html {redirect_to invoice_index_path, notice: 'Email validé '}
else
format.html{render :new}
end
end
end
end
Secondly this does seem to mean that any user wanting to enter a new email, will be punished if another user has also entered another email. So in that case you might want to check as follows:
Email.where(created_by_id: current_user.id).last
to only check for Email 's the current user has entered (but maybe that is taking your problem/solution too far?).
Also note there are much better/efficient ways to throttle requests (rate limiting) using apache/nginx (which is probably how it will be deployed), so is this actually a good approach to handle in your ruby on rails code?

Getting the ability to post in a model under a different controller Rails

I decided to make a clone of Facebook in Rails. First I'm working on getting status updates working. I got it setup as the StatusUpdate model that is called by the Pages controller to render on the index page.
The issue I'm having is that if I use form_for(#status_update) I get:
undefined method to_key' for
<StatusUpdate::ActiveRecord_Relation:0x00000000049d3448>
Did you mean? to_set to_ary
If I use form_with(model: #status_update):
undefined method to_model' for
<StatusUpdate::ActiveRecord_Relation:0x000000000471cd80>
Did you mean? to_xml
If I use form_with(model: status_update):
undefined local variable or method status_update' for
<#<Class:0x0000000005801678>:0x0000000002ec8ec8>
Did you mean? #status_update
My action:
def create
#status_update = StatusUpdate.new(status_update_params)
respond_to do |format|
if #status_update.save
format.html { redirect_to root_path, notice: 'Status successfully posted!' }
else
format.html { render :new }
end
end
and erb view:
<%= form_with(model: status_update) do |sp| %>
<div class="form-group">
<%= sp.label :status_update %>
<%= sp.text_area :status_update, class: 'form-control', rows: 15, placeholder: 'Content' %>
</div>
<div class="form-group">
<%= sp.submit 'Submit', class: 'btn btn-primary' %>
</div>
<% end %>
I think you are missing the initialisation step. You have to first initialise the model object in new action of the controller.
def new
#status_update = StatusUpdate.new
end
and then use it in form.
form_with(model: #status_update)
The argument to form_with must be a single model instance. Not a whole collection.
class Pages
def index
#status_updates = StatusUpdate.all
#new_status_update = StatusUpdate.new
end
end
---
# app/views/pages/index.html.erb
<%= form_with(model: #new_status_update) %>
# ...
<% end %>
<%= #status_updates.each do |s| %>
# ...
<% end %>
Which is why you need to pay attention to pluralization when naming variables!
Another way to solve this is by using a condition:
# app/views/status_updates/form.html.erb
<%= form_with(model: local_assigns(:status_update) || StatusUpdate.new) %>
...
<% end %>
Which lets you use the form as a partial even without a StatusUpdate instance:
# app/views/pages/index.html.erb
<%= render partial: 'status_updates/form' %>
<%= #status_updates.each do |s| %>
# ...
<% end %>

.each loop returns []. Form / controller issue

I have RoR 4.2.0beta. (Although it s irrelevant as this is a beginer problem).
My form does not insert in the database the "propuneres" that I am creating trough it. And as a result they do not show in the index page when I get redirected to it. They show up when I create them through the console.
class PropuneresController < ApplicationController
before_action :prop_params
def new
#user = User.find(params[:user_id])
#propunere = #user.propuneres.build
end
def create
#user= User.find(params[:user_id])
#propunere = #user.propuneres.new(params[:prop_params])
#propunere.save
if #propunere.empty?
render 'new'
else
redirect_to user_propuneres_path
end
end
def index
#user = User.find(params[:user_id])
#propunere = #user.propuneres(params[:prop_params])
end
private
def prop_params
params.require(:propunere).permit(:titlu, :body)
end
end
new.html.erb
<h2> Propunere Nouă </h2>
<%= form_for #propunere do |f| %>
<ul>
<% #propunere.errors.full_messages.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<p>
<%= f.label :titlu %><br />
<%= f.text_field :titlu %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
index.html.erb
<h2> Propuneri: </h2>
<% #propunere.each do |p| %>
<%= p.titlu %>
<%= p.body %>
<% end %>
Not sure if its relevant, but you have code
#propunere.save
if #propunere.empty?
render 'new'
else
redirect_to user_propuneres_path
end
Object #prorunere will never be empty, since you have
#propunere = #user.propuneres.new, which assigneds user_id to your #propunere object and
render 'new' will never be rendered, therefore you wont see any validation errors and never find out why your record wasnt created
Also since you have that piece of code, and dont see errors, this is what most like broke your code
#user.propuneres.new(params[:prop_params]) - you should use your permitted params, so it'd look like
#propunere = #user.propuneres.new(prop_params)
I've cloned your repo, here's the problem: in new.html.erb you had
&lt%= form_for #propunere, url: new_user_propunere_path(#user, #propunere), html: { method: :get } do |f| %&gt
Both the url and the method are wrong. user_propuneres_path will give you the correct url for the create action and the correct method is :post, not :get. This is why you never reached the create action.
You also need to change from #propunere = #user.propuneres.new(params[:propunere]) to #propunere = #user.propuneres.new(prop_params), otherwise you'll get a ActiveModel::ForbiddenAttributesError exception.
You can see all the routes in the app by running rake routes in the terminal.
I don't think you need the params in your index action:
#propunere = #user.propuneres
and it would be more logical to write it in plural since you have many of them.
Edit:
As Avdept suggested your create action should look like this:
def create
#user = User.find(params[:user_id])
#propunere = #user.propuneres.new(prop_params)
respond_to do |format|
if #propunere.save
format.html { redirect_to user_propuneres_path(#user), notice: 'Your propunere has been saved' }
else
format.html { render :new }
end
end
end
Do you have any validations for the Propunere model? Maybe the model is invalid. You can use
the create! method instead of create for testing, because it will throw an exception if the object cannot be saved. Also try puts #propunere.inspect before persisting it and check that the contents of the object are ok, the output will be shown in the development log.

Rendering edit form via ajax

I am attempting to render a form via ajax. It works fine for creating a new venue, but when attempting to edit an existing venue the venue data should load into the form. The form (_modal) is rendered when the edit venue link is called, however the form is processed as a new form, with all fields blank. Calling #venue at the binding.pry, we see the correct venue object.
How would I get the form to process as edit rather than new? Ideas:
respond_to do |format|
format.js { *do stuff* }
Add more parameters to form?
Do it manually - change form attributes and/or fill in data with jquery
Appreciate any suggestions!
_modal.html.erb:
<section id="venue-modal" class='modal' title="Venue Form" class="">
<%= simple_form_for(#venue, remote: true) do |v| %>
<div id='closeButton'><a href='#'>x</a></div>
<% binding.pry %>
<%= v.input :name, label: "Venue Name" %>
<%= v.input :city %>
<%= v.input :state, collection: States.us_states %>
<div class="actions">
<%= v.submit 'Submit', class: 'button' %>
</div>
<% end %>
</section>
Renders following html:
<form accept-charset="UTF-8" action="/venues" class="simple_form new_venue" data-remote="true" id="new_venue" method="post">
Link calling the modal:
<%= link_to edit_venue_path(venue), :remote => true, :class => "edit_venue_link" do %>
Controller:
def edit
id = params[:id]
if id == 'new'
#venue = Venue.new
else
#venue = Venue.find(id)
end
end
Venue.js:
$('.edit_venue_link').on("ajax:success", function(e, data, status, xhr) {
// stuff happens
Replace the modal content with this line of code in modal.js.erb:
$('#venue-modal').html("<%= escape_javascript(render partial: 'venues/modal') %>");
Controller:
def edit
id = params[:id]
if id == 'new'
#venue = Venue.new
else
#venue = Venue.find(id)
end
respond_to do |format|
format.js { render 'venues/modal' }
end
end
Section tags moved out of the modal partial. The form then recognizes #venue and the fields load appropriately.

How to redirect to a certain location in a page?

I have a blogging application with comments.
Currently, the comments controller has a standard create action
def create
#comment = current_user.build(params[:comment])
respond_to do |format|
if #comment.save
format.html { redirect_to #comment.post }
end
end
After creation, the user is redirected to the blog post for which the comment was made. How do I redirect lower down in the page, to where the new comment is?
posts/show.html.erb
<div id="post_show">
<%= #post.content %>
<%= render #post.comments %>
</div>
comments/_comment.html.erb
<div id="comment_partial">
<%= comment.content %>
</div>
Is there something I can add to my HTML, then reference in my controller? Do I need to "save" the location somehow? Thanks for helping out a newbie!
You can use the anchor option in path helpers, e.g.
redirect_to post_path(#comment.post, anchor: 'some-id')

Resources