DB Query in Ruby on Rails - mysql

I am trying to perform a database search in an application, however, I have been unable to get the search to work properly.
In the index page I have the option to search or display all items in the database, however the return all always seems to be called, instead of the search. If someone searches, I would like to only display the searched for item when the search is completed.
I am, however, running into some issues.
articles_controller.rb:
class ArticlesController < ApplicationController
def index
if params[:id]
fun = Article.find_by(title: params[:id].search)
else
#articles = Article.all
end
end
def show
#article = Article.find(params[:search])
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#article = Article.new(params.require(:article).permit(:title, :text))
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text)
end
end
article.rb:
class Article < ActiveRecord::Base
validates :title, presence: true,
length: { minimum: 5 }
def self.search(search)
if :search
Article.where('tite LIKE ?', "%#{search}%")
else
Article.all
end
end
end
index.html.erb:
<h1>Listing articles</h1>
<%= link_to 'New article', new_article_path %>
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th colspan="3"></th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<%= form_tag articles_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :title => nil %>
</p>
<% end %>
</table>
Backend DB:
Started GET "/articles?search=asdfa&commit=Search&utf8=%E2%9C%93" for ::1 at 2016-03-14 15:01:12 -0400
Processing by ArticlesController#index as HTML
Parameters: {"search"=>"asdfa", "commit"=>"Search", "utf8"=>"✓"}
Article Load (0.1ms) SELECT "articles".* FROM "articles"
Rendered articles/index.html.erb within layouts/application (1.4ms)
Completed 200 OK in 19ms (Views: 18.6ms | ActiveRecord: 0.1ms)
The latest error/incorrect call is:
Started GET "/assets/application.self-3b8dabdc891efe46b9a144b400ad69e37d7e5876bdc39dee783419a69d7ca819.js?body=1" for ::1 at 2016-03-14 15:39:25 -0400
Started GET "/articles?search=asdfa&commit=Search&utf8=%E2%9C%93" for ::1 at 2016-03-14 15:39:40 -0400
Processing by ArticlesController#index as HTML
Parameters: {"search"=>"asdfa", "commit"=>"Search", "utf8"=>"✓"}
Article Load (0.1ms) SELECT "articles".* FROM "articles"
Rendered articles/index.html.erb within layouts/application (1.3ms)
Completed 200 OK in 18ms (Views: 17.2ms | ActiveRecord: 0.1ms)
What exactly am I doing wrong? How can I fix/make this work?

You've defined search method in your model, but you are not using in it in your controller:
def index
#articles = Article.search params[:search]
end
In your model, you have some logic errors (symbol :search instead of search variable, tite instead of title ):
def self.search search
search.present? ? where('title LIKE ?', "%#{search}%") : all
end

In your controller you have:
def index
if params[:id]
fun = Article.find_by(title: params[:id].search)
else
#articles = Article.all
end
end
but you are definitely not passing any id to the controller via the form.
For example, you can change the condition to:
if params[:search]
and then find by:
Article.find_by(title: params[:search])

Related

Hello everyone, pass params of a link_to to the instance of a controller action and thus save in db

Good afternoon, I am trying to pass params from a link_to to the instance of a controller action and thus save that data in the database, but for some reason they do not pass. I appreciate some help, and good morning ..
This is the controller of reservas
def index
#reservas = Reserva.all
end
def show
#reserva = Reserva.find(params[:id])
end
def new
#reserva = Reserva.new
end
def create
end
def cupoClase
#clase = Clase.find(params[:id])
#reserva = #clase.reservas.new(params[:reserva])
#reserva.idUsuario = current_usuario.id
#reserva.clase_id = params[:id].to_i
#reserva.fecha = params[:fecha]
respond_to do |format|
if #reserva.save
format.html { redirect_to #reserva, notice: 'Clase reservada' }
format.json { render action: 'index', status: :created, location: #reserva }
else
format.html { render action: 'index' }
format.json { render json: #reserva.errors, status: :unprocessable_entity }
end
end
end
private
def reserva_params
params.require(:reserva).permit(:idUsuario, :clase_id, :fecha)
end
def set_reserva
#reserva = Reserva.find(params[:id])
end
end ```
This is the index html.erb, and has the link_to of the params
<% #clases.each do |clas| %>
<tr>
<td><%= clas.nombre %></td>
<td><%= clas.fecha %></td>
<td><%= clas.cupos %></td>
<td><%= link_to 'Reservar', {:controller => 'reservas', :action => 'cupoClase', :id => clas.id, :fecha => clas.fecha } %></td>
<% if can? :destroy, #clase %>
<td><%= link_to 'Eliminar', clase_path(clas), method: :delete, data: { confirm: "Eliminar?" } %></td> |
<% end %>
</tr>
<% end %>
This is the routes..
``` Rails.application.routes.draw do
devise_for :usuarios, :controllers => { registrations: 'registrations' }
root to: 'home#index'
resources :clases do
resources :reservas
end
get '/clases', to: 'clases#index'
get '/reservas/:fecha/:id', to: 'reservas#cupoClase'
end

How to fix extra data appearing in the ERB generated HTML

I am following ruby-on-rails instruction guide to creating a simple blog web application: https://guides.rubyonrails.org/getting_started.html#generating-a-controller
All my project files are pretty much the same as the ones in the guide.
app/views/articles/show.html.erb
<p>
<strong>Title:</strong>
<%= #article.title %>
</p>
<p>
<strong>Text:</strong>
<%= #article.text %>
</p>
<h2>Add a comment:</h2>
<%= render 'comments/form' %>
<h2>Comments (<%= #article.comments.count %>)</h2>
<%= render 'comment_section' %>
<%#= render #article.comments %>
<%= link_to 'Edit', edit_article_path(#article) %> |
<%= link_to 'Delete', article_path(#article),
method: :delete,
data: {confirm: 'Are you sure?'} %> |
<%= link_to 'Back', articles_path %>
app/views/comments/_form.html.erb
<%= form_with(model: [#article, #article.comments.build], local: true) do |form| %>
<p>
<%= form.label :commenter %><br>
<%= form.text_field :commenter %>
</p>
<p>
<%= form.label :body %><br>
<%= form.text_area :body %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
app/views/articles/_comment_section.html.erb
<% if #article.comments.count > 0 %>
<%= render #article.comments %>
<% else %>
<p>There are no comments yet!</p>
<% end %>
app/views/comments/_comment.html.erb
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<p>
<%= link_to 'Delete comment', [comment.article, comment],
method: :delete,
data: {confirm: 'Are you sure you want to delete this comment?'}
%>
A simple article with no comments works as expected:
However, when showing an article with some actual comments, an extra empty comment gets displayed at the end:
When I try to delete that comment I get the following error (11 in the path is the article_id):
Deleting other comments works fine.
Rest of the files that I think might be relevant:
app/config/routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
end
root 'welcome#index'
end
app/models/article.rb
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
validates :title, presence: true, length: {minimum: 5}
end
app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :article
end
app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
end
def new
#article = Article.new
end
def edit
#article = Article.find(params[:id])
end
def create
#article = Article.new(article_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
def update
#article = Article.find(params[:id])
if #article.update(article_params)
redirect_to #article
else
render 'edit'
end
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
private
def article_params
params.require(:article).permit(:title, :text)
end
end
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def create
#article = Article.find(params[:article_id])
#comment = #article.comments.create(comment_params)
redirect_to article_path(#article)
end
def destroy
#article = Article.find(params[:article_id])
#comment = #article.comments.find(params[:id])
#comment.destroy
redirect_to article_path(#article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
I'm using:
ruby 2.6.5p114
Rails 6.0.0
sqlite3 3.8.7.2
RubyMine 2019.2.3
I'm developing on Windows
The reason why this is happening is this line:
<%= form_with(model: [#article, #article.comments.build], local: true) do |form| %>
The part that says #article.comments.build is building an empty comment on the article. If there are no comments on the article and you were to print out #article.comments.count it would be zero. It does this because #article.comments.count runs a query, and since the blank comment isn't saved yet, it doesn't count it against the comments count.
As a side note, #article.comments.size would return 1, since in this case it returns the size of the relation with the blank comment. This is why you don't get a blank comment when the article has no comments.
However if you were to already have a comment and print out #article.comments.count, it would be 1 because now you have a saved comment in the database. This renders your comments out on the page now. The thing is that there is a blank comment inside of the #article.comments return value. This gets printed out to the screen, and since it doesn't have an id, the route for delete gets rendered like this /article/11/comments without a comment id. This route does not exist, so you get an error.
One possible way to fix this would be to change this line in your comment_section partial from this:
<%= render #article.comments %>
to this:
<%= render #article.comments.select { |comment| comment.persisted? %>
UPDATE:
I think that arieljuod's solution is even cleaner, to change this:
<%= form_with(model: [#article, #article.comments.build], local: true) do |form| %>
To this:
<%= form_with(model: [#article, Comment.new], local: true) do |form| %>
in your views/comments/_comment.html.erb
change
<%= link_to 'Delete comment', [comment.article, comment],
method: :delete,
data: {confirm: 'Are you sure you want to delete this comment?'} %>
to
<%= link_to 'Delete comment', comment_path(comment),
method: :delete,
data: {confirm: 'Are you sure you want to delete this comment?'} %>

update join table has_many through with additional checkboxes

if i dont find solution here i have no idea where i should looking for...
I know there is right, easy solution for it...but something i just dont understand.
I have 3 models...
Scheme.rb
class Scheme < ActiveRecord::Base
has_many :projects
has_many :custom_issue_field_definitions, through: :scheme_custom_issue_field_definitions
has_many :scheme_custom_issue_field_definitions
end
CustomIssueFieldDefinition.rb
class CustomIssueFieldDefinition < ActiveRecord::Base
has_many :schemes, through: :scheme_custom_issue_field_definitions
has_many :scheme_custom_issue_field_definitions
belongs_to :custom_issue_field
end
SchemeCustomIssueFieldDefinition.rb
class SchemeCustomIssueFieldDefinition < ActiveRecord::Base
belongs_to :scheme
belongs_to :custom_issue_field_definition
end
Join Model have 3 additional fields...with type: boolean.
I'd like to update scheme_custom_issue_field_definitions table. How controller and form should looks like?
Additional image:
Update:
In console i can update it like this:
a = Scheme.first
b = CustomIssueFieldDefinition.first
c = a.scheme_custom_issue_field_defintitions.find_or_create_by(custom_issue_field_definition: b)
c.update_attributes(visible: 1, reportable: 0, required: 0)
Next Update:
Now form looks like this (what is completely wrong):
<%= simple_form_for #scheme_new_custom_issue_field, url: configurations_scheme_path(#scheme), method: :put do |f| %>
<% #available_custom_issue_field_definitions.each do |custom_issue_field| %>
<tr>
<td><%= custom_issue_field.label %></td>
<td><%= f.input :visible, as: :boolean %></td>
<td><%= f.input :reportable, as: :boolean %></td>
<td><%= f.input :required, as: :boolean %></td>
</tr>
<% end %>
<%= f.button :submit, class: "btn btn-primary" %>
<% end %>
and schemes_controller
def update
#scheme = Scheme.find(params[:id])
#scheme_new_custom_issue_field = #scheme.scheme_custom_issue_field_definitions.
find_or_create_by(scheme_id: #scheme, custom_issue_field_definition_id: params[:custom_issue_field_definition_id])
if #scheme_new_custom_issue_field.update_attributes(scheme_custom_issue_field_definition_params)
flash[:success] = "Scheme has been successfully updated"
redirect_to :back
else
render :edit
end
end
Update Solution:
If you want to create new SchemCustomIssueFieldDefinition record in the console, I suggest this alternative:
a = Scheme.first
b = CustomIssueFieldDefinition.first
c = SchemeCustomIssueFieldDefinition.find_or_initialize_by(scheme: a, custom_issue_field_definition: b)
c.assign_attributes(visible: 1, reportable: 0, required: 0)
c.save
This will save you one less query than your current example code as this will not do have an UPDATE sql.
For your form:
<%= simple_form_for #scheme, method: :patch do |f| %>
<% #available_custom_issue_field_definitions.each do |custom_issue_field| %>
<tr>
<%= f.simple_fields_for :scheme_custom_issue_field_definitions, #scheme.scheme_custom_issue_field_definitions.find_or_initialize_by(custom_issue_field_definition: custom_issue_field) do |ff| %>
<%= ff.hidden_field :id %>
<%= ff.hidden_field :scheme_id, value: #scheme.id %>
<%= ff.hidden_field :custom_issue_field_definition_id, value: custom_issue_field.id %>
<td><%= custom_issue_field.label %></td>
<td><%= ff.input :visible, as: :boolean %></td>
<td><%= ff.input :reportable, as: :boolean %></td>
<td><%= ff.input :required, as: :boolean %></td>
<% end %>
</tr>
<% end %>
<%= f.button :submit, class: "btn btn-primary" %>
<% end %>
schemes_controller.rb:
class SchemesController < ApplicationController
# ...
def update
#scheme = Scheme.find(params[:id])
if #scheme.update(scheme_params)
flash[:success] = "Scheme has been successfully updated"
redirect_to :back
else
render :edit
end
end
# ...
private
def scheme_params
# update below if you need other scheme attributes to be updated
params.require(:scheme).permit(:id, scheme_custom_issue_field_definitions_attributes: [:id, :scheme_id, :custom_issue_field_definition_id, :visible, :reportable, :required])
end
end
scheme.rb
class Scheme < ActiveRecord::Base
# ...
accepts_nested_attributes_for :scheme_custom_issue_field_definitions_attributes
# ...
end

cant access edit path in rails

currently im accessing my join table directly. the reason im doing this is because i only want the staff to be able to adjust the status
im facing problem with
undefined method order_task_path' for #<#<Class:0x00000009bf62c0>:0x0000000a6d7c70>`
with parameter Parameters:
{"id"=>"1,1"}
i'm able to display the join table according to my need. the problem is when i try to display it in edit.
here is my ordertask controller
class OrdersTasksController < ApplicationController
before_action :set_status, only: [:show]
def index
#orders = Order.all
##status = OrderTask.includes(:task,:order).where(order_id: params[:id])
end
def edit
#status = OrderTask.find(params[:id])
end
def show
end
def update
respond_to do |format|
if #status.update(order_params)
format.html { redirect_to #status, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #status.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_status
#status = OrderTask.includes(:task).where(order_id: params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order_task,:order).permit(:id,:order_id,:status)
end
end
my show.html.erb
<p id="notice"><%= notice %></p>
<table class="table table-hover">
<tr>
<td><h4>Order Number : <%= #status.first.order.order_number %></h4>
</td>
</tr>
<tr>
<td>Task
</td>
<td>Status:
</td>
</tr>
<tr>
<% #status.each do |i| %>
<td><%= i.task.task_name %>
</td>
<td><%= i.status %>
</td>
<td><%= link_to 'Edit', edit_orders_task_path(i) %></td>
</tr>
<% end %>
</table>
<%= link_to 'Back', orders_tasks_path %>
my _form.html.erb
<%= form_for(#status) do |f| %>
<% if #status.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#status.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% #status.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<table class="table table-hover">
<tr>
<td><%= f.label "List of task" %>
</td>
<td><%= f.label "Status" %>
</td>
</tr>
<tr>
<td><%= f.task_id %>
</td>
<td><div class="dropdown">
<%= f.select(:status,['In progress', 'Completed'], {}, {class: "control"})%> </div>
</td>
</tr>
<tr>
<td>
</td>
<td><%= f.submit %>
</td>
</tr>
</table>
<% end %>
and my routes
resources :orders
resources :services
resources :tasks
resources :customers
resources :staffs
resources :orders_tasks
root 'staffs#index'
and lastly my ordertask model
class OrderTask < ActiveRecord::Base
self.primary_key = [:order_id,:task_id]
self.table_name = "Orders_tasks"
belongs_to :order
belongs_to :task
end
hope u guys can give suggestion or something to help me with this. thx in advance.
EDIT
here is my route.rb
C:\Users\Idea\DHMS>rake routes
Prefix Verb URI Pattern Controller#Action
orders GET /orders(.:format) orders#index
POST /orders(.:format) orders#create
new_order GET /orders/new(.:format) orders#new
edit_order GET /orders/:id/edit(.:format) orders#edit
order GET /orders/:id(.:format) orders#show
PATCH /orders/:id(.:format) orders#update
PUT /orders/:id(.:format) orders#update
DELETE /orders/:id(.:format) orders#destroy
services GET /services(.:format) services#index
POST /services(.:format) services#create
new_service GET /services/new(.:format) services#new
edit_service GET /services/:id/edit(.:format) services#edit
service GET /services/:id(.:format) services#show
PATCH /services/:id(.:format) services#update
PUT /services/:id(.:format) services#update
DELETE /services/:id(.:format) services#destroy
tasks GET /tasks(.:format) tasks#index
POST /tasks(.:format) tasks#create
new_task GET /tasks/new(.:format) tasks#new
edit_task GET /tasks/:id/edit(.:format) tasks#edit
task GET /tasks/:id(.:format) tasks#show
PATCH /tasks/:id(.:format) tasks#update
PUT /tasks/:id(.:format) tasks#update
DELETE /tasks/:id(.:format) tasks#destroy
customers GET /customers(.:format) customers#index
POST /customers(.:format) customers#create
new_customer GET /customers/new(.:format) customers#new
edit_customer GET /customers/:id/edit(.:format) customers#edit
customer GET /customers/:id(.:format) customers#show
PATCH /customers/:id(.:format) customers#update
PUT /customers/:id(.:format) customers#update
DELETE /customers/:id(.:format) customers#destroy
staffs GET /staffs(.:format) staffs#index
POST /staffs(.:format) staffs#create
new_staff GET /staffs/new(.:format) staffs#new
edit_staff GET /staffs/:id/edit(.:format) staffs#edit
staff GET /staffs/:id(.:format) staffs#show
PATCH /staffs/:id(.:format) staffs#update
PUT /staffs/:id(.:format) staffs#update
DELETE /staffs/:id(.:format) staffs#destroy
orders_tasks GET /orders_tasks(.:format) orders_tasks#index
POST /orders_tasks(.:format) orders_tasks#create
new_orders_task GET /orders_tasks/new(.:format) orders_tasks#new
edit_orders_task GET /orders_tasks/:id/edit(.:format) orders_tasks#edit
orders_task GET /orders_tasks/:id(.:format) orders_tasks#show
PATCH /orders_tasks/:id(.:format) orders_tasks#update
PUT /orders_tasks/:id(.:format) orders_tasks#update
DELETE /orders_tasks/:id(.:format) orders_tasks#destroy
root GET / staffs#index
According to the error message undefined method order_task_path' for #<#<Class:0x00000009bf62c0>:0x0000000a6d7c70>, the url helper method does not exist.
you can rake rake routes in the terminal to get all the routes and route helpers.
resources :orders do
resources :tasks
end
generate the following routes and helpers.
order_tasks GET /orders/:order_id/tasks(.:format) tasks#index
POST /orders/:order_id/tasks(.:format) tasks#create
new_order_task GET /orders/:order_id/tasks/new(.:format) tasks#new
edit_order_task GET /orders/:order_id/tasks/:id/edit(.:format) tasks#edit
order_task GET /orders/:order_id/tasks/:id(.:format) tasks#show
PATCH /orders/:order_id/tasks/:id(.:format) tasks#update
PUT /orders/:order_id/tasks/:id(.:format) tasks#update
DELETE /orders/:order_id/tasks/:id(.:format) tasks#destroy
resources :orders do
resources :orders_tasks
end
generate the following routes and helpers.
order_orders_tasks GET /orders/:order_id/orders_tasks(.:format) orders_tasks#index
POST /orders/:order_id/orders_tasks(.:format) orders_tasks#create
new_order_orders_task GET /orders/:order_id/orders_tasks/new(.:format) orders_tasks#new
edit_order_orders_task GET /orders/:order_id/orders_tasks/:id/edit(.:format) orders_tasks#edit
order_orders_task GET /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#show
PATCH /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#update
PUT /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#update
DELETE /orders/:order_id/orders_tasks/:id(.:format) orders_tasks#destroy
http://guides.rubyonrails.org/routing.html#nested-resources

Ruby on Rails save a record on database based on post data

I've been playing around with this for the past 6 hours and I really can't solve it. I'm new to ruby on rails. I have a products and I have added a purchases model. now I want a 'buy' key next to each product to add it to my purchases database. This is my Purchases controller:
class PurchasesController < ApplicationController
def new
end
def update
end
def create
#purchase = Purchase.new(purchase_params)
if Purchase.save
redirect_to products_path notice: 'Product bough'
else
redirect_to products_path notice: 'Error!!!'
end
end
private
def purchase_params
params.require(:product).permit(:amount,:product_id)
end
And the buy button:
<td><%= link_to 'Buy',purchases_path(product.attributes), method: :post %></td>
And that's within <% #products.each do |product %>. Now I really wanna know how to send product_id and then save it in my purchases database. I keep getting all sorts of errors!
Like parameter not found: product to undefined methodpermit' for "8":String8 is the product id andmethod save is undefined ...`. I think I really don't know what I'm doing here! A little help or tutorial on how to manually save data to database will be appreciated. (by manually I mean entering which posted field to saved for which col)
You should do #purchase.save, not Purchase.save
Something like this should be your view.
<% #products.each do |product| %>
<td><%= product.amount %><td>
<td><%= form_for #product, url: {action: "create"}, html: {method: "post"} do |f| %>
<%= f.hidden_field_tag :id,product.id%>
<%= f.hidden_field_tag :amount,product.amount%>
<%= f.submit "Create" %>
<% end %></td>
<% end %>
Your controller should look something like this:
def create
#purchase = Purchase.new(purchase_params)
if #purchase.save
redirect_to products_path notice: 'Product bough'
else
redirect_to products_path notice: 'Error!!!'
end
end
def purchase_params
params.require(:product).permit(:amount,:id)
end
I am not sure why you want to not use the form. Why is that? Anyway here is a solution.
<td><%= link_to 'Buy',purchases_path(amount: product.amount,id: product.id), method: :post %></td>
This should work. Try this.