Hi I have the following code in my model:
class Product < ActiveRecord::Base
before_destroy :check_tasks
has_many :tasks, :order => 'created_at DESC'
validates :name, :presence => true
belongs_to :sprint
validates :sprint_id, :presence => true
def check_tasks
if self.tasks.any?
errors.add_to_base "Product has tasks and cannot be destroyed."
return false
end
end
end
When I am in the product view which lists all the products, I would like to display the error message on the top of the view, every time someone tries to delete a product which has tasks linked to it. I want the message: Product has tasks and cannot be destroyed displayed.
What code should I put in the view below? The view is the product view, which is in the views/products folder.
Thanks!!!
<h1>Listing products</h1>
<%= link_to 'New Product', new_product_path %>
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Sprint</th>
<th></th>
<th></th>
<th></th>
</tr>
<% if not #messages_rendered -%>
<% if flash[:error] -%>
<p class='error'><%=h flash[:error] %></p>
<% end -%>
<% if flash[:notice] -%>
<p class='notice'><%=h flash[:notice] %></p>
<% end -%>
<% end -%>
<% #messages_rendered = true -%>
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.description %></td>
<td><%= product.sprint.name %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
<td><%= link_to 'Destroy', product, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
Try putting this in your product_controller:
def destroy
...
flash[:error] = #product.errors.full_messages.join(' ')
...
end
Related
I have a web app that displays questions with options. The problem is for the options it is displaying whole object along with the body parameter of the object. I do not know what is happening here. Is it something related to serializing and deserializing?
index.html.erb
<tbody>
<% #questions.each do |question| %>
<tr>
<td><%= question.body %></td>
<td><%= question.user.email %></td>
<td>
<%= question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
</td>
<td><%= link_to 'Show', question %></td>
<% if current_user && current_user.admin %>
<td><%= link_to 'Edit', edit_question_path(question) %></td>
<td><%= link_to 'Destroy', question, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<tr>
</tr>
<% end %>
</tbody>
controller_params
private
def set_question
#question = Question.find(params[:id])
end
def question_params
params.require(:question).permit(:body, options_attributes: [:body])
end
model
class Question < ApplicationRecord
belongs_to :user
has_many :options, dependent: :delete_all, :autosave => true
validates_length_of :options, maximum: 4
accepts_nested_attributes_for :options
end
output
<%= question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
Your problem is with this block. Your first part of ERB is telling the view to render question.options.each as well as the followowing HTML, resulting in the objects themselves being rendered. Changing to:
<% question.options.each do |p| %>
<%= radio_button_tag('option',p.id) %>
<%= p.body %>
<% end %>
Will fix your issue.
I'm trying to update multiple records with one form:
Here's the code in the view:
<%= form_for :product, :url => admin_products_update_multiple_path, :html => { :method => :put } do %>
<table>
<tr>
<th>Supplier Name </th>
<th>Product Name </th>
<th>type_name</th>
<th>brand</th>
<th>image</th>
</tr>
<% #products.each do |product| %>
<%= fields_for "product[]", product do |product_fields| %>
<tr>
<td><%= product.supplier_name %> </td>
<td><%= product.subcategory_name %> </td>
<td><%= product_fields.text_field :type_name %></td>
<td><%= product_fields.text_field :brand %></td>
<td><%= product_fields.text_field :image %></td>
</tr>
<% end %>
<% end %>
</table>
<div class="actions">
<%= submit_tag %>
</div>
<% end %>
... and here's the controller action I'm calling to update:
def update_multiple
params['product'].keys.each do |id|
#product = Product.find(id.to_i)
#product.update_attributes(product_params)
end
flash[:notice] = "Update products successfully"
redirect_to(admin_products_path)
end
private
def product_params
params.require(:product).permit(:id, :type_name, :brand, :image)
end
When I run the method, I'm getting a 'Unpermitted parameters' error showing all the ids it's trying to update. Any ideas? Thanks in advance!
I'm making a to-do list with Rails. I want to have two checkboxes for every task ("Important" and "Urgent"). I want to sort those tasks according to two criteria.
First criteria are the checkboxes and the second criteria should be the time where the task has been created or updated. So with the first criteria there are 4 priorities which the tasks should be sorted:
Task (important and urgent checbox checked)
Task (important checkbox checked, urgent is not checked)
Task (urgent checkbox is checked, important is not checked)
Task (no checboxes are checked)
If there are multiple tasks with the same priority those should be sorted descending by the second criteria but within the first criteria.
I would create a migration to add an integer to the task model and then set the checkboxes to the values: "important = 2" and "urgent = 1" (unchecked value = 0). Those checkbox values should be summed up and linked to the integer in the task model and then I would sort them in the task view.
Questions:
How can I make checkboxes, set checkbox values and sum them up to one task model value?
How can I sort the tasks according to the summed up value?
How can I sort the tasks by the created/updated time as second criteria?
index.html.erb (task view)
<h1>To Do</h1>
<table>
<thead>
<th>Content</th>
<th>State</th>
<th></th>
<th></th>
<th></th>
<th></th>
</thead>
<tbody>
<% #to_do.each do |task| %>
<tr>
<td><%= task.content %></td>
<td><%= task.state %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task_path(task), method: :delete, data: { confirm: "Are you sure to delete this task?" } %></td>
<td><%= link_to 'Mark as Doing', change_task_path(task, state: "doing"), method: :put %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<h1>Doing</h1>
<table>
<thead>
<th>Content</th>
<th>State</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</thead>
<tbody>
<% #doing.each do |task| %>
<tr>
<td><%= task.content %></td>
<td><%= task.state %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task_path(task), method: :delete, data: { confirm: "Are you sure to delete this task?" } %></td>
<td><%= link_to 'Mark as To Do', change_task_path(task, state: "to_do"), method: :put %></td>
<td><%= link_to 'Mark as Done', change_task_path(task, state: "done"), method: :put %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<h1>Done</h1>
<table>
<thead>
<th>Content</th>
<th>State</th>
<th></th>
<th></th>
<th></th>
<th></th>
</thead>
<tbody>
<% #done.each do |task| %>
<tr>
<td><%= task.content %></td>
<td><%= task.state %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task_path(task), method: :delete, data: { confirm: "Are you sure to delete this task?" } %></td>
<td><%= link_to 'Mark as Doing', change_task_path(task, state: "doing"), method: :put %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Task', new_task_path %>
new.html.erb (task new view)
<h1>New Task</h1>
<%= form_for(#task) do |f| %>
<%= f.text_field :content, placeholder: "Content", class: "formfield" %>
<%= f.submit "Save Content", class: "form_button" %>
<% end %>
<%= link_to 'Back', tasks_path %>
tasks_controller.rb
class TasksController < ApplicationController
before_action :logged_in_user
before_action :set_task, only: [:show, :edit, :update, :destroy, :change]
def index
#to_do = current_user.tasks.where(state: "to_do")
#doing = current_user.tasks.where(state: "doing")
#done = current_user.tasks.where(state: "done")
end
def show
end
def new
#task = Task.new
end
def edit
end
def create
#task = current_user.tasks.new(task_params)
if #task.save
flash[:success] = "You successfully created a Task!"
redirect_to tasks_path
else
render 'new_task_path'
end
end
def update
#task.update(task_params)
if #task.save
flash[:success] = "You successfully updated a Task!"
redirect_to tasks_path
else
render 'edit_task_path'
end
end
def destroy
#task.destroy
flash[:success] = "You successfully deleted a Task!"
redirect_to tasks_path
end
def change
#task.update_attributes(state: params[:state])
flash[:success] = "You successfully changed the State!"
redirect_to tasks_path
end
private
def set_task
#task = Task.find(params[:id])
end
def task_params
params.require(:task).permit(:content, :state)
end
end
Solution by OP.
task.rb
class Task < ActiveRecord::Base
belongs_to :user
scope :important, -> { where(important: true) }
scope :urgent, -> { where(urgent: true) }
default_scope { order(:important => :desc, :urgent => :desc, :updated_at => :desc, :created_at => :desc) }
end
new.html.erb
<h1>New Task</h1>
<%= form_for(#task) do |f| %>
<%= f.text_field :content, placeholder: "Content", class: "formfield" %>
<strong>Important:</strong>
<%= f.check_box :important %>
<strong>Urgent:</strong>
<%= f.check_box :urgent %>
<%= f.submit "Save Content", class: "form_button" %>
<% end %>
<%= link_to 'Back', tasks_path %>
Q1: How can I make checkboxes, set checkbox values and sum them up to one task model value?
I don't think that summing the checkbox values to one 'task model value' is the best solution. I would add both an Urgent and an Important column to your Task model. This is far more scalable in the long run and easier to work with generally. Then it's just a case using the Rails check_box_tag helper. http://apidock.com/rails/ActionView/Helpers/FormTagHelper/check_box_tag
Q2: How can I sort the tasks according to the summed up value?
If you have separate columns/attributes for the important and urgent you can create scopes on your task model to sort as you wish.
scope :important, -> { where(important: true) }
scope :urgent, -> { where(urgent: true) }
You can then chain your named scopes as you require.
Task.important.urgent
or maybe you can also specify a recent scope:
scope :recent, -> { order("posts.updated_at DESC") }
and then call:
Task.important.recent
which would run the following SQL query:
# SELECT "tasks".* FROM "tasks" WHERE "tasks"."important" = 'true'
# ORDER BY tasks.updated_at DESC
Q3: How can I sort the tasks by the created/updated time as second criteria?
The above query sort of addresses this but you could also use:
Task.order(important: :asc, created_at: :desc)
Hope some of this is helpful.
I defined the next things:
task.rb:
class Task < ActiveRecord::Base
belongs_to :worker
attr_accessible :done, :name
end
worker.rb:
class Worker < ActiveRecord::Base
has_many :tasks
attr_accessible :name
end
I wrote the next code in "views/workers/index.html.erb":
<h1>Listing workers</h1>
<table>
<tr>
<th>Name</th>
<th>Task</th>
<th>Done</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #workers.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<td><%= tasks.select{ |task| task.done != 'yes' }.size %></td>
<td><%= link_to 'new Task', new_worker_task_path(name) %></td>
<td><%= link_to 'Show Tasks', worker_tasks_path(name) %></td>
</tr>
<% end %>
</table>
in order to use the link of: new_worker_task_path,
I defined in the task_controller:
def new
#worker = Worker.find(params[:worker_id])
#task = #worker.tasks.new
respond_with(#worker)
end
In addition, I defined: new.html.erb in the views/tasks, that also has: "Hi".
When I pressed the link of: "new task", I got:
Couldn't find Worker with id=alon
Rails.root: /home/alon/projects/TODO
Application Trace | Framework Trace | Full Trace
app/controllers/tasks_controller.rb:48:in `new'
Request
Parameters:
{"worker_id"=>"alon"}
first question: how can I find the worker who I want to add him a task?
second question: as I said, I defined:
<td><%= link_to 'new Task', new_worker_task_path(name) %></td>
why should I have to send the name? I use this value? I don't really understand why this parameter is necessary..
You have to send actual :param_key, which by default is ID.
So,
new_worker_task_path()
# have to receive worker's ID as argument. Or worker object, accepted too...
new_worker_task_path(#worker)
Updated for the 1st question:
Let me guess what you want.
<% #workers.group_by(&:name).each do |name, workers| %>
<tr>
<td><%= name %></td>
<td><%= workers.map {|w| w.tasks.size}.sum %></td>
<td><%= workers.map {|w| w.tasks.select{ |task| task.done != 'yes' }.size}.sum %></td>
<td>
<% workers.each do |worker| %>
<%= link_to 'new Task', new_worker_task_path(worker) %>
<% end %>
</td>
<td>
<% workers.each do |worker| %>
<%= link_to 'Show Tasks', worker_tasks_path(worker) %>
<% end %>
</td>
</tr>
<% end %>
I am working on a simple rails 3 todo application and I am trying to filter the app by completed tasks and none completed task but whenever I try calling a scope I get the error message.
undefined method `completed' for #<Array:0x007fe8420d0e58>
task.rb
scope :completed , where(:completed => true)
scope :incomplete , where(:finished => false)
index.html.erb
<table>
<tr>
<th>Name</th>
<th>Description</th>
<th>Finished</th>
<th>User</th>
</tr>
<% #tasks.each do |task| %>
<tr>
<td><%= task.name %><%= button_to "complete", complete_task_path(task.id)%></td>
<td><%= task.description %></td>
<td><%= task.finished %></td>
<td><%= task.user_id %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Destroy', task, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<%= content_tag :h2, "Stuff Ive done" %>
<table>
<tr>
<th>Name</th>
</tr>
<% #tasks.completed.each do |task| %>
<tr>
<td><%= task.name %></td>
</tr>
<% end %>
</table>
task_controller.rb
def complete
#task = Task.find(params[:task_id])
#task.completed = true
#task.save
redirect_to task_path
end
routes.rb
match "tasks/:id/complete" => "task#complete", :as => :complete_task
Any reasons why rails is giving me this error?
Just by looking at your view (index.html.erb), in one place, you are treating as a relation.
<% #tasks.each do |task| %>
Later in the code, you are trying to access it as a single object.
<% #tasks.completed.each do |task| %>
Since you are seeing the error on the second instance, you need to access 'completed' as in:
<% #tasks.completed.each do |task| %>
<% completed = task.completed %>
<% completed.each do |com| %>
Does this make sense?