什么var类型从另一个控制器动态访问Model的属性? (Rails 4.2)

时间:2016-08-22 20:08:21

标签: ruby-on-rails ruby

enter image description here目标:当cards_controller运行def update操作时,从Controller(cards_controller.rb)动态更新另一个Model的属性(Tracker)。

我收到错误:CardsController#update中的NameError,它调出了第二行的最后一行 def update_tracker(card_attribute):

updated_array = @tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, @card.(eval(card_attribute.to_s))]

感知问题:除了在使用动态属性时我不知道正确“调用”Tracker属性的适当方法时,我已经完成了所有工作。

Tracker的属性是一个数组(使用PG作为db工作正常),我想

  1. 找出哪些属性已被更改(有效)
  2. 从Tracker的模型中读取相应的属性数组,并从中创建一个局部变量。 (我觉得有效),
  3. 将一个新数组推送到本地var。这个新数组包含datetime(现在)和一个字符串(带有更新的Card字符串的值)(有效)
  4. 使用正确的属性更新了跟踪器。
  5. 使用cards_controller.rb中的以下代码

    • 更新方法中的if @card.deck.tracked使进程启动

    cards_controller.rb

    ...
        def update
            @card = Card.find(params[:id])
            if @card.deck.tracked
                detect_changes
            end
            if @card.update_attributes(card_params)
                if @card.deck.tracked
                    prop_changed?
                end
                flash[:success] = "Card info updated."
                respond_to do |format|
                    format.html { render 'show' }
                end
            else
                render 'edit'
            end
        end
    ...
    private
            def detect_changes
                @changed = []
                @changed << :front if @card.front != params[:card][:front]
                @changed << :hint if @card.hint != params[:card][:hint]
                @changed << :back if @card.back != params[:card][:back]
            end
    
    def prop_changed?
        @changed.each do |check|
            @changed.include? check
            puts "Following property has been changed : #{check}"
            update_tracker(check)
        end
    end
    
    def update_tracker(card_attribute)
        tracker_attribute =  case card_attribute
        when :front; :front_changed
        when :back; :back_changed
        when :hint; :hint_changed
        end
        string_tracker_column = tracker_attribute.to_s
        @tracker ||= Tracker.find_by(card_id: @card.id)
        updated_array = @tracker.instance_variable_get("#{string_tracker_column}")[Time.zone.now, @card.(eval(card_attribute.to_s))]
        @tracker.update_attribute(tracker_attribute, updated_array)
    end
    

    修改:为了清晰起见,这里是app / models / tracker.rb:

    class Tracker < ActiveRecord::Base
        belongs_to :card
    end
    

2 个答案:

答案 0 :(得分:1)

从您的错误看,您的问题似乎是:

@tracker.instance_variable_get("#{string_tracker_column}")

在字符串插值后计算结果:

 @tracker.instance_variable_get("front_changed")

这是instance_variable_get的错误使用。它需要@前置:

 @tracker.instance_variable_get("@front_changed")

如果在Tracker模型上设置instance_variable_get,则似乎不需要使用attr_reader :front_changed

答案 1 :(得分:1)

您对instance_variable_get的使用已得到纠正,但是这种方法注定会失败,因为ActiveRecord列值不会存储为单个实例变量。

您可以使用

@tracker[string_column_changed]
@card[card_attribute]

按名称检索属性值。如果您想获得关联,请使用public_send。如果存在包含列值的访问器(例如载波),后者也很有用