I'm trying to include a form partial for the model request in another partial view.
I have a model called request.
class CreateRequests < ActiveRecord::Migration[5.0]
def change
create_table :requests do |t|
t.string :name
t.string :email
t.string :phone
t.string :product
t.string :details
t.timestamps
end
end
end
I have my requests_controller.rb
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
# GET /requests
# GET /requests.json
def index
#requests = Request.all
end
# GET /requests/1
# GET /requests/1.json
def show
end
# GET /requests/new
def new
#request = Request.new
end
# GET /requests/1/edit
def edit
end
# POST /requests
# POST /requests.json
def create
# Create the user from params
#request = Request.new(request_params)
if #email.save
# Deliver the signup email
RequestNotifierMailer.send_email(#request).deliver
flash[:success] = "Thanks! We'll be in touch soon!"
redirect_to :action => 'new'
else
render :action => 'new'
end
end
# PATCH/PUT /requests/1
# PATCH/PUT /requests/1.json
def update
respond_to do |format|
if #request.update(request_params)
format.html { redirect_to #request, notice: 'Request was successfully updated.' }
format.json { render :show, status: :ok, location: #request }
else
format.html { render :edit }
format.json { render json: #request.errors, status: :unprocessable_entity }
end
end
end
# DELETE /requests/1
# DELETE /requests/1.json
def destroy
#request.destroy
respond_to do |format|
format.html { redirect_to requests_url, notice: 'Request was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_request
#request = Request.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def request_params
params.require(:request).permit(:name, :email, :phone, :product, :details)
end
end
The form partial I have requests/_form.html.erb
<%= form_for(request) do |f| %>
<% if request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(request.errors.count, "error") %> prohibited this request from being saved:</h2>
<ul>
<% request.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :phone %>
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :product %>
<%= f.text_field :product %>
</div>
<div class="field">
<%= f.label :details %>
<%= f.text_field :details %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And I included the resource in my config/routes.rb by adding:
resources :requests
I'm trying to include requests/form into static_pages/_requestquote.html.erb:
<div class="actionsHolder">
<div class="buyHolder">
<h2>Starting from <%= price %></h2>
<h3 id="myBtn">
<a href="#">
Request for Quote
</a>
</h3>
</div>
</div>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<%= render :partial => "requests/form" %>
</div>
</div>
However I'm getting the error:
NoMethodError in Products#bigmikepopular113
Showing /Users/beckah/Documents/projects/Envirovacs/app/views/requests/_form.html.erb where line #1 raised:
undefined method `model_name' for #<ActionDispatch::Request:0x007fee89b49040>
Extracted source (around line #1):
1
2
3
4
5
6
<%= form_for(request) do |f| %>
<% if request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(request.errors.count, "error") %> prohibited this request from being saved:</h2>
<ul>
Products#bigmikepopular113 is the controller view where the original partial is conluded, so essentially the structure is
products/bigmikepopular113.html.erb -> static_pages/_requestquote.html.erb -> requests/_form.html.erb
What can I do differently to make sure I can have an embedded partial?
From what I can see, you're not initializing the creation of a New request anywhere. Only under the new action inside your controller, but there's no view corresponding to that action. You only have the view _form.html.erb.
To clarify: every action in your controller, must correspond to a view, sharing the same name as the action inside the controller. Even if it's a partial.
So, def new automatically points to new.html.erb. def index to index.html.erb and so on.
You therefor have two options. Either create a def form inside the controller, and set up the routes in your routes.rb accordingly, or simply write the statement directly inside the view instead of in the controller:
Remove:
<%= form_for(request) do |f| %>
Instead:
<%= form_for Request.new do |f| %>
Hope that'll help.
Related
I am trying to add form validation to a simple blog post form. Currently I am testing for presence of title and description and if I submit an empty form it gives me the errors, but if I fill out the form it still gives me the errors. When I use byebug in my create action for the post_controller it shows the contents of the title and description that I enter but says permitted false.
Here is the form partial:
<%= form_with(model: post, local: true) do |f| %>
<% if post.errors.any? %>
<div class="row center-align">
<div class="card-panel alert alert-danger">
<span class="white-text">
<strong><%= pluralize(post.errors.count, "error") %></strong>
occured:
<ul>
<% post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</span>
</div>
</div>
<% end %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :description %>
<%= f.text_area :description, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :header_image %>
<%= f.file_field :header_image %>
</div>
<div class="mt-1">
<% if post.header_image.present? %>
<small>Current Image</small>
<%= image_tag(post.header_image, width: '100%') %>
<% end %>
</div>
<div class="actions">
<%= f.submit class: 'btn btn-primary mt-1 form-control' %>
</div>
<% end %>
Here is the post_controller:
module Authors
class PostsController < AuthorsController
before_action :set_post, only: [:edit, :update, :destroy]
# GET /posts
def index
#posts = current_author.posts
end
# GET /posts/new
def new
#post = current_author.posts.build
end
# GET /posts/1/edit
def edit
#element = #post.elements.build
end
# POST /posts
def create
#post = current_author.posts.build
if #post.save
redirect_to edit_post_path(#post), notice: 'Post was successfully created.'
else
render :new
end
end
# PATCH/PUT /posts/1
def update
if #post.update(post_params)
redirect_to edit_post_path(#post), notice: 'Post was successfully updated.'
else
render :edit
end
end
# DELETE /posts/1
def destroy
#post.destroy
redirect_to posts_url, notice: 'Post was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = current_author.posts.find(params[:id])
end
# Only allow a list of trusted parameters through.
def post_params
params.require(:post).permit(:title, :description, :header_image)
end
end
end
And her is the post.rb:
class Post < ApplicationRecord
belongs_to :author
has_many :elements
has_one_attached :header_image
validates :title, :description, presence: true
end
The post form was working fine until I tried adding the validations.
When I add buy but and test it I get the following when I run params:
#<ActionController::Parameters {"authenticity_token"=>"1hQyn6kWCiCwAaeaUa1PD9q76D29RF-56LKof1uC64auGtNvA2VCZ-mDLdY7EjCYP9zWpLLvfkgkE33AUZP7Ng", "post"=>{"title"=>"Testing", "description"=>"test"}, "commit"=>"Create Post", "controller"=>"authors/posts", "action"=>"create"} permitted: false>
(byebug)
In the create method, you're not instantiating the Post object with post_params. So, #post.title and #post.description are nil causing the validations to fail.
#post = current_author.posts.build(post_params)
I have a rails scaffold for Accounts and another scaffold for Transactions. The Accounts model as an attribute account_name which is created within the form. For each Transaction, the form then prompts a user to select the account the transaction belongs to which is retrieved from the Accounts account_name field. This displays perfectly but when the Transaction is saved, the Account name does not save in the db or display in my index. When I edit the transaction the account name field is set to blank.
Been stuck on this for so damn long - any advice would be greatly appreciated.
My Account model:
class Account < ActiveRecord::Base
has_many :transactions
end
My Account form looks like this (and saves perfectly in the DB )
<%= form_for(#account) do |f| %>
<% if #account.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#account.errors.count, "error") %> prohibited this account from being saved:</h2>
<ul>
<% #account.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="jumbotron">
<div class="container">
<div class="form-group">
<%= f.label :account_name %><br>
<%= f.text_field :account_name, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :account_number %><br>
<%= f.number_field :account_number, class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit %>
</form>
<% end %>
</div>
</div>
Transaction Model
class Transaction < ActiveRecord::Base
has_many :accounts
end
The Transaction form looks like (I used the Pluck method to retrieve the Accounts account_name value and it displays all the created accounts):
<div class="form-group">
<%= form_for(#transaction) do |f| %>
<% if #transaction.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#transaction.errors.count, "error") %> prohibited this transaction from being saved:</h2>
<ul>
<% #transaction.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "jumbotron">
<form class="needs-validation" novalidate>
<div class="col-md-4 mb-3">
<%= f.label :date %><br>
<%= f.date_select :date, class:"form-control" %>
</div>
<div class="col-md-4 mb-3">
<%= f.label :reference %><br>
<%= f.text_field :reference, class:"form-control" %>
</div>
<div class="col-md-3 mb-3">
<%= f.label :account_name %> <br>
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<%= f.label :description %><br>
<%= f.text_field :description, class:"form-control" %>
</div>
</div>
<div class="col-md-3 mb-3">
<%= f.label :amount %><br>
<%= f.text_field :amount, class:"form-control" %></br>
</div>
</br></br></br></br></br></br>
<div class="form-check form-check-inline">
</br>
<%= f.label :payment %>
<%= f.check_box :payment %> |
<%= f.label :receipt %>
<%= f.check_box :receipt %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>
My transaction controller is as follows:
class TransactionsController < ApplicationController
before_action :set_transaction, only: [:show, :edit, :update, :destroy]
# GET /transactions
# GET /transactions.json
def index
#transactions = Transaction.all
#balance = 0
#transactions.each do |transaction|
if transaction.payment == true
#balance += transaction.amount
else
#balance -= transaction.amount
end
end
end
# GET /transactions/1
# GET /transactions/1.json
def show
end
# GET /transactions/new
def new
#transaction = Transaction.new
end
# GET /transactions/1/edit
def edit
end
# POST /transactions
# POST /transactions.json
def create
#transaction = Transaction.new(transaction_params)
respond_to do |format|
if #transaction.save
format.html { redirect_to transactions_url, notice: 'Transaction was successfully created.' }
format.json { render :show, status: :created, location: #transaction }
else
format.html { render :new }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /transactions/1
# PATCH/PUT /transactions/1.json
def update
respond_to do |format|
if #transaction.update(transaction_params)
format.html { redirect_to transactions_url, notice: 'Transaction was successfully updated.' }
format.json { render :show, status: :ok, location: #transaction }
else
format.html { render :edit }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# DELETE /transactions/1
# DELETE /transactions/1.json
def destroy
#transaction.destroy
respond_to do |format|
format.html { redirect_to transactions_url, notice: 'Transaction was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_transaction
#transaction = Transaction.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def transaction_params
params.require(:transaction).permit(:date, :description, :reference, :account, :amount, :account_id, :payment, :receipt, account_attributes: [:account_name])
end
end
The problem seems to be in the usage of select method for creating a select tag:
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
The second parameter is expected to be an array of two-elements arrays (one for displayed value in the select tag, and another one for the value that is going to be sent as a request parameter).
Thus, the solution you're looking for is going to look something like:
<%= f.select :account_name, Account.pluck(:account_name).map { |name| [name, name] }, {prompt:"Choose Account"}%>
Or you might want to use options_from_collection_for_select method:
<%= f.select :account_name, options_from_collection_for_select(Account.all, :name, :name) %>
You are facing that issue because you need to store the id of the account as a reference in the transaction.
Currently you are saving account name, so it is not prefetching and saving the data
You can use collection_select and tell that save id into DB and display account_name in select tag.
Syntax:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
The :value_method and :text_method parameters are methods to be called
on each member of collection. The return values are used as the value
attribute and contents of each <option> tag, respectively.
Here is the collection_select in your example:
<%= f.collection_select(:account_name,Account.all, :id, :account_name, :prompt => 'Choose Account') %>
Here is the documentation for the same
I'm creating a rails app that allows someone to create an album by adding a title, a description and several pictures. However, I only find on the web a way that needs two controller, one to create the album and another to attach the images on it.
I'm now used to Rails even though I know I still have lots of things to learn.
So far, I managed to allow the user to create something that only allows him to upload to only upload one photo.
So I changed the form part where the file is uploaded, and now, it doesn't save anything...
Here are my files:
_form.html.erb
<%= form_for #pet, html: { multipart: true } do |f| %>
<% if #pet.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#pet.errors.count, "error") %> prohibited this album from being saved:</h2>
<ul>
<% #pet.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 :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :image %><br>
# added :multiple => true
<%= f.file_field :image, :multiple => true %>
<% if f.object.image? %>
<%= image_tag f.object.image.thumb.url %>
<%= f.label :remove_image %>
<%= f.check_box :remove_image %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pets_controller.rb
class PetsController < ApplicationController
before_action :set_pet, only: [:show, :edit, :update, :destroy]
# GET /pets
def index
#pets = Pet.all
end
# GET /pets/1
def show
end
# GET /pets/new
def new
#pet = Pet.new
end
# GET /pets/1/edit
def edit
end
# POST /pets
def create
#pet = Pet.new(pet_params)
if #pet.save
redirect_to #pet, notice: 'Album was successfully created.'
else
render :new
end
end
# PATCH/PUT /pets/1
def update
if #pet.update(pet_params)
redirect_to #pet, notice: 'Album was successfully updated.'
else
render :edit
end
end
# DELETE /pets/1
def destroy
#pet.destroy
redirect_to pets_url, notice: 'Album was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pet
#pet = Pet.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def pet_params
params.require(:pet).permit(:name, :description, :image)
end
end
So my summed up question is the following: is there a simple way to allow my form to save multiple images inside an array where it would be easy to show them up?
Thank you in advance
i have the following situation:
I have a controller for admins , that i use to manage the users (model generated by Devise).
So, i use the actions of another controller to manage the resources "users".
Here my files:
admins_controller.rb
before_action :set_user, only: [:show, :edit, :update, :destroy]
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to admins_index_path, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def set_user
#user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:id)
end
edit.html.erb
<h1>Edit user</h1>
<%= form_for #user, :as => :patch, :url => admins_update_path(id: #user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this line_item from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :id %><br>
<%= f.text_field :id %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :admin %><br>
<%= f.text_field :admin %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The problem is that when i submit the edit , rails gives me an error:
Can you help me? i really don t knok how to fix
thank you
EDIT:
Change your view to drop the :as option, that will fix the params requirement error:
= form_for #user, :url => admins_update_path(id: #user) do |f|
The :as tells form_for to use a different key name than the default class-name based one that you're using in your params.require call.
You should also remove your f.text_field :id - you don't want someone editing that.
Then your permit(...) block will need to include anything else in that form that you want to allow mass-assignment for, most likely you'll want: permit(:email, :admin)
Updated version - I have taken the initial advice provided (thanks for that!) but I'm still having the same issue. I have updated everything below.
I have two models, products that belong to a store.
I'm attempting to display a related object's column (Store.name) in a couple of views for products that belong to a store and can't seem to get the store to save correctly. Please note: Still very new to this and learning.
Model for Product:
class Product < ActiveRecord::Base
belongs_to :store
validates_presence_of :name, :url, :price
end
Model for Store:
class Store < ActiveRecord::Base
has_many :products
has_many :pins, through: :products
accepts_nested_attributes_for :products
end
Controller for Product:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.all
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
#stores = Store.all
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:name, :description, :imageurl, :url, :price, :Store_id)
end
end
Form for products
<%= 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 |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name, "Name" %>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :description, "Description" %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :imageurl, "Image" %>
<%= f.text_field :imageurl, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :url, "Web Address" %>
<%= f.text_field :url, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :price, "Price" %>
$<%= f.text_field :price, class: "form-control" %>
</div>
<div class="form-group">
<%= collection_select(:product, :Store_id, Store.all, :id, :name, {:prompt=> "Select A Store"}, {:class => "form-control"} ) %>
</div>
<div class="form-group">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
<%= params.inspect %>
View for products (show.html.erb):
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #product.name %>
</p>
<p>
<strong>Description:</strong>
<%= #product.description %>
</p>
<p>
<strong>Store Id:</strong>
<%= #product.Store_id %>
</p>
<p>
<strong>Store Name:</strong>
<%= #product.store.try(:name) %>
</p>
<p>
<strong>Image:</strong>
<%= #product.imageurl %>
</p>
<p>
<strong>Url:</strong>
<%= #product.url %>
</p>
<p>
<strong>Price:</strong>
$<%= #product.price %>
</p>
<%= params.inspect %>
<%= link_to 'Edit', edit_product_path(#product) %> |
<%= link_to 'Back', products_path %>
You'll notice that I have .try in place where I'm referencing product.store.name from product.store so that I stop getting the error listed in the subject of this post.
When I look up the product I'm viewing using the console I see that Store_id: 2
When I look up the store with id of 2 I see that Store_id: 1 - so there is a value present there.
I printed params on the show view and only get this: {"action"=>"show", "controller"=>"products", "id"=>"2"}.
Can anyone find what I'm missing in this whole set up to get product.store.name to display in my product views? Let me know if I can provide more info!
First, you should be using snake_case for attributes. UpperCamelCase is reserved for constant names in Ruby, that includes things like classes and modules. Update your code to not use UpperCamelCase style naming for attributes (eg. ProdDesc, ProdImageUrl). Also it is unnecessary to use prefixes like Prod* for attributes.
So instead of
class Product < ActiveRecord::Base
belongs_to :store
validates_presence_of :ProdTitle, :ProdUrl, :ProdPrice
end
Your class will look like this:
class Product < ActiveRecord::Base
belongs_to :store
validates_presence_of :title, :url, :price
end
You can read more about Ruby and Rails naming conventions here:
http://rubylearning.com/satishtalim/ruby_names.html
https://github.com/bbatsov/rails-style-guide
I suspect that this causes the problem. You will also need to rename columns in database and change your controller and view code to reflect the change. If you can, please start again with your application.
You have taken name for field In database which are non conventional. By default The active record looks for store_id field in product table . Field name in a table should be snake case .so now you have to explicitly tell in product model the foreign key for store model