Edit user input from form_for - ruby-on-rails

Currently i'm using form_for read read a text_field called :comment, after the user submit it goes to the controller as such:
def create
#entry = Entry.new(entry_params)
if #entry.save
redirect_to :back
else
render 'new'
end
end
private
def entry_params
params.require(:entry).permit(:comment)
end
my question is whether I can search inside :comment (string) for a substring "test", when submitting?
Thanks

You can access what was submitted in the comment text field with params[:entry][:comment], so you should be able to compare it to the value you want with params[:entry][:comment].include?("test")

Related

Offer options if record already exists in Ruby on Rails

I'm creating a database of products and want to check when a new product is created, if that product already exists.
99% of the time, the product should have a unique product code, but sometimes this will not be the case when a revised version comes out with the same product code.
I would like to have it so that the database checks if the product code exists already. If it does, then the user can either go ahead and create the product anyway, go to the product that already exists, or cancel.
I am trying to achieve this in the controller but cannot seem to get the syntax of the exists? method correct. Can someone point out where I am going wrong, please?
def create
#product = Product.new(product_params)
if Product.product_code.exists?(#product.product_code)
render 'new'
flash[:error] = "This product already exists."
elsif #product.save
redirect_to #product
else
render 'new'
end
end
You should note that what you are doing in the controller or adding a standard uniqueness validation to the model will not allow duplicate Products to be created at all.
This will just keep sending the user back to the form:
def create
#product = Product.new(product_params)
if Product.exists?(product_code: #product.product_code)
render 'new'
flash[:error] = "This product already exists."
elsif #product.save
redirect_to #product
else
render 'new'
end
end
If you want to simply warn the user once you can attach a virtual attribute on the model and use it as condition for the validation:
class Product < ApplicationRecord
attribute :dup_warning, :boolean, default: true
validate :lax_product_code_uniquenes
def lax_product_code_uniqueness
if new_record? && !dup_warning && Product.exists(product_code: self.product_code)
errors.add(:product_code, 'is not unique - are you sure?')
self.dup_warning = true
end
end
end
Then add the virtual attribute to the form:
<%= form_with(model: #product) do |f| %>
...
<%= f.hidden_input(:dup_warning) %>
...
<% end %>
And you don't need to really do anything in the controller besides add dup_warning to the params whitelist.
def create
#product = Product.new(product_params)
if #product.save
redirect_to #product
else
render 'new'
end
end
def product_params
params.require(:product)
.permit(:foo, :bar, :product_code, :dup_warning)
end
Instead if Product.product_code.exists?(#product.product_code) possibly you should use if #product.product_code.present?
UPD: thanks to all, commented below.
Correct use of exists? is Product.where(product_code: #product.product_code).exists?

Form failing to save one attribute

I have a form that is saving all but one attribute. :user_id (a foreign key) persists in coming out as nil. This is a form for creating a new comment, and it's located in my impressions#show file, so that may be part of the problem; but the other attributes (:name and :impression_id) seem to be saving fine.
Here's the form:
= form_for #comment do |f|
= f.label 'Add Comment'
%br
= f.text_area :body, placeholder: 'Comment', cols: 50, rows: 3
%br
= f.hidden_field :impression_id, :value => #impression.id
= f.hidden_field :user_id, :value => current_user.id
%br
= f.submit "Save"
The relevant section of the impressions_controller is:
def show
#impression = Impression.find(params[:id])
#play = Play.find_by(id: #impression.production.play_id)
#production = Production.find_by(id: #impression.production_id)
#comments = Comment.where(impression_id: #impression.id)
#comment = Comment.new
end
In the comments_controller, I have the following:
def new
#impression = Impression.find(params[:impression_id])
#comment = Comment.new(comment_params)
authorize #comment
end
def create
#comment = Comment.new(comment_params)
authorize #comment
if #comment.save
flash[:notice] = 'You have successfully added a comment.'
redirect_to :back
else
flash[:notice] = 'Please try again.'
render :new
end
end
private
def comment_params
params.require(:comment).permit(:body, :impression_id, :user_id)
end
As you can see, I'm trying to assign :user_id the value of current_user.id, but it isn't taking. Can anyone see what I'm missing?
I've tried adding comment_params to my impressions controller, but I get an error message that the param comment is empty . . .
Thanks!
First check current_user if the value of current_user is coming fine then it has to save user_id in your comments table.
If your user is not logged in, current_user is nil.
Make sure that your user is logged in
To answer your question...
Maybe your hidden field is not sending user_id inside the comments subhash. Check your params and see. Your comment_params method expects it to be inside the comments subhash.
And how do you check these params?
Either look at your rails console after each form submission, or
if you are using rails 4.2, check https://gorails.com/episodes/rails-4-2-introduction about 4 minutes in...,
or...
in your gemfile, put
group :development do
gem 'better_errors'
gem 'binding_of_caller'
end
bundle (in your terminal), restart your rails server
and then in your controller code, at a line where current_user SHOULD exist, type the line raise "oops", run the code, get an error, then go to http://localhost:3000/__better_errors to see your console
This will give you an error page with a console, in which you can type out any variable name (params, current_user, whatever) and check its value.

Trying to pass parameters

I'm trying to pass URL params into my Rails app (Ex: /entries/new?name=asdf
Controller:
def new
#entry = Entry.new(params[:name])
end
def create
#entry = Entry.new(params[:name])
if #entry.save
redirect_to #entry, notice: 'Entry was successfully created.'
else
render :new
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_entry
#entry = Entry.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def entry_params
params.require(:entry).permit(:name)
end end
Form field :
<%= hidden_field_tag :name, params[:name] %>
I'm getting the error "When assigning attributes, you must pass a hash as an argument."
Any ideas?
params is a Hash. params[:name] will return a string ('asdf' in your example above). When instantiating Entry you're only passing the string when you should be passing a hash. Assuming that name is an attribute on your Entry model, you'll need to do this
#entry = Entry.new(name: params[:name])
Use rails generate scaffold Entry and take a look to the generated code. What you're trying to do don't have much sense

Could find Addict without an ID

I'm trying to put a new form that creates new "Addicts" in a modal in my home page.
It's a simple form with 2 inputs, that when clicking on New, a modal pops up with that form in my index page.
I can't get it to work because it keeps saying "Couldnt find Addict without an ID".
My Pages Controller
class PagesController < ApplicationController
def home
#addict = Addict.find(params[:id])
#lanzaderas = Lanzadera.all
render 'index'
end
end
My Addict Controller
class AddictsController < ApplicationController
def index
#posts = Addict.all
end
def show
#addict = Addict.find(params[:id])
end
def new
#addict = Addict.new(params[:addict])
end
def create
#addict = Addict.new(params[:addict])
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end
def edit
end
def update
end
def destroy
end
end
end
My form in my modal
<%= form_for #addict do |f| %>
<%= f.input :name %>
<%= f.input :surname %>
<%= f.input :postal %>
<%= f.submit %>
<% end %>
I know it has something to do with the variable / id not being passed correctly in my Controller, but it's an error I get lots of times and don't know why I happens.
Thanks!
In def home in your PagesController you have this code:
#addict = Addict.find(params[:id])
I suspect, that you don't have the id for 'addict' in your parameters, when you visit your home action.
Do you want to display one particular addict in your 'home' page? If not, you can remove this line.
Update:
Change this in your AddictsController:
def new
#addict = Addict.new
end
In the new action you only "prepare" a new addict object. Using the find method is not possible, since the record hasn't been created yet.
If you're using Rails 4 you also have to permit your parameters (for security reasons; more info here: Railsguides: Strong Parameters)
In your case you have to do 2 things:
First: add this at the bottom of your AddictsController:
private
def addict_params
params.require(:addict).permit(:name, :surname, :postal)
end
Second: use this method in your create action instead of params[:addict]:
def create
#addict = Addict.new(addict_params)
if #addict.save
redirect_to posts_path, :notice => "Your Addict was saved"
else
render "new"
end
end

Rails redirect to assoc model after create

I have a #miniatures model and a #lines model joined via a #minilines model.
In the #miniature show view I have this link
<%= link_to "Add to product line", new_miniline_path(:miniature_id => #miniature) %>
To a New #miniline form that takes the :miniature_id from a hidden field like so
<%= f.hidden_field :miniature_id, :value => #miniature.id %>
And then you select the desired #line from a dropdown.
This all works. What I can't get to work is for the controller to redirect a user back to the originating #miniature after the create action works.
This is what I have in my new and create actions in the controller
def new
#miniline = Miniline.new(#miniature)
#miniature = Miniature.find(params[:miniature_id])
#lines = Line.all
end
def create
#miniline = Miniline.new(miniline_params)
if #miniline.save
flash[:success] = "Miniature added to product line"
redirect_to miniature_path(#miniature)
else
flash[:success] = "Did not work!!!"
render 'new'
end
end
I've tried various alternatives to miniature_path(#miniature) like plain #miniature and miniature_path(:miniature_id) but to no avail. I suspect my problem is with the passing of the :miniature_id to the #minilines model. Any help very much appreciated as I've been banging my head for an hour or two.
redirect_to miniature_path(#miniline.miniature)
Assuming you have an association setup.
You haven't set #miniature in create which is that that doesn't work
You could also do
redirect_to #miniline.miniature

Resources