Ask A Question

Notifications

You’re not receiving notifications from this thread.

Problem with deletion and recreation of same association

Rohan Mayya asked in Rails

I have a user model created through devise, a stock model (generated through a scaffold) so I can create a stocks database with my own custom prices, and a UserStock model to establish an association between the two. Everything seems to run fine in both my UI and my console.

Here's the catch.
I have a delete method tied to a button that is configured in my _list.html.erb, which displays all stocks in the user's portfolio. When I delete it the first time, (remove stock from my portfolio) it works fine. When I add the stock again to my portfolio, works fine of course. But the deletion the second time does not work.

Say, for example, my user ID is 1. My UserStock association creates an association between user_id 1 and stock_id 1 (say stock with id 1 is Google). This is stored in UserStock id 1. When I delete this association and recreate the same, it gets stored in UserStock id 2 (a brand new association). But when I try to delete it again, I'm unable to do so. My rails console indicates this error in my UserStock controller.

This is the error that pops up: Record Not Found in UserStocksController#destroy

  def set_user_stock
   @user_stock= UserStock.find(params[:id])  
  end

Here's my view and the required models:
_list.html.erb

            <% if @user.id == current_user.id %>
            <td>
            <%=link_to "Delete", user_stock_path(user_stock), :method 
            => :delete, :data => { :confirm => "Are you sure?" },
            :class => "btn btn-xs btn-danger" %>
            </td>
            <% end %>

user.rb

     has_many :user_stocks
     has_many :stocks, through: :user_stocks
     def can_add_stock?(ticker_symbol)
       !stock_already_added?(ticker_symbol)
     end

     def stock_already_added?(ticker_symbol)
       stock = Stock.find_by_ticker(ticker_symbol)
       return false unless stock
       user_stocks.where(stock_id: stock.id).exists?
     end

stock.rb

has_many :user_stocks
has_many :users, through: :user_stocks
def self.find_by_ticker(ticker_symbol)
    where(ticker: ticker_symbol).first
end

user_stock.rb

belongs_to :user
belongs_to :stock
Reply

The easiest way is to mimmic the flow in your console.
Check UserStock.last and compare its details to the one you're trying to find after the second time.

BTW a few things that will make your code cleaner (in my personal opinion)

I would replace set_user_stock by:

def set_user_stock
       @user_stock= @user.user_stocks.find_by( id: params[:id]) 
         if @user_stock.nil?
          # do something , for example:
             flash[:danger]= 'msg'
             redirect_to 'path' and return
         end
end

This will also remove the need for the if @user.id condition since if some other user tries to touch another user stock , he will get redirected.

No need to define find_by_ticker simply use Model.find_by( key_name: value) , it will return the model or nil.
Also , you can add a unique index + validation on ticker_symbol (or ticker_symbol && user_id which make it easier to search/validate the checks you do.

Is this a typo?
<% if @user.id = current_user.id %>
You're assigning to @user.id and not comparing ==.

Reply
  1. UserStock.last retrieves UserStock id:6, (user_id:1 and stock_id: 2) which means there have been over 5 associations created just by creating and deleting the same association. (I kept manually destroying the association in my console). I just deleted and recreated the same association again, and it allots UserStock id:7.
    But when I try to use the destroy action in my UI, the rails console still tells me UserStock id:1 cannot be found.
    How am I supposed to work around this?

  2. In your set_user_stock method, user_stocks is a method that isn't defined.

  3. It'd be a pain to remove the method I created and then remove it everywhere but I'll do it when I'm in the process of refactoring code. Thanks for the heads up, didn't know I could directly call a Model.

  4. Yes, it was a typo. Was in a hurry while typing out this question.

How do I go about this? Same error.

Reply
  1. Add prints from inside the view <% puts "user_id = #{@user.id} | current_user.id = #{current_user.id} | user_stock = #{user_stock.inspect}" %> to see what is the content in the view.

  2. Your user model should have user_stocks association on it, did you create a foreign key reference?

  3. Yeah , where usualy works on some ActiveRecord types. The various find* methods are actually wrappers for where. For example find_by https://apidock.com/rails/v4.0.2/ActiveRecord/FinderMethods/find_by , although I'm missing a limit(1) in those calls , that bothers me a little bit since if you know that you take the first only than you should also limit the SQL call.

Try #1 , to understand what's going on , the inconsistency must be in one of the 3 variables hence , start exploring them. puts and inspect are your friends :)

Reply
  1. Nothing is displayed in the view when I add this line.
    EDIT: When I look at my server logs the values returned from user_id, current_user.id and user_stock all seem to be correct. They're returning the values that are supposed to be returned.
    UPDATE: Oops, on checking again, user_stock = #{user_stock.inspect}" is returning the Stock id in my console and NOT my user_stock association ID. So the fault lies in this variable. (In fact, this variable is returning the entire stock itself, with its name, ticker symbol and price) But isn't it supposed to be returning only the user_stock association ID?

  2. I just generated a migration to add foreign keys for user_stocks to user and stocks, but the user_stocks is still a method that is not defined. (this is what my console tells me)

EDIT: I think I know where I'm going wrong. The table is being iterated with the stocks association and not the user_stock association. I changed it to iterate through the user_stock end, but now how do I call the name, symbol and price variables within the table data?

Reply

I didn't understand the problem once you change the iterator.
Are you having any issue with <% user_stock.symbol %> or anything similar?

Reply
Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 85,376+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.