Rails切换属性动态

时间:2015-11-13 19:27:47

标签: jquery ruby-on-rails mongodb

我试图切换用户属性而不为我要切换的每个属性创建单独的方法:

  def toggle
    item = params[:item]
    id   = params[:id]
    @user = User.find(id)
    respond_to do |format|
      if @user.update("#{item}": !@user."#{item}")
        flash[:success] = "Success!"
        format.js {render template: "admin/toggle_admin"}
      else
        flash[:error] = "Problem toggling"
      end
    end
  end

我认为这只是一个语法问题。这显然不会起作用......但是如何在属性动态的情况下切换用户的属性?

此外,这是一个好主意,还是可以切换任何类的属性?这将允许我使用一种方法通过app普遍使用jquery开关。

2 个答案:

答案 0 :(得分:0)

以下是如何做到这一点

  1. 如果您想使用任何值更新动态属性,那么

    respond_to do |format|
    
        if @user.respond_to? item
            @user.send("#{item}=", value)
            @user.save
    
            flash[:success] = "Success!"
            format.js {render template: "admin/toggle_admin"}
        else
            flash[:error] = "Problem toggling"
        end
    end 
    
  2. 如果您只想切换布尔值,例如从false切换到true,反之亦然

    respond_to do |format|
    
        if @user.respond_to? item
            @user.toggle(item)
            @user.save
    
            flash[:success] = "Success!"
            format.js {render template: "admin/toggle_admin"}
        else
            flash[:error] = "Problem toggling"
        end
    end
    
  3. 如果你正在使用mongoid,你可以做

    @user.update_attribute item.to_sym, !@user[item.to_sym]
    
  4. 这也应该有用

    @user[item] = !@user[item]
    @user.save
    

答案 1 :(得分:0)

首先,我将此切换逻辑移动到模型中,如果要在不同的模型中使用它,可以将其抽象为模块。您只需将参数传递给方法即可完成所需的动态行为。例如:

class User

  def toggle(attribute)
    current_value = self.send(attribute)
    self.update_attribute!("#{attribute}", !current_value)
  end

end

从控制器中你可以调用@ user.toggle('foo')并进行切换,如果失败则抛出异常。

如果命名方法更适合您的JQuery开关,您可以尝试一些元编程:

class User
  SWITCHES = %w(foo bar baz)

  SWITCHES.each do |switch|
    define_method("toggle_#{switch}") do
      toggle("#{switch}") 
    end
  end

  private

  def toggle(attribute)
    current_value = self.send(attribute)
    self.update_attribute!("#{attribute}", !current_value)
  end
end

对于User类的每个实例,将为您指定为开关的每个属性创建一个方法。它们都有共同的功能,因此我抽象了一个每个人都称之为的私有方法。

从控制器中你可以调用@ user.toggle_foo并进行切换。

根据您想要的链接,这是控制器的外观:

class ToggleUserController

  def update
    @user = User.find(params[:user_id])
    if @user.toggle(params[:switch])
      flash[:success] = "Success!"
      redirect_to @user
    else
      flash[:error] = "Problem toggling"
    end
  end
end

你的路线:

patch ":user_id/relevant_path", to: "toggle_user#update", as: :toggle_user_path

链接:

link_to "Foo", toggle_user_path(@user, switch: 'foo'), method: :patch

你可能应该:

  • 防止意外切换非布尔属性
  • 确保为布尔值指定默认值,因为此代码不会对nil
  • 执行任何操作