<% #book.each do |book| %>
<%= book.title%>
<%=image_tag book.image_link%>
<%= book.authors%>
<%= book.description%>
<%= link_to 'Book IT' %>
<%= link_to 'Read IT' %>
<%= link_to 'Own IT' %>
<% end %>
So heres a copy of my code that prints the title, image, and author of a book searched. I am trying to associate the 'Book IT' link to add that particular object to my "Book it" library/table so that when i click on my 'Book It' Library link it will display that book.
A few other questions. Should I replace the link with a button? if so will the button be associated with the object through the loop?
you can do it with ajax request
<%= link_to 'Book IT',add_to_my_books_book_path,remote: true %>
routes
resoures :books do
member do
get :add_to_my_books
end
end
controller
def add_to_my_books
#book = Book.find params[:id]
#my_books = current_user.books
#my_books << #book
respond_to do
format.js {render alert("book added to your books")}
end
end
i assume that you has one_to_many relationship between users and books
Related
In my Rails 5 app, Doctor/Admin have to create a Caregiver with linked Patient (new object CaregiverPatient represents that). During this process, inside the registrants_controller#new, Doctor/Admin search for a Patient (which is done by Ransack gem) and from the result he/she push Add Patient button to add Patient to initialized CaregiverPatient object from caregiver_patient#new and display #patient.full_name inside the form.
In order not to lose already filled form fields, everything must be done asynchronously. I've tried to do so with AJAX, below my code:
registrant_controller.rb
def new
#registrant = Registrant.new
#patient = Registrant.find(session[:patient_id_to_add_caregiver]) if session[:patient_id_to_add_caregiver]
end
registrants/_new_form.html.erb
<%= form_for #registrant do |f| %>
<%= f.fields_for :registration do |registration| %>
<% if #patient %>
<div id="add-patient"></div>
<% else %>
<%= required_text_field_group registration, #registrant, :registrant_id, "Patient Added", {}, { disabled: true } %>
<% end %>
<% end %>
# some other logic (...)
# patient search result
<% #registrants do |registrant| %>
<%= link_to 'Add Patient', new_registrant_link_path(registrant), remote: true %>
<% end %>
Add Patient button triggers caregiver_patients#new action:
#caregiver_patient_controller.rb
class CaregiverPatientsController < ApplicationController
# new_registrant_link_path
def new
session[:patient_id_to_add_caregiver] = params[:registrant_id].to_i
respond_to do |format|
format.html { redirect_to request.referer }
format.js { render action: 'patient_to_caregiver', notice: 'Patient Added' }
end
end
end
AJAX request is made:
#views/caregiver_patients/patient_to_caregiver.js.erb
$("#add-patient").html("<%= escape_javascript(render :partial => 'registrants/add_patient') %>");
views/registrants/_add_patient.html.erb
Patient Added: <%= #patient.full_name %>
But surprisingly gets an error:
ActionView::Template::Error (undefined method `full_name' for nil:NilClass):
1: Patient Added: <%= #patient.full_name %>
Which probably means that registrants_controller#new was not refreshed under the hood somehow. What have I missed?
I realize there are dozens of similar questions here on this topic, I have looked through many of them and tried to duplicate the solutions and nothing has worked for me.
I have a list of tasks displayed in the index view as a partial, when the user adds a task I would like list to show the newest task (as well as all the others already there).
Here is the create controller:
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
respond_to do |format|
format.js
end
else
flash[:error] = "Task not added"
render 'new'
end
The _new partial:
<%= form_for(#task, method: :post, remote: true) do |f| %>
<%= f.label :comments %>
<%= f.text_field :comments, id: "task-comments" %>
<%= f.submit "Insert" %>
<% end %>
Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
create.js.erb
console.log("create.js.erb called");
document.getElementById("task-comments").value = "";
document.getElementById("current-tasks").html('<%= j(render partial: "show_list") %>');
I have been able to get the console to log the message and even been able to clear the input box but the partial does not render, I have tried this in a few different ways and the script always seems to stop executing when it gets to the escape javascript line.
There are no JS errors, as stated above, the console logs the message when the "submit" button is pressed. There is a warning [Violation] Forced reflow while executing JavaScript took 114ms but I don't think that is relevant to this issue.
Here is the partial that I am trying to render _show_list.html.erb
<% unless #tasks.nil? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
def create
#task = current_user.tasks.build(task_params)
if #task.save
flash[:success] = "Task added"
#respond_to do |format|
#format.js
#end
else
flash[:error] = "Task not added"
render 'new'
end
end
It's always good practice to use local variable in partial
1) => Index.html.erb
<div id="new-task-form">
<%= render 'new' %>
</div>
<div id="current-tasks">
<%= render partial: 'show_list', locals: {tasks: #tasks} %>
</div>
2) => If you are using jquery (create.js.erb)
console.log("create.js.erb called");
$("#task-comments").val('');
$("#current-tasks").html('<%= j render "show_list", tasks: #tasks) %>');
3) => _show_list.html.erb(Use tasks instead of #tasks)
<% unless tasks.blank? %>
<ul>
<% tasks.each do |tsk| %>
<li><%= tsk.comments %></li>
<% end %>
</ul>
<% end %>
ok you have some problem here with your validation on the show_list partial.
you have this line
<% unless #tasks.nil? %>
try to use something more readable like
<% if #tasks.present? %>
and on your controller create action, you don't fill the #tasks variable, so that's the problem in reality, add on you controller the load for all the tasks after saving the new one.
if #task.save
#tasks = Task.all
flash[:success] = "Task added"
and that will make it work, but I recommend to load just the created one and add just one column to the table and not update the complete list again if you have all the others on the client already.
I'm trying to create a relationship in the database, but cant get it to work.
why wont the create action work? why can't it find the if statement? I think i havent written the create action correctly in the relationships controller but don't know how to fix it
When a user clicks 'add relationship'. the app should create the new relationship.
At the moment a user clicks 'add relationship' and this flash success msg appears:
You are now connected !
this is the information that comes across to the view where the flash success msg appears:
relationships.html.erb
relationship: !ruby/hash:ActionController::Parameters
followed_id: '3'
commit: Add Relationship
action: create
controller: relationships
but! a relationship is not created in the database
Here is the flow users take with comments to help explain:
users/index.html.erb:
# 1. USER SEARCHES FOR ANOTHER USER IN SYSTEM:
<%= form_tag users_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
# 2. IF ANOTHER USER IS FOUND, THEIR NAME IS PRESENTED AND AN 'ADD RELATIONSHIP' BUTTON APPEARS:
<ul>
<% #users.each do |user| %>
<li>
<%= user.name %>
<%= render 'followed', followed: user %>
</li>
<% end %>
</ul>
_followed.html.erb:
# 3. ADD RELATIONSHIP BUTTON INFORMATION. THE USER CLICKS THE BUTTON, RELATIONSHIPS/CREATE IS THE NEXT PAGE. NO RELATIONSHIP IS CREATED
<%= form_for :relationship, url: relationships_path, method: :post do |f| %>
<div class="form form-actions">
<%= f.hidden_field :followed_id, value: followed.id %>
<%= f.submit "Add Relationship", class: "btn btn-primary" %>
</div>
<% end %>
relationships_controller:
def create
if params[:relationship] && params[:relationship].has_key?(:followed_id)
#followed = User.find_by(name: params[:active_relationship][:followed_id])
#active_relationship = current_user.active_relationships.new(followed: #followed)
#active_relationship.save
flash[:success] = "You are now connected !"
else
flash[:danger] = "Relationship required"
end
end
Looks like the error is in the second line in your create controller. In your if statement you have params[:relatioship] so I guess you would write
#followed = User.find_by(name: params[:relationship][:followed_id])
and I guess the followed_id shouldn't be a name
You should refactor the code like this:
if params[:relationship]
#followed = User.find(params[:relationship][:followed_id])
#active_relationship = current_user.active_relationships.new(followed: #followed)
if #active_relationship.save
flash[:success] = "You are now connected !"
else
flash[:danger] = "Relationship required"
end
else
flash[:danger] = "Something was wrong!!"
end
You might also use pry to debug codes. Links for reference http://pryrepl.org
So I have an interesting problem I'm working on. I am trying to create multiple objects of the same model in one view. I would like to display all the possible objects in my view, check boxes to select which ones to create, then submit and create all the corresponding objects.
Now the objects to select are gotten using an API request and returned in JSON format. The JSON is then displayed on the view for the user to select, then an array containing all the selected objects is sent back to the controller for creation.
Here is the relevant code that I've tried so far.
objects_controller.rb
def new
#possible_objects = <api call to get objs>
#objects = []
end
def create
params[:objects].each do |obj|
# create and save obj
end
end
objects/new.html.erb
<% form_for #objects do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag(api_obj["name"])%>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
This is definitely not the right approach, as the form will not accept an empty array as a parameter. I'm not sure where else to go with this, any pointers in the right direction would be great. Thanks.
Thanks to MrYoshiji for pointing me in the right direction, this is what ended up working
objects_controller.rb
def
#possible_objects = <api call to get objs>
end
def create
params[:objects].each do |object|
new_obj = Object_Model.new( <params> )
new_obj.save
if !new_obj.save
redirect_to <path>, alert: new_obj.errors.full_messages and return
end
end
redirect_to <path>, notice: 'Successfully created.'
end
objects/new.html.erb
<%= form_tag objects_path(method: :post) do %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[]', api_obj %>
<%= possible_object["name"] %>
<% end %>
<%= submit_tag 'Create'%>
<% end %>
Can you try the following?
# view
<% form_tag my_objects_path(method: :post) do |f| %>
<% #possible_objects.each do |api_obj| %>
<%= check_box_tag 'objects[names][]', api_obj["name"] %>
<%= api_obj["name"] %>
<% end %>
<%= f.submit %>
<% end %>
# controller
def create
params[:objects][:names].each do |obj_name|
YourModelForObject.create(name: obj_name)
end
end
See this comment on the documentation of check_box_tag: http://apidock.com/rails/ActionView/Helpers/FormTagHelper/check_box_tag#64-Pass-id-collections-with-check-box-tags
I am having a difficult time finding information on this but think the solution is a simple one. In short, I need to have the ability to add multiple entries to one model at one time. The user story goes like this: User selects "Add New" and is directed to the page where they can add simply ONE entry or select a drop down of the desired entries they want to add.
All the posts I see have information about doing this with objects that are nested but I am just using one model. Do I need to follow the same protocol? Is there a simpler way? Am I just searching for the wrong terminology since being new to Ruby?
The basic application looks like this:
ticket_controller.rb
def new
#ticket = Ticket.new
end
def create
tnum = gets.chomp
tnum.times do Ticket.new(ticket_params)
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render action: 'show', status: :created, location: #ticket }
else
format.html { render action: 'new' }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
new.html.erb
<h1>New ticket</h1>
<%= render 'form' %>
<%= link_to 'Back', tickets_path %>
I have looked throughout the site and just think I am missing something! Thanks for pointing me in the direction needed.
_form.html.erb
<%= form_for(#ticket) do |f| %>
<% tnum.times do |index|%>
<div class="field">
<%= f.label :type %><br>
<%= f.text_field :type %>
</div>
<div class="field">
<%= f.label :amount %><br>
<%= f.text_field :amount %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
There must be a better way, but this one way to do it. (Note I normally use a 'Form Object' but for this example I'll just use the raw collection):
In your controller change the object passed to the new form to be an array (in this case I'll pre-populate it):
def new
#tickets = [Ticket.new(title: 'New Ticket')]
end
Then in your new template you need to update it to iterate over the tickets array:
<%= form_tag tickets_path do |f| %>
<% #tickets.each do |ticket| %>
<%= fields_for "tickets[#{ticket.object_id}]", ticket do |builder| %>
<%= render 'ticket_fields', f: builder %>
<% end %>
<% end %>
<%= link_to_add_ticket "Add Tickets" %>
<%= submit_tag %>
<% end %>
The ticket fields partial looks like:
<fieldset>
<%= f.label :content, "Ticket" %><br />
<%= f.text_field :title %><br />
</fieldset>
For good measure add a helper to allow you to add new tickets dynamically:
module TicketsHelper
def link_to_add_ticket(name)
# create a new object for the form
new_object = Ticket.new
# get an id for javascript to hook into
id = new_object.object_id
fields = fields_for("tickets[#{id}]", new_object) do |builder|
render("ticket_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
end
and you need some coffee script to wire that up:
jQuery ->
$('form').on 'click', '.add_fields', (event) ->
time = new Date().getTime()
regexp = new RegExp($(this).data('id'), 'g')
$(this).before($(this).data('fields').replace(regexp, time))
event.preventDefault()
Basically all of this is an adaption of this railscast which might be helpful: http://railscasts.com/episodes/196-nested-model-form-revised however, that is dealing with the more classic nested model.
Couldn't you save the number of tickets the user wants to purchase to a variable, then pass that integer to a times loop? Like so:
#gets from form
ticket_buys = gets.chomp
ticket_buys.times do Ticket.new(ticket_params)