What Is The Best Method To Create Edit Forms? - ruby-on-rails

I'm working on an application in Ruby on Rails (Ruby 2 - Rails 4 - Bootstrap 3)
I have used the simple_form gem to build the forms, like signup and register, but how do you create a form that loads an object from the database and allows a user to edit the details?
Say we had a Product table in the database and I wanted to create a form to load the details of that product into the form and allow the user to edit a product's description, price, etc.
I have had a look around but still not clear.
Thanks.

First you need to put a link from your view to the edit action where you send the product as a parameter this usually goes in your index (app/views/products/index.html.erb). It should look something like this:
<%= link_to 'Edit', edit_product_path(product) %>
Then you need to make sure you have the edit action in your Products controller (app/controllers/products_controller.rb):
def edit
end
Now your edit.html.erb (app/views/products/edit.html.erb) should look something like this:
<h1>Editing product</h1>
<%= render 'form' %>
<%= link_to 'Show', #product %> |
<%= link_to 'Back', product_path %>
And finally the form you are rendering that should be located in app/views/_form.html.erb should look like this:
<%= form_for(#product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :descriptions %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Tip: When you generate a Scaffold with the rails generate Scaffold command, it automatically creates the edit, delete, show and new actions for your model and all the views and classes I mentioned above.
rails generate Scaffold Product name:string description:text price:decimal
Hope it helps!

Related

Weird redirection when updating datas

I generated a scaffold for a portfolio via the Rails command, rails g portfolio titre:string, thumbnail:string lien:string description:text. I also added FriendlyId to get a better URL, and that's about all. Here is the 'update' action.
def update
if #portfolio.update(portfolio_params)
redirect_to #portfolio, notice: 'Portfolio mis à jour.'
else
render :edit
end
end
However, when trying to update a project in my portfolio, the submit button tries to get to 'portfolio#update' via patch, but puts a '.' instead of a '/' which gives me No route matches [PATCH] "/portfolios.test-1"
For the route, I only have resources :portfolios
edit : added the form
<%= form_for #portfolio, url: portfolios_path(#portfolio) do |f| %>
<% if portfolio.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(portfolio.errors.count, "error") %> prohibited this portfolio from being saved:</h2>
<ul>
<% portfolio.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :titre %>
<%= f.text_field :titre %>
</div>
<div class="field">
<%= f.label :categorie %>
<%= f.text_field :categorie %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :thumbnail %>
<%= f.file_field :thumbnail %>
</div>
<div class="field">
<%= f.label :lien %>
<%= f.text_field :lien %>
</div>
<div class="actions">
<%= f.submit 'Enregistrer' %>
</div>
<% end %>
I didn't have any other possibilities that doing #portfolio, url: portfolios_path(#portfolio), otherwise Rails considered that '#portfolio' was nil
edit 2 : added the private 'set_portfolio' params
private
# Use callbacks to share common setup or constraints between actions.
def set_portfolio
#portfolio = Portfolio.friendly.find(params[:id])
end
What's wrong with my app ?
portfolios_path is the collection path.
change it portfolio_path should fix it.
<%= form_for #portfolio, url: portfolio_path(#portfolio) do |f| %>
I guess you are going to use this form for creating new portfolio as well, so change it to <%= form_for(#portfolio) %> should fix it and will also work for both cases. form_for will submit to correct path.

Rendering a form that creates an object that is Nested under two other models.

I'm building a rails app that has a an object that is created /nested underneath two objects.
Routes.rb
resources :pages do
resources :referralpages do
resources :rewards do
end
end
end
I've just added the rewards resource and have this for my form for creating a new reward
<%= form_for ([#referralpage, #reward]) do |f| %>
<% if #reward.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reward.errors.count, "error") %> prohibited this reward from being saved:</h2>
<ul>
<% #reward.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name %><br>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :level %><br>
<%= f.text_field :level, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :dscount %><br>
<%= f.text_field :discount, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
I need help getting the form_for ([#referralpage, #reward]) portion working.
Here's the error message I'm getting when clicking the new reward button:
undefined method `referralpage_rewards_path'
<%= form_for ([#referralpage, #reward]) do |f| %>
my guess is that it's routing to the incorrect path. What's the proper syntax to get this to work?
I think it should render this path
new_page_referralpage_reward
The point of this feature is to render rewards in the referral/show.html.erb page
I have created an index partial in my rewards view file and am rendering it in the show action of the referralpages/show.html.erb file.
I think you cannot put more than one resource path in form_for which cause invalid path.
Why you want to put 2 resource path in form?
Do you plan to save the same data for referral & rewards Model?
If, yes use just one path and make a create method in your controller to save to other model.
From this point of view:
The point of this feature is to render rewards in the
referral/show.html.erb page
If you only plan to render the data of rewards to referral/show.html.erb,
in your referral controller
def show
#rewards = Reward.all #example
end
Unless, you have model relationships like:
#Reward Model
belongs_to :refferal
#Referral Model
has_many :rewards or has_one :reward
With model realtionship:
def show
#referal = Referral.all #example
end
show.html.erb View # iterate it:
<%for referral in #referral%>
<% referral.rewards %> # need to iterate if has many
or
<%= referral.reward... %>
<%end%>

How to get a nested text_area to render properly

I have a scaffold called submits that has a form for creating new submissions. I also created a model called question. I've used this model to create different questions in the submission form.I've utilized a join form and use active admin to add/edit questions from the backend. I'm getting this error.
undefined method `submit[question_ids][]' for #<Submit id: nil, name: nil, created_at: nil, updated_at: nil>
submits.rb
class Submit < ActiveRecord::Base
has_and_belongs_to_many :questions
end
question.rb
class Question < ActiveRecord::Base
has_and_belongs_to_many :submits
end
subits/_form.html.erb
<%= form_for(#submit) do |f| %>
<% if #submit.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#submit.errors.count, "error") %> prohibited this submit from being saved:</h2>
<ul>
<% #submit.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<div class="field">
<%= f.label :name,"Team Name" %><br>
<%= f.text_field :name, class: "form-control" %>
</div>
<% #questions.each do |question| %>
<div class="field">
<%= f.label(question.question)%>
<%= f.text_area "submit[question_ids][]" %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Apply", class: "btn btn-primary btn-lg" %>
</div>
<% end %>
I'm guessing my error is here:
<%= f.text_area "submit[question_ids][]" %>
I'm just not sure what the correct syntax is. Any suggestions?
For Rails form_for input forms, you need :(whatever attribute) which should be defined in your migration file.
ex.) if you have 'text' attribute in your Submit model you can have your input form for the text attribute just like this. <%= f.text_area :text %>
But in this case it seems like you have a join table for your models, so I think you should fields_for for your join table.
cf.) How do i include Rails join table field in the form?

Rails: one view, model and it's associated model

So, for example, case from http://guides.rubyonrails.org/getting_started.html As you can see, if you try to create invalid post, you will see error messages:
<%= form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
How to implement error messages rendering for associated Comment model, keeping in mind that comment creation form is placed in posts/show view?
Form code is usually kept in the folder of the matching model in a _form.html.erb partial that is rendered in both new.html.erb and edit.html.erb (to see a good example, generate a scaffold for a sample model).
What you can do in your case is render this comments form partial in the posts show action.
app/views/posts/show.html.erb
<%= render 'comments/form', comment: #comment || #post.comments.build # Whatever you have here %>
app/views/comments/_form.html.erb
<%= form_for comment do |f| %>
<%= render 'error_messages', target: comment %>
...
<% end %>
In addition, showing error messages usually is the same in all forms, so in order to remove duplication, you can extract this code into a seperate partial.
app/views/application/error_messages.html.slim # here is slim syntax, convert as nescessary
/ error explanation
/
/ = render 'shared/error_explanation', target: #school
/
- if target.errors.any?
.error-messages
h4 Please correct the following fields:
ul
- target.errors.full_messages.each do |message|
li = message
Hope this helps.

Submit a form to a model from my homepage

I have a links model which has all the generic scaffold created for it, however, rather than go to the link#new page, I'd like to submit a form from my homepage that populates a new record.
I only have one text field, but im not sure how to construct the form. I read somewhere you have to specify the controller in the form field but this doesn't appear to be working.
<%= form_for(:link, #link) do |f| %>
<% if #link.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#link.errors.count, "error") %> prohibited this link from being saved:</h2>
<ul>
<% #link.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :url %><br />
<%= f.text_field :url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You don't need to specify anything if you are using default routes.
If the #link is an object that doesn't exist in database, Rails will automatically think this is a form for #new. So the form action will be /links, and method is post, which is the default resource to #create
In your case, you don't need to do anything, just revise the form code to:
<%= form_for(#link) do |f| %>
....
Besides, you need to prepare #link object in home controller, something like
#link = Link.new
All you have to do is add a url parameter to the form_for helper
<%= form_for :link, url: your_home_path do |f| %>

Resources