I'm attempting to learn Ruby on Rails by creating a project and I can't seem to get my head around an error I keep getting. If I don't get the "NoMethodError", I'll get something like "You have a nil object when you didn't expect it!" - I simply want to view a bank account and have it show the transactions on that bank account. My problem may be with the controller, but I've tried all sorts of different things and can't figure it out. Much help would be greatly appreciated. I think I've included everything, if not, I apologise and will include what ever else is needed.
Bank Account Controller Show (I think the error is in the show):
def show
#bank_account = BankAccount.find(params[:id])
#transactions = #bank_account.transaction
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #bank_account }
end
Views: bank_accounts>show.html.erb
<% #transactions.each do |transaction| %>
<tr>
<td><%=h transaction.transaction_id %></td>
<td><%=h transaction.dateD %></td>
<td><%=h transaction.trans_type %></td>
<td><%=h transaction.amount %></td>
<td><%=h transaction.new_balance %></td>
<td><%=h transaction.transaction_success %></td>
<td><%= link_to 'Show', transaction %></td>
<td><%= link_to 'Edit', edit_transaction_path(transaction) %></td>
<td><%= link_to 'Destroy', transaction, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
I think this is the backtrace (sorry for not including it).
"BankAccount/app/controllers/bank_accounts_controller.rb:17:in `show'"
Also, if I do the following for the bank account controller:
def show
#bank_account = BankAccount.find(params[:id])
#transactions = #bank_account.transactions
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #bank_account }
end
I get this SQL error:
"ActiveRecord::JDBCError: [SQLITE_ERROR] SQL error or missing database (no such column: transactions.bank_account_id): SELECT * FROM "transactions" WHERE ("transactions".bank_account_id = 1)"
It looks like your problem is that the BankAccount.find is returning nil. Then, on the next line, you are trying to access the transaction method on #bank_account, which throws the error.
Make sure that params[:id] has the correct value.
if your BankAccount model has many transactions, the method to access them is plural:
#transactions = #bank_account.transactions
You may want to look at your model code and your migration code.
In order to have #bank_account.transaction to return the transaction, the two of them must have one-to-one relationship.
Your bank_account model should have
has_one :transaction
Your transaction should have
belong_to :bank_account
Your migration script when creating transaction table should have something like
transaction.references :bank_account
The reference will create the field bank_account_id in your transaction table.
I think it explain why you have error that "no such column: transactions.bank_account_id)"
Related
Good Evening, I've been trying for figure out why when I raise inspect.params I get id => "id"
Please see the code I have for updating the :approved to true from an admin form which doesn't update the attributes. I guess it's something I'm just overlooking
Form index.html.erb
<% #snippets.each do |snippet| %>
<tr>
<td><%= link_to snippet.content %></td>
<td><%= snippet.created_at.to_date %></td>
<td><%= render snippet %></td>
<td>Status</td>
<td><%= button_to 'Approve', active_snippet_path(snippet.id) %></td>
</tr>
Controller (Snippets#approve)
def approve
##snippet = #book.snippet.find(params[:id])
if #snippet.update_attribute(:approved, true)
redirect_to users_path
else
render root_path
end
end
The error is being cause by this bit apparently but not sure why:
def find_book
raise params.inspect
#book = Book.find(params[:id])
#snippet = #book.snippets
return #book
end
end
This is the inspect I get.
{"authenticity_token"=>"D70njMSz3iYbVcCCkFIlolPBKeZUsVtFL5pabRT1CMo=", "controller"=>"snippets", "action"=>"approve", "id"=>"id"}
Please let me know if you need anything else. I would like to understand clearly why this put isn't working for a nested model.
The problem is you have what seems an array of Snippets (#book.snippets) you set to #snippet, and are attempting to use the update_attribute method, which only works on one instance. If you want to update an array, you could use something to the effect of:
Snippet.where(book_id: params[:id]).update_all(approved: true)
I'm new to ruby and picking it up a little slower than I would like. I'm working with ruby 3.0. For one of my tables in the database I created I want the primary key to show on the "index" page. I'm having difficulty doing this. I manually put the id in the index view, but it keeps on saying "undefined method `venture_round_id'"
This is what my index.html looks like for the table:
<h1>Listing venture_rounds</h1>
<table>
<tr>
<th>id</th>
<th>company</th>
</tr>
<% #venture_rounds.each do |venture_round| %>
<tr>
<td><%= venture_round.venture_round_id %></td>
<td><%= venture_round.company_id %></td>
<td><% link_to 'show', venture_round %></td>
<td><%= link_to 'Edit', edit_venture_round_path(venture_round) %></td>
<td><%= link_to 'Destroy', venture_round, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
I entered "venture_round_id" and "id" in manually.
This is what my controller looks like for the index:
def index
#venture_rounds = VentureRound.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #venture_rounds }
end
end
I've been researching this problem for two days now and haven't been able to find much about it. I imagine the problem has something to do with accessing the key in its own table. Other parts of my database structure that use venture_round_id as a foreign key work just fine. Any pointers or tips would be greatly appreciated!
Try venture_round.id instead of venture_round.venture_round_id
edit from MrDanA:
a foreign key is usually in the format "table_id" but the table's own primary key is usually just "id". If you ever want to look at what your database tables look like, you can open db/schema.rb to look at the schema. You can also fire up a Rails console and if you just type in the name of your class like VentureRound it will show you its attributes, something like VentureRound(id: integer, company_id: integer, etc)
I'm doing an online judge application, so I have a User model, a Problem model and a Solution model to make the many to many relation. In that Solution model I have an extra column called "state" where I plan to store the state of a problem for a certain user: solved, wrong anwser, not solved.
I'm trying to modify the index action in my problems controller to render the state of the problem in the problem list (so a user can see if he has solved a problem or not, like I said before). Nevertheless I'm having an "uninitialized constant Admin::ProblemsController::Solution" error when I access the view.
I'm really new to RoR and my experience so far has been really harsh, so I'll appreciate any leads. Here is the code in the controller and the view:
problems_controller.rb
def index
#problems = Problem.all
if current_user
#solutions = Solution.includes(:problem).where(:user_id => current_user.id)
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #problems }
end
end
views/problems/index.html.erb
<% #problems.each do |problem| %>
<tr>
<td><%= problem.name %></td>
<td><%= problem.code %></td>
<td><%= problem.description %></td>
<% if current_user %>
<%= for solution in #solutions do %>
<% if solution %>
<td><%= solution.state%></td>
<% else %>
<td>Not Solved</td>
<% end %>
<% end %>
<% end %>
<td><%= link_to 'Show', problem %></td>
<% if current_user && current_user.is_admin? %>
<td><%= link_to 'Edit', edit_problem_path(problem) %></td>
<td><%= link_to 'Delete', problem, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
</tr>
<% end %>
I'm not sure if that's the best way I should be accessing the Solutions table or if I should be doing that in another controller (in the users controllers? in a solutions controller file perhaps?).
I want to be clear of how to use that "Solutions" join table. I had a has_and_belongs_to_many before and changed it because of the extra column. I've read a lot about many to many relationships, but I can't understand it for this case =(
Just need to use:
problem.solution.state
Unless a problem may have many solutions, then it would need to be something like:
problem.solutions.first.state
However this will just give the state of the first, so I'd define a method in Problem which calculates a status (eg. If any of the solutions solve it then problem is solved)
For 1 problem, many solutions for a given user.
In Solution.rb
scope :for_user, lambda {|user_id| :conditions => {:user_id => user_id}}
Then we can call:
problem.solutions.for_user(current_user.id).first.state
It might look a bit long but it's highly flexible.
I am trying to simply create a button that will delete a contact from a list of contacts.
At the moment I have the following setup:
Contacts Controller
def destroy
#user.contacts.delete(params[:contact])
#contact.delete
end
View
<tbody>
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.name %></td>
<td><%= contact.company %></td>
<td><%= contact.email %></td>
<td><%= contact.phone %></td>
<td><%= contact.mobile %></td>
<td><%= button_to 'Delete', contact, :method => :delete %></td>
</tr>
<% end %>
Routes
controller :contact do
get "newcontact" => "contact#new"
get "index" => "contact#index"
delete "delete" => "contact#destroy"
end
I have read online that using button_to is the preferred method but at the moment I am getting the following error:
undefined method `contacts' for nil:NilClass
It would be great to get any feedback that might help me fix this.
Thanks in advance
Tom
For anyone looking for the final answer on this it was
def destroy
contact = current_user.contacts.find(params[:id])
contact.destroy
redirect_to index_path
end
In my controller and the following in my view
<%= button_to 'Delete', contact, :method => :delete %>
Thanks
Tom
If you are goin to use #user you need to set #user in your delete method or else it will be nil - hence the error message
The other issue is that the id of the contact is params[:id] and not params[:contact]
I'd just do
contact = current_user.contacts.find(params[:id])
contact.destroy
You definitely want to be deleting the contact via the user or else people can delete other users' contacts. This deletes the contact and removes it from the association - you don't need to do anything else
try something like this:
button_to "Delete", { :action => "delete", :id => contact.id}, :method => :delete
If #user is only defined in create it's only going to exist for requests that call create—and I'm guessing you're not calling create right before destroy. Each browser request creates a new instance of the controller; instance variables like #user don't stick around between requests.
To make it work, you probably just need this:
def destroy
Contact.delete params[:contact]
end
(When you delete a contact it will automatically be removed from e.g. current_user.contacts assuming your relations are set up in the usual way.)
Okay so I am creating an appointments site for professors and students to log on and create/edit appointments. I have the professors side done but I am struggling with the students. Right now I am trying to make it so students click a button next to their appointment to remove themselves from the appointment that they have with a professor. Now I could easily just delete the appointment id and the appointment would be gone but instead I want to remove the student_id from the appointment so other students could choose that appointment later. here is my code:
THE CONTROLLER:
def destroy
if session[:professor] != nil
#appointment = Appointment.find(params[:id])
#appointment.destroy
end
if session[:student] != nil
#appointment = Appointment.find_by_id_and_student_id(params[:id],params[:student_id])
#appointment.destroy(params[:student_id])
end
end
VIEW:
<% #appointments.each do |appointment| %>
<tr>
<td><%= appointment.professor_id %></td>
<td><%= appointment.student_id %></td>
<td><%= appointment.timeslot %></td>
<td><%= link_to 'remove appointment', appointment, confirm: 'Are you sure?', method:
:delete %></td>
</tr>
<% end %>
I have included the link here with my files if you want to take a look.
CLICK HERE TO VIEW MY FILES.
Also, everything takes place in the appointments controller. and this problem is in the show student view(where you press the delete button).
SOLUTION:
Okay so I got it working due to the help I got from you guys. So here is what I did:
#appointment = Appointment.find_by_id_and_student_id(params[:id], session[:student].user_id)
#appointment.update_attribute(:student_id, nil)
Almost certainly the error here is that Appointment.find_by_id_and_student_id is returning nil. Refactor your code like this:
#appointment = Appointment.find_by_id_and_student_id(params[:id],params[:student_id])
if #appointment
#appointment.destroy(params[:student_id])
else
flash[:error] = 'An appointment could not be found for that student.'
end
This will prevent you from receiving that error and should help you track down its root cause.