Edit multiple saved records - ruby-on-rails

I'm trying to develop a simple exercise log app, and I'm stuck (again). A user selects a category, and a specific workout, and I return a list of exercises belonging to that workout.
An effort is a user specific instance of an exercise.
class Exercise < ActiveRecord::Base
has_many :efforts
end
class Effort < ActiveRecord::Base
belongs_to :exercise
end
I'm retrieving the list of exercises in the efforts controller
class EffortsController < ApplicationController
def log_workout
#exercises = Exercise.where("category_id = ? AND workout_id = ?", params[:exercise][:category_id], params[:exercise][:workout_id])
#effort = Effort.new
end
end
The user logs their workout by using the following form
<%= form_tag save_workout_path, method: :put do %>
<table>
<tr>
<th>Exercise</th>
<th>Sets</th>
<th>Reps</th>
</tr>
<% #exercises.each do |exercise| %>
<%= fields_for "efforts[]", #effort do |f| %>
<tr>
<td><%= exercise.name %></td>
<td><%= f.number_field :sets %></td>
<td><%= f.number_field :reps %></td>
<%= f.hidden_field :exercise_id, :value => exercise.id %>
</tr>
<% end %>
<% end %>
</table>
<%= submit_tag "Log it" %>
<% end %>
class EffortsController < ApplicationController
def create
params[:efforts].each do |values|
if current_user.efforts.create(values)
flash[:notice] = 'Efforts were successfully saved.'
else
render action: 'new'
end
end
end
end
How right this is, I'm not sure, but it works. My problem now is trying to retrieve saved 'efforts' and allowing them to be modified through the same form. (Letting the user edit their workout log). Would appreciate any guidance/help

Related

undefined method after using includes

i'll start how my models looks:
User -> has_one :customer, has_one :employee, has_many :appointments
Customer -> belongs_to :user
Employee -> belongs_to :user
Appointment -> belongs_to :user
And now in view:
<% #appointments.order(:appointment_date).each do |appointment| %>
<% if appointment.confirmation == wait_or_confirmed?(#status) %>
<tr>
<td><%= appointment.purpose %></td>
<td><%= appointment.appointment_date %></td>
<td><%= appointment.appointment_time %></td>
<td><%= Employee.find(appointment.employee_id).first_name %> <%= Employee.find(appointment.employee_id).last_name %></td>
<td><%= Customer.find(appointment.customer_id).first_name %> <%= Customer.find(appointment.customer_id).last_name %></td>
<td><%= link_to 'Show', appointment_path(appointment), class: "btn btn-primary" %></td>
</tr>
<% end %>
<% end %>
My brother told me i shouldnt pick up informtaions from database in views so i tried using includes:
#appointments = Appointment.all
#users = User.includes(:appointments)
And after combination in view it still doesn't work. Can someone help me?
Instead of this:
Employee.find(appointment.employee_id).first_name
Do this:
appointment.employee.first_name
For performance, in the controller, you can also replace this:
#appointments = Appointment.all
With this:
#appointments = Appointment.all.includes(:employee, :customer)
By doing so, you are eager-loading all associated employee and customer data from the database in a single query, rather than one at a time.

Bulk insert in rails

I cannot solve the following problem
Any help or suggestion is appreciated
Agent collects orders for Product on a paper going from one Shop to another in his Region.
At the end of the day, he inserts the quantity of each Product to each Shop.
Each Shop orders more than 4 types of products.
I need to design to be able to bulk insert.
<table>
<tr>
<td>Shop1</td>
<td>Product1</td>
<td>Product2</td>
<td>Product3</td>
<td>Product4</td>
etc...
</tr>
<tr>
<td>Shop2</td>
<td>Product1</td>
<td>Product2</td>
<td>Product3</td>
<td>Product4</td>
etc...
</tr>
etc...
</table>
In the browser it needs to look as below
One approach could be to use a custom form model. This is a pretty good guide on the subject. This may not be perfect, but should get you on the right track at least. All credit to the following (slightly modified for your question) code goes to Sam Slotsky from the blog linked above. Read the post for more detail about each piece.
Here's the custom form model:
class ProductForm
include ActiveModel::Model
attr_accessor :products
def products_attributes=(attributes)
#products ||= []
attributes.each do |i, product_params|
#products.push(Product.new(product_params))
end
end
end
Here's the controller:
class ProductsController < ApplicationController
def new
#product_Form = ProductForm.new(products: [Product.new])
end
def create
#product_form = ProductForm.new(params[:product_form])
if #product_form.save
flash[:notice] = "Created products"
redirect_to root_path
else
flash[:notice] = "There were errors"
render :new
end
end
end
Here's the view:
<div>
<%= form_for #product_form, url: products_path, method: :post do |f| %>
<%= f.fields_for :products do |c| %>
<%= c.text_field :attr_1 %>
<%= c.text_field :attr_2
<%- # ... etc ... %>
<% end %>
<p>
<%= f.submit "Submit" %>
</p>
<% end %>
</div>

RoR edit value of join table from nested form

I am a noob on Ror. Been looking for my problem answers for 3 days now, I have been looking for the answers but can’t find one with my specific problem. ( I even found it hard to write the right title)
So I have been trying to build a nested form in RoR. I have a simple order form that enable users to specify the quantity they ordered in that form. The form will only store the value into the database if the quantity text field is not empty.
The Order form is simply look like this:
I am storing the quantity data into the join table between order and inventory which has many to many relationship through Inventory_orders table. now in the Inventory_orders table instead of only having orders_id and inventories_id , I also add the quantity column.
now I have been able to get the form working with the code below:
Controller:
def new
#order = Order.new
#customer = Customer.all
#inventories_list = Inventory.all
#inventory_order = #order.inventory_orders.build
end
def create
#order = Order.new(order_params)
#inventories_list = Inventory.all #controller can call any model
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def order_params
params.require(:order).permit(:customer_id, :order_ids => [],:inventory_orders_attributes => [:id, :quantity, :inventory_id ])
end
View:
<%= form_for(#order) do |f| %>
<div id = “Main_Container">
*** Some Code ***
<table id = "inventory_table">
<tr>
<td class = "prodCodeTitle"><h3>Prod Code</h3></td>
<td class = "prodResult"><h3>Quantity</h3></td>
<td class = "prodResult"><h3>Size</h3></td>
<td class = "prodResult"><h3>Price</h3></td>
</tr>
//Here display all the inventories list
<% #inventories_list.each do |t| %>
<tr>
<td class ="prodResult"><%= link_to t.pName, inventory_path(t), :remote => true %></td>
<td class = “prodResult">
//nested form for the join table
<%= f.fields_for :inventory_orders do |qty| %>
<%= qty.hidden_field :inventory_id , value: t.id %>
<%= qty.number_field :quantity %>
<%end%>
</td>
<td class = "prodResult"><%= t.pMeter %></td>
<td class = "prodResult"><%= t.pSellPrice %></td>
</tr>
<% end %>
*** Some Code***
<% end %>
Model:
class Order < ActiveRecord::Base
belongs_to :customer
has_many :inventory_orders
has_many :inventories, through: :inventory_orders
validates :customer_id, :presence => true
accepts_nested_attributes_for :inventory_orders, :reject_if => lambda { |a| a[:quantity].blank?}
end
class InventoryOrder < ActiveRecord::Base
belongs_to :inventory
belongs_to :order
validates :quantity, :presence => true
end
Now when creating new Orders form , the application works and store the data that I want in the inventory_orders table.
The problem occurs when I try to edit the form. When trying to click on edit button I get this output in my View file:
for example this is what I Input into the form:
when I try to edit the form this is what I get:
this is my controller for edit:
def edit
#order = Order.find(params[:id])
#customer = Customer.all
#inventories_list = Inventory.all
end
I have been looking at the psql database schema by manual do sql query as follow:
select * from inventory_orders where inventory_orders.order_id = 63;
and get this as result:
now it seems that the fields_for Inventory_orders get the number of rows returned , but I don't get why all the quantity also get displayed 4 times for each product. Also how can I ensure that when I try to edit quantity for product “aaa” it will only display one number_field with what users has input before.
Sorry for the long post,otherwise I am not sure how to clearly convey my meaning.
EDITED
this to show my Inventory Model:
Class Inventory < ActiveRecord::Base
has_many :inventory_orders
has_many :orders, through: :inventory_orders
end
You need to use the following:
//Here display all the inventories list
<% #inventories_list.each do |t| %>
<%= link_to t.pName, inventory_path(t), :remote => true %>
<%= f.fields_for :inventory_orders, t do |qty| %>
<%= qty.hidden_field :inventory_id , value: t.id %>
<%= qty.number_field :quantity %>
<% end %>
<%= t.pMeter %>
<%= t.pSellPrice %
<% end %>
The issue is that since f.fields_for populates a form based on the built associated objects, if you're passing 4 fully constructed objects through the edit action, fields_for is going to populate all of them each time.
What you need is to use the instance of the associated data.
I think your code could be improved a lot:
#app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def new
#order = Order.new
#inventory = Inventory.all
#inventory_order = #order.inventory_orders.build
end
def edit
#order = Order.find params[:id]
#inventory = Inventory.all
end
end
#app/views/orders/new.html.erb
<%= form_for #order do |f| %>
<% #inventory.each do |inventory| %>
<%= f.fields_for :inventory_orders, item do |item| %>
<%= item.text_field :quantity %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
#app/views/orders/edit.html.erb
<%= form_for #order do |f| %>
<%= f.fields_for #order.inventory_orders do |item| %>
<%= item.text_field :quantity %>
<% end %>
<%= f.submit %>
<% end %>

Why do I get this NoMethodError

I'm making a twitter-copy and right now I'm trying to show all the posts from the users an other user is following. I'm new at ruby and rails, so i might be doing this a really weird way..
These are the files I have:
session#home.html.erb
<h2 class='User_Header'> Home <h2>
<%= link_to "New Post", controller: "posts", action: "new" %>
<%= link_to "Log Out", :controller => "sessions", :action => "logout" %>
<%= show_tweets("following") %>
sessions_helper
module SessionsHelper
def show_tweets(opt)
if opt == "following"
#sub = Subscription.where("userID = ?", #current_user.id)
#post = Post.where("user_id = ?", #sub.followingID)
render partial: 'shared/follower_tweets'
end
end
def show_tweet(s)
#post = Post.where("user_id = ?", s.id)
render partial: 'shared/tweet'
end
def tweet_username(p)
#username = User.where("id = ?", p.user_id)
Rails.logger.debug #username.inspect
render partial: 'shared/user'
end
end
_follower_tweets.html.erb
<h2>Tweets</h2>
<table>
<tr>
<th>Username</th>
<th>Tweet</th>
</tr>
<% div_for(#post, class: 'post') do %>
<td><%= tweet_username(#post) %></td>
<td><%= #post.content %></td>
<% end %>
</table>
_user.html.erb
<%= #username %>
session.rb
class Session < ActiveRecord::Base
attr_accessible :content, :user_id, :followingID, :userID
end
Error
app/views/sessions/home.html.erb where line #9 raised:
undefined method `followingID' for #<ActiveRecord::Relation:0x007fd74b66f8a8>
What is happening is that you have followingID on your Session model instead of Subscription model. Should be something like the following:
class Subscription < ActiveRecord::Base
attr_accessible :followingID
end
However, the problem is bigger than that. You must read about Active Record Associations, then you would be able to do something like
#subs = #current_user.subscriptions
#posts = #current_user.posts
check if your model's association is correct. the messages indicates that there's an error about this.

Help with rails nested forms

I have these three models.
Student.
Evaluation.
Grade (student_id, evaluatioin_id, value)
I want to make a form so that a User can set the grade for each student of a evaluation...
I want to keep this is as clean as possible (and restful)...
Im open to any suggestions on how to get this done.
Please Help.
See these
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
I suppose you have the following associations:
Evaluation:
class Evaluation < ActiveRecord:Base
has_many :grades
accepts_nested_attributes_for :grades
end
Student:
class Student < ActiveRecord::Base
has_many :grades
end
Grade:
class Grade < ActiveRecord::Base
belongs_to :student
blongs_to :evaluation
end
Regarding your comment I think you want to use the nested_form_for gem made by Ryan Bates. It helps you add/delete dynamically nested attributes in your form, very efficiently. You can use it like this:
<% nested_form_for #evaluation do |f| %>
<% f.fields_for :grades do |gf| %>
<%= gf.label 'Username of the student' %>
<%= gf.collection_select(:student, :student_id, Student.All, :id, :username) %> <br/>
<%= gf.label :value %>
<%= gf.text_field :value %> <br/>
<%= gf.link_to_remove 'delete' %> <br/>
<% end %>
<%= f.link_to_add 'Add grade', :grades %> <br/>
<%= f.submit %>
<% end %>
Tell me if it works/fits your needs. I have been using this gem a lot these previous days.
What I ended up doing was..
In Grade Model
scope :for_student,lambda{|student, evaluation| where("student_id"=>student.id).where("evaluation_id"=>evaluation.id)}
In EvaluationsController
def assign_grades])
#evaluation = Evaluation.find(params[:id])
#students = Student.all
#students.each do |s|
grade = Grade.for_student(s,#evaluation)
if !grade.exists?
#evaluation.grades.build(:value=> 0,:student_id=>s.id)
end
end
end
def save_grades
#evaluation = Evaluation.find(params[:id])
#evaluation.update_attributes(params[:evaluation])
redirect_to [#evaluation.batch_subject, #evaluation]
end
In View
<table class="medium">
<thead>
<tr>
<th>name</th>
<th>Grade</th>
</tr>
</thead>
<tbody>
<%=f.fields_for :grades do |g|%>
<tr>
<td><%=g.label :value,g.object.student.full_name%> <%= g.hidden_field :student_id%></td>
<td><%=g.text_field :value%></td>
</tr>
<%end%>
</tbody>
</table>

Resources