简体   繁体   中英

RoR: Update attribute in a model from a unrelated controller

I need to pass a value to attribute in a model from a different controller with no direct relation between them. In the below example I need to update farming_year in the Field Model from the Planting controller.

The Field model:

class Field < ApplicationRecord
  has_many :crops
  attr_accessor :farming_year

  def getting_crops
    @crops_list = Crop.select('crops.name').where(field_id: self.id, year: self.get_farming_year) # doesn't get the farming_year 
  end
  def get_farming_year
    @farming_year  # passing the value directly will work @farming_year=2015!!
  end
  def farming_year=(val)
    @farming_year = val # passing the value directly won't work @farming_year=2015!!
  end
end

In the Planting controller:

def new
  @field = Field.new
  @field.farming_year = session[:working_year] 
  @field.save
  flash.now[:success] = @field.get_farming_year # it works and gives the correct year
end

when I changed the @farming_year in the get_farming_year method to @farming_year=2016, then the code will work and will give the correct Crops records. the flash message in the code above without any change will give the correct year from the model. I think my main issue is passing the farming year from get_farming_year method to getting_crops method.

Hint: the framing year is belong to the Crop not to the Field, so I don't need to add it to the Field table.

Any ideas how to achieve that?

Your code has a number of issues.

  1. attr_accessor

    Why are you using an attr_accessor ? You should store the value on a model attribute, in the database. If your Field model doesn't already have a farming_year attribute, create a migration to add it to the database by running these commands:

     $ rails g migration AddFarmingYearToField farming_year:integer $ rails db:migrate 

    If you're running Rails <= 4, use rake db:migrate instead of the second command.

    Doing this means you don't need to use attr_accessor , or define getters and setters.

  2. PlantingController#new

    This method isn't working for you because you haven't defined the correct methods, and you're not saving the instance.

    In your Field model, you've defined a farming_year method, but you haven't defined a farming_year= method, which is what the setter should be. Change your farming_year method definition to farming_year= . Alternatively, use the method I described in 1. , then you won't have to.

Make sure you're saving the model object once you're done with it - call Field#save , which returns truthy on success and falsy on failure; or call Field#save! , which returns truthy on success and raises an exception on failure.

The main issue with my code was using attr_accessor which I didn't need it, so, I've replaced "attr_accessor :farming_year" with a class variable "@@work_year =''", and updated the getter and setter method as in the below code

The Field model:

class Field < ApplicationRecord
 has_many :crops
 attr_accessor :farming_year
 @@work_year =''

 def getting_crops
   @crops_list = Crop.select('crops.name').where(field_id: self.id, year:   farming_year) #now this can request the getter method and get the year
 end
 def farming_year # getter method
   @@work_year ||= ''
 end
 def farming_year=(val) #setter method
   @@work_year = val
 end
end

In the Planting controller:

def new
  @field = Field.new
  @field.farming_year = session[:working_year] 
  #@field.save NO need for this line
  flash.now[:success] = @field.farming_year 
end

Thank you all for your kind support:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM