I want to create an object with random sequence generated through the follow method. But after clicking the "Generate" button, it creates 2 objects (1 with all attributes null and the other 1 with the value I entered). Can someone tell me where's the problem?
CONTROLLER :
class GeneratorsController < ApplicationController
before_action :set_generator, only: [:show, :edit, :update, :destroy]
after_action :random_generate, only: [:create, :new, :edit]
# GET /generators
# GET /generators.json
def index
#generators = Generator.all
end
# GET /generators/1
# GET /generators/1.json
def show
end
# GET /generators/new
def new
#generator = Generator.new
end
# GET /generators/1/edit
def edit
end
# POST /generators
# POST /generators.json
def create
#generator = Generator.new(generator_params)
respond_to do |format|
if #generator.save
format.html { redirect_to #generator, notice: 'Generator was successfully created.' }
format.json { render action: 'show', status: :created, location: #generator }
else
format.html { render action: 'new' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /generators/1
# PATCH/PUT /generators/1.json
def update
respond_to do |format|
if #generator.update(generator_params)
format.html { redirect_to #generator, notice: 'Generator was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# DELETE /generators/1
# DELETE /generators/1.json
def destroy
#generator.destroy
respond_to do |format|
format.html { redirect_to generators_url }
format.json { head :no_content }
end
end
def random_generate
if #generator.choice == 'Randomly'
length = #generator.primer_length
chars = 'ATGC'
seq = ''
length.times { seq << chars[rand(chars.size)] }
#generator.random_primer_generated = seq
end
#generator.save!
end
private
# Use callbacks to share common setup or constraints between actions.
def set_generator
#generator = Generator.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def generator_params
params.require(:generator).permit(:primer_length, :choice, :random_primer_generated)
end
end
VIEW :
<%= form_for (#generator ) do |f| %>
<% if #generator.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#generator.errors.count, "error") %> prohibited this generator from being saved:</h2>
<ul>
<% #generator.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<label>Primer Length</label><br>
<%= f.number_field :primer_length %>
</div>
<label>Selection :</label><br>
<label>Randomly</label>
<%= radio_button_tag(:choice, 'Randomly')%>
<%= button_to('Generate', random_generate_generator_path(#generator))%>
<% end %>
You have an after_action callback which triggers the random_generate action every time you display the new view. That's where your empty object comes from. You shouldn't need this after_action callback on new.
Related
sorry for this question but I'm struggling with this issue for hours now and can't find the answer anywhere.
Here is the thing, I have a rails app with "Reservation" and "Space" models with the following relations:
class Reservation < ActiveRecord::Base
belongs_to :space
belongs_to :user
end
class Space < ActiveRecord::Base
belongs_to :condo
has_many :reservations
end
When the user creates a new Reservation, in the form he gets to choose from a dropdown (f.select) the spaces available for him. The f.select in the form look like this:
<div class="field">
<%= #user_spaces = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user_spaces, :id, :name), :prompt => "Select space"
%>
</div>
That select it supose to assign a value to the key "space_id" in the Reservation that is being created (column's table is created). But when I check the last reservation in Rails console, space_id value is "nil". What am I doing wrong?
Thank you very much for your help
Reservation controller file:
class ReservationsController < ApplicationController
before_action :set_reservation, only: [:show, :edit, :update, :destroy]
# GET /reservations
# GET /reservations.json
def index
#reservations = Reservation.all
end
# GET /reservations/1
# GET /reservations/1.json
def show
end
# GET /reservations/new
def new
#reservation = Reservation.new
end
# GET /reservations/1/edit
def edit
end
# POST /reservations
# POST /reservations.json
def create
#reservation = Reservation.new(reservation_params)
#user = current_user.id
#reservation.user_id = #user
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :new }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reservations/1
# PATCH/PUT /reservations/1.json
def update
respond_to do |format|
if #reservation.update(reservation_params)
format.html { redirect_to #reservation, notice: 'Reservation was successfully updated.' }
format.json { render :show, status: :ok, location: #reservation }
else
format.html { render :edit }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reservations/1
# DELETE /reservations/1.json
def destroy
#reservation.destroy
respond_to do |format|
format.html { redirect_to reservations_url, notice: 'Reservation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reservation
#reservation = Reservation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:eventdate)
end
end
Space controller file:
class SpacesController < ApplicationController
before_action :set_space, only: [:show, :edit, :update, :destroy]
# GET /spaces
# GET /spaces.json
def index
#spaces = Space.all
end
# GET /spaces/1
# GET /spaces/1.json
def show
end
# GET /spaces/new
def new
#space = Space.new
end
# GET /spaces/1/edit
def edit
end
# POST /spaces
# POST /spaces.json
def create
#space = Space.new(space_params)
respond_to do |format|
if #space.save
format.html { redirect_to #space, notice: 'Space was successfully created.' }
format.json { render :show, status: :created, location: #space }
else
format.html { render :new }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /spaces/1
# PATCH/PUT /spaces/1.json
def update
respond_to do |format|
if #space.update(space_params)
format.html { redirect_to #space, notice: 'Space was successfully updated.' }
format.json { render :show, status: :ok, location: #space }
else
format.html { render :edit }
format.json { render json: #space.errors, status: :unprocessable_entity }
end
end
end
# DELETE /spaces/1
# DELETE /spaces/1.json
def destroy
#space.destroy
respond_to do |format|
format.html { redirect_to spaces_url, notice: 'Space was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_space
#space = Space.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def space_params
params.require(:space).permit(:name)
end
end
And full Reservation Form:
<%= form_for(#reservation) do |f| %>
<% if #reservation.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reservation.errors.count, "error") %> prohibited this reservation from being saved:</h2>
<ul>
<% #reservation.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :eventdate %><br>
<%= f.date_select :eventdate %>
</div>
<div class="field">
<%= #user = current_user.condo.spaces
f.select :space_id,
options_from_collection_for_select(#user, :id, :name), :prompt => "Select space"
%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
pretty sure you need to permit the space_id attribute in your strong params.
def reservation_params
params.require(:reservation).permit(:eventdate, :space_id)
end
whats happening is that when you go to create a reservation, youre passing in set of params, that is the output of reservation_params
#reservation = Reservation.new(reservation_params)
if space_id is not being permitted in your strong params, then it will be nil when created.
if this is not the issue, can you post what params are getting to the server, and what the output of reservation_params are.
I'm trying to be on that page right before the checkout, where you can modify the quantity and update all the prices accordingly. Now my "Update" button, updates 'something' but it's not what i'm trying to achieve, it sends me on a line_items show page that i don't even want to have (i'm keeping it for now to avoid the missing template error). The rails documentation isn't helping me ... well anyway, the code is this
<ul>
<% #cart.line_items.each do |item| %>
<%= form_for(item) do |f| %>
<li><%= f.number_field :quantity, :value => item.quantity %> x <%= item.product.name %>
<%= item.total_price %> </li>
<% end %>
<%= submit_tag "Update" %>
<% end %>
<br><strong>Total Price:</strong> <%= #cart.total_price %>
</ul>
<%= button_to "Checkout", new_order_path, method: :get, data: { confirm: "Are you sure?" } %>
<%= button_to 'Empty cart', #cart, method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to 'Back', categories_path %>
Thank you !
edited
class LineItemsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:create, :update, :destroy]
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
# GET /line_items
# GET /line_items.json
def index
#line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show
end
# GET /line_items/new
def new
#line_item = LineItem.new
end
# GET /line_items/1/edit
def edit
end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
#line_item = #cart.add_product(product.id)
respond_to do |format|
if #line_item.save
format.html { redirect_to #line_item.cart, notice: 'Line item was successfully created.' }
format.json { render :show, status: :created, location: #line_item }
else
format.html { render :new }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
respond_to do |format|
if #line_item.update(line_item_params)
format.html { redirect_to #cart, notice: 'Line item was successfully updated.' }
format.json { render :show, status: :ok, location: #line_item }
else
format.html { render :edit }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
#line_item.destroy
respond_to do |format|
format.html { redirect_to line_items_url, notice: 'Line item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
#line_item = LineItem.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_item_params
params.require(:line_item).permit(:product_id, :cart_id, :order_id)
end
end
Just do redirect after you update an item. And provide correct line_item_update_params method that permites quantity param. Your controller should look like that:
class ItemsController < ApplicationController
def update
item = Item.find(params[:id])
item.update(line_item_update_params)
redirect_to :back # this is the key line of code
end
...
private
# it is used for creating
def line_item_params
params.require(:line_item).permit(:product_id, :cart_id, :order_id)
end
# it is used for updating
def line_item_update_params
params.require(:line_item).permit(:quantity)
end
...
end
I have a Result that belongs to a Website. After I create the website I also create the result and redirect to its edit page. Here I want to add some more values.
My problem is: When I try to update my Result, then I get:
param is missing or the value is empty: result
Request
Parameters:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"GRN/y/04Qbsm9DzlUAbUYF8ZSv2EMHnRZgBZY/6GMDlOBdq8V5Uncij9VRp51uydC6M/qc61jPWwpUehSuc5xA==", "data"=>["//html/body/div[position() = 3]/ul/li[position() = 16]/ul/li[position() = 2]/child::text()", "//html/body/div[position()
= 3]/ul/li[position() = 16]/ul/li[position() = 2]/p/a/child::text()", "//html/body/div[position() = 3]/ul/li[position() = 16]/ul/li[position() = 4]/child::text()", "//html/body/div[position()
= 3]/ul/li[position() = 16]/ul/li[position() = 5]/a/child::text()"], "commit"=>"Update Result", "id"=>"66"}
This is how my Result params looks like
def result_params
params.require(:result).permit(:data)
end
My model:
class Result < ActiveRecord::Base
belongs_to :website
attr_accessor :website_id
attr_accessor :data
serialize :data, Array
end
Here is my controller code:
class ResultsController < ApplicationController
before_action :set_result, only: [:show, :edit, :update, :destroy]
# GET /Results
# GET /Results.json
def index
#results = Result.all
end
# GET /Results/1
# GET /Results/1.json
def show
end
# GET /Results/new
def new
#result = Result.new
end
# GET /Results/1/edit
def edit
#result = Result.find(params[:id])
end
# POST /Results
# POST /Results.json
def create
#result = Result.new(result_params)
respond_to do |format|
if #result.save
format.html { redirect_to #result, notice: 'Result was successfully created.' }
format.json { render :show, status: :created, location: result }
else
format.html { render :new }
format.json { render json: #result.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Results/1
# PATCH/PUT /Results/1.json
def update
respond_to do |format|
if #result.update(result_params )
format.html { redirect_to #result, notice: 'Result was successfully updated.' }
format.json { render :show, status: :ok, location: #result }
else
format.html { render :edit }
format.json { render json: #result.errors, status: :unprocessable_entity }
end
end
end
# DELETE /Results/1
# DELETE /Results/1.json
def destroy
#result.destroy
respond_to do |format|
format.html { redirect_to results_url, notice: 'Result was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_result
#result = Result.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def result_params
params.permit(:data => [])
end
end
My view:
<%= form_for(#result) do |f| %>
<% if #result.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#result.errors.count, "error") %> prohibited this result from being saved:</h2>
<ul>
<% #result.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<% if #result.website.url != nil %>
<%= atts = get_all_elements(#result.website.url)%>
<% atts.each do |p| %>
<div>
<%= check_box_tag "data[]", get_xpath_from_node(p)%>
<%= p.text %>
</div>
<%end%>
<% end%>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And this is the place where i call the edit result page:
def update
respond_to do |format|
if #website.update(website_params)
format.html { redirect_to #website, notice: 'Website was successfully updated.' }
format.json { render :show, status: :ok, location: #website }
else
format.html { render :edit }
format.json { render json: #website.errors, status: :unprocessable_entity }
end
end
end
Ive allready tryed every solution I could find, but none of them seemed to work for me.
The problem lies here:
params.require(:result).permit(:data)
From require documentation,
require ensures that a parameter is present. If it's present, returns
the parameter at the given key, otherwise raises an
ActionController::ParameterMissing error.
You are requiring result parameter but it's missing from the params. All your values are inside data param. Removing require should do the trick.
params.permit(:data)
If you want to keep require, wrap data inside result in forms.
I know, what you met. if you strong params is
def result_params
params.require(:result).permit(:data)
end
Your parameters should has the format like this
Parameters: {"result"=>{"data"=>"string"}}
and your parameters is just
Parameters: {"data"=>"string"}
so you should remove the "result"
I have nested resources - users have_many manufacturers and manufacturers have_many lines. I wrote a before_filter to load the #manufacturer so it could go through the rest of the functions in the lines_controller. Problem is, I'm running into issues when I click edit on the lines/show view.
Error: Couldn't find Manufacturer with id=manufacturer_id
77 def load_manufacturer
78 #manufacturer = Manufacturer.find(params[:manufacturer_id])
79 end
So here's what I'm working with:
app/views/lines/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #line.name %>
</p>
<p>
<strong>Manufacturer:</strong>
<%= #line.manufacturer_id %>
</p>
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %> |
<%= link_to 'Back', manufacturer_lines_path(#line.manufacturer_id) %>
lines_controller.rb
class LinesController < ApplicationController
before_action :set_line, only: [:show, :edit, :update, :destroy]
before_filter :load_manufacturer
# GET /lines
# GET /lines.json
def index
#lines = Line.all
end
# GET /lines/1
# GET /lines/1.json
def show
end
# GET /lines/new
def new
#manufacturer = Manufacturer.find(params[:manufacturer_id])
#line = #manufacturer.lines.build
end
# GET /lines/1/edit
def edit
end
# POST /lines
# POST /lines.json
def create
#line = #manufacturer.lines.build(line_params)
respond_to do |format|
if #line.save
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully created.' }
format.json { render action: 'show', status: :created, location: #line }
else
format.html { render action: 'new' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /lines/1
# PATCH/PUT /lines/1.json
def update
respond_to do |format|
if #line.update(line_params)
format.html { redirect_to manufacturer_line_path(#manufacturer, #line), notice: 'Line was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #line.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lines/1
# DELETE /lines/1.json
def destroy
#line.destroy
respond_to do |format|
format.html { redirect_to manufacturer_lines_url(#manufacturer) }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line
#line = Line.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_params
params.require(:line).permit(:name, :manufacturer_id)
end
def load_manufacturer
#manufacturer = Manufacturer.find(params[:manufacturer_id])
end
end
This:
<%= link_to 'Edit', edit_manufacturer_line_path(:manufacturer_id,#line) %>
Should be
<%= link_to 'Edit', edit_manufacturer_line_path(#manufacturer,#line) %>
What is happening is it is changing the symbol :manufacturer_id to a string and passing it to the route so your route looks like
`/manufacturers/manufacturer_id/lines/###/edit`
when you want
/manufacturers/###/lines/###/edit
This is my controller. def random_generate is not giving me any output, and when I create the object, length is there but random_primer_generated is empty. Can someone help me?
class GeneratorsController < ApplicationController
before_action :set_generator, only: [:show, :edit, :update, :destroy]
helper_method :random_generate
# GET /generators
# GET /generators.json
def index
#generators = Generator.all
end
# GET /generators/1
# GET /generators/1.json
def show
end
# GET /generators/new
def new
#generator = Generator.new
end
# GET /generators/1/edit
def edit
end
# POST /generators
# POST /generators.json
def create
#generator = Generator.new(generator_params)
respond_to do |format|
if #generator.save
format.html { redirect_to #generator, notice: 'Generator was successfully created.' }
format.json { render action: 'show', status: :created, location: #generator }
else
format.html { render action: 'new' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /generators/1
# PATCH/PUT /generators/1.json
def update
respond_to do |format|
if #generator.update(generator_params)
format.html { redirect_to #generator, notice: 'Generator was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #generator.errors, status: :unprocessable_entity }
end
end
end
# DELETE /generators/1
# DELETE /generators/1.json
def destroy
#generator.destroy
respond_to do |format|
format.html { redirect_to generators_url }
format.json { head :no_content }
end
end
def random_generate
if #generator.choice == 'Randomly'
length = #generator.primer_length
chars = 'atgc'
seq = ''
#length = length.to_i
length.times { seq << chars[rand(chars.size)] }
#generator.random_primer_generated = seq
end
return #generator.random_primer_generated
end
private
# Use callbacks to share common setup or constraints between actions.
def set_generator
#generator = Generator.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def generator_params
params.require(:generator).permit(:primer_length, :choice_random_primer_generated)
end
end
This is my Form_VIEW (to get the user's data - length and choice):
<%= form_for (#generator ) do |f| %>
<% if #generator.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#generator.errors.count, "error") %> prohibited this generator from being saved:</h2>
<ul>
<% #generator.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<label>Primer Length</label><br>
<%= f.number_field :primer_length %>
</div>
<label>Selection :</label><br>
<label>Randomly</label>
<%= radio_button_tag(:choice_random_primer_generated, 'Randomly')%>
<%= button_to('Generate', random_generate_generator_path(#generator))%>
<% end %>
Note: the form may be a red herring here. If you only want the code to be randomly generated when the user explicitly clicks that button, and NOT after every create or save, then you don't want any callbacks. You're doing it the right way. The only thing you are missing is the save call at the end of your method, and you'll also want to redirect the user back to a page.
However, if you DO want generate to happen after EVERY create or update, then you should probably change that button_to call to f.submit, and move that random_generate code to your model. Then, you can use rails callback for after_save and call that method from there within your controller.
More info:
http://guides.rubyonrails.org/active_record_callbacks.html
You are not calling your helper_method anywhere. When you post the form and it reaches the server, the create method is called. The helper_method is not triggered, therefore you are not creating a random number.
I didn't understand it very well, but what are you trying to randomize? Why don't you simply use a rand(999) to randomize numbers for example?
It looks like you want to call random_generate after your new and create action, but you are not calling it. All you have to do is change helper_method :random_generate to after_action :random_generate, only: [:create, :new]
You also want to make sure to save your new record in random_generate. You don't need the return #genator.random_primer_generated. See below:
def random_generate
if #generator.choice == 'Randomly'
length = #generator.primer_length
chars = 'atgc'
seq = ''
#length = length.to_i
length.times { seq << chars[rand(chars.size)] }
#generator.random_primer_generated = seq
end
#generator.save!
end