Search code examples
ruby-on-railsruby-on-rails-4.2nomethoderror

How can I write a Ruby method that allows me create a new row in a destination table while editing an attribute in the source table?


ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-darwin14]
Rails 4.2.5.2

So I've been struggling with this for a couple of days and not sure where to focus. My scenario: My user clicks a button on a source request view at REQUEST/index that creates a new row in my PERFORMANCE destination table and assigns attributes from the source. At the same time I need to flip a boolean attribute in the source table (REQUEST).

My code is below:

REQUEST VIEW

<%= new_performance_path( :attribute_id1 => (source.attribute_id1), :attribute_id2 => (source.attribute_id2), :attribute_id3 => (source.attribute_id3)), class: "btn btn-success" %>

PERFORMANCE CONTROLLER/NEW

def new
    @performance = Performance.new(:attribute_id1 => params[:attribute_id1], :attribute_id2 => params[:attribute_id2], :attribute_id3 => params[:attribute_id3] )
    @performance.completed = false
    @performance.save
    if @request.present?
      @request.available = false  #  Need to assign 'false' to this boolean attribute
      @request.save  #  Then save it.
    end
    redirect_to :performances
end

While the code creates the new row in my PERFORMANCE table I can't figure out the method syntax to effectively flip the REQUEST table attribute to "false". This code with the if statement processes without throwing an erorr. I've originally tried this in the PERFORMANCE CONTROLLER/NEW, without the if statement, which results in an internal server error:

  def new
    ...
    @request.available = false
    @request.save
    ...
  end

RAILS CONSOLE

Completed 500 Internal Server Error in 29ms (ActiveRecord: 10.1ms)

NoMethodError (undefined method `available=' for nil:NilClass):
  app/controllers/performances_controller.rb:26:in `new'

So I think this means I can't call available on request in my performances model. Based on that I tried to add a method to my PERFORMANCE model...

PERFORMANCE.RB

  def available
    Request.where( :available == true )
  end

...but the error persists. My thinking is that I need to grab all rows in the REQUEST table where the boolean value 'available' is equal to true.

Note that these two tables are not directly related to each other. REQUESTS is a join table in my domain model. The app is a music request app, so a USER has_many :REQUESTS, and :PERFORMANCES and I'm using existing rows in the REQUEST table to build new rows in the PERFORMANCE table, but need to edit the row in the request table when a new row is created in performance.

Thanks guys. Still learning being new to Rails and I struggle with referential relationships especially. Thanks for taking a look and helping me out.


Solution

  • @Shishir - After more research on Stack I ended up making my model fatter with a new method & thinning out the controller. This appears to have worked.

    PERFORMANCE CONTROLLER/NEW

     def new
        ...
        @performance.save
        # After @performance is saved we point to new method in performance.rb
        @performance.remove_request
        # it then comes back for the redirect
        redirect_to :performances, notice: "..."
      end
    

    performance.rb

      def remove_request
        @request = Request.find_by(:available => true)
        if @request.available == true
          @request.available = false
        end
        @request.save
      end
    

    This effectively sets the request to 'false' which displays as expected in my request view. Thanks for your help buddy and forcing me to think about this differently. Cheers, my friend.