2015-12-22 4 views
6

В PHP я могу установить для модели атрибут (который не является столбцом в базе данных). Э.Г. (PHP-код),Установить атрибут без базы данных для модели rails без `attr_accessor`

$user = new User; 
$user.flag = true; 

Но в рельсах, когда я установил какой-либо атрибут, который не существует в базе данных, он выдаст ошибку undefined method flag. Существует метод attr_accessor, но что произойдет, если мне понадобится около десяти атрибутов temp?

+0

Наличие нон колонки атрибуты в объекте - это запах кода, по крайней мере для меня. Здесь что-то связано: https://www.youtube.com/watch?v=SvL_aZt3zyU –

+1

Обычно вы не использовали $ -переменные в рельсах. Вы смешиваете код php и ruby ​​вместе? –

+0

@MaxWilliams Нет, это пример PHP. – sawa

ответ

3

Ожидается, что именно так работает ActiveRecord по дизайну. Если вам нужно установить произвольные атрибуты, вам придется использовать объекты другого типа.

Например, Ruby предоставляет библиотеку под названием OpenStruct, которая позволяет создавать объекты, где вы можете назначить произвольные ключи/значения. Вы можете использовать такую ​​библиотеку, а затем преобразовать объект в соответствующий экземпляр ActiveRecord только в том случае, если/когда вам нужно сохранить базу данных.

Не пытайтесь моделировать ActiveRecord, чтобы вести себя так, как вы только что описали, потому что это было просто не для того, чтобы вести себя таким образом. Это будет ошибка cargo culting из ваших текущих знаний PHP.

+0

Большое спасибо, я никогда не знаю 'OpenStruct' lib, пока вы не сказали мне. Я объединил ваше решение с решением @Nimir и отлично работает: D 'attr_accessor: flag after_initialize do | user | self.flag = OpenStruct.new end' И я могу установить/получить атрибут временного флага с помощью '@user.flag.hello = «Hello World» ' пса: стер, я не знаю, как форматировать код – user3783161

0

Если вам нужны временные атрибуты, вы можете добавить их к объекту singleton.

model = Model.new 

class << model 
    attr_accessor :name 
end 
1

Все, что attr_accessor делает это добавить методы получения и установки, которые используют переменную экземпляра, например, это

attr_accessor :flag 

добавит эти методы:

def flag 
    @flag 
end 

def flag=(val) 
    @flag = val 
end 

Вы можете написать эти методы сами если вы хотите, и попросите их сделать что-то более интересное, чем просто сохранить значение в экземпляре var, если хотите.

2

Как объяснили ребята, attr_accessor - это всего лишь быстрый setter и getter.

Мы можем настроить наш attr_accessor Model на инициализацию записи как Ruby#Hash, например, используя ActiveRecord#After_initilize method, поэтому мы получаем большую гибкость при временном хранении значений (idea credit to this answer).

Что-то вроде:

class User < ActiveRecord::Base 

    attr_accessor :vars 

    after_initialize do |user| 
    self.vars = Hash.new 
    end 

end 

Теперь вы можете сделать:

user = User.new 

#set 
user.vars['flag'] = true 

#get 
user.vars['flag'] 
#> true 
5

, но что произойдет, если мне нужно около десяти атрибутов временные?

#app/models/user.rb 
class User < ActiveRecord::Base 
    attr_accessor :flag, :other_attribute, :other_attribute2, :etc... 
end 

attr_accessor создает в Rails "virtual" attributes - они не существуют в базе данных, но присутствуют в модели.

Как с атрибутами из БД, attr_accessor только создает набор setter & getter (экземпляр) в своем классе, который можно назвать & взаимодействовать с при инициализации класса:

#app/models/user.rb 
class User < ActiveRecord::Base 
    attr_accessor :flag 

    # getter 
    def flag 
    @flag 
    end 

    # setter 
    def flag=(val) 
    @flag = val 
    end 
end 
Смежные вопросы