2009-05-24 23 views
18

Próbuję przekonwertować wartość ciągu na nazwę atrybutu należącego do obiektu. Na przykład w poniższym kodzie, potrzebuję wszystkich wartości ciągu w column_array przekształconych w nazwy atrybutów. Nazwy "student_identification", "email", itp. Są rzeczywistymi nazwami kolumn mojej tabeli Student. W rzeczywistym scenariuszu użytkownik ustawi column_array (zaznaczając pola wyboru). I new_array zostanie zastąpiony przez csv, ponieważ chcę dane przenieść do pliku csv.Jak przekonwertować ciąg znaków na nazwę atrybutu obiektu?

W tej chwili jestem naprawdę borykają się następujący wiersz:

new_array << r."#{column_array[i]}" 

Chcę "#{column_array[i]}" zostać przekształcony nazwy atrybutu, więc mogę uzyskać dostęp do danych.

def exp_tst 

    @records = Student.find(:all, :conditions=> session[:selection_scope], 
           :order => sort_order('laboratory_id')) 

    column_array = ["student_identification", "laboratory_id", "email", "current_status"] 

    new_array = Array.new() 

    @records.each do |r| 

    (0..(column_array.size-1)).each do |i| 
     new_array << r."#{column_array[i]}" 
    end 
    end 

end 
+0

'(0 .. (column_array.size -1)) każdy może być zastąpiony przez 'column_array.each_index'. –

Odpowiedz

39

Załóżmy na przykład column_array[i] = "foo".

Jeśli chcesz wywołać metodę r.foo użyć Object#send:

r.send(column_array[i], arg1, arg2, arg3, ...) 

Jeśli chcesz uzyskać dostęp do r „s instancję zmiennej @foo, użyj Object#instance_variable_get i Object#instance_variable_set:

r.instance_variable_get('@'+column_array[i]) 
r.instance_variable_set('@'+column_array[i], new_value) 

W w tym przypadku musimy poprzedzić podaną nazwę znakiem @, ponieważ jest to wymagane w początek wszystkich nazw zmiennych instancji.

Ponieważ jest szyny, a tam całe mnóstwo ActiveRecord magia dzieje się z modeli (i zgaduję Student jest podklasą ActiveRecord::Base) prawdopodobnie chcesz używać tych pierwszych, ponieważ ActiveRecord tworzy metody aby uzyskać dostęp do bazy danych, a wartości przechowywane w zmiennych instancji mogą nie być zgodne z oczekiwaniami.

Użyję przykład z jakiegoś danych testowych mam leżące wokół:

% script/console 
Loading development environment (Rails 2.3.2) 
irb> Customer 
#=> Customer(id: integer, date_subscribed: datetime, rental_plan_id: integer, name: string, address: string, phone_number: string, credit_limit: decimal, last_bill_end_date: datetime, balance: decimal) 
irb> example_customer = Customer.find(:all)[0] 
#=> #<Customer id: 6, date_subscribed: "2007-12-24 05:00:00", rental_plan_id: 3, name: "Evagation Governessy", address: "803 Asbestous St, Uneradicated Stannous MP 37441", phone_number: "(433) 462-3416", credit_limit: #<BigDecimal:191edc0,'0.732E3',4(12)>, last_bill_end_date: "2009-05-15 04:00:00", balance: #<BigDecimal:191e870,'0.743E3',4(12)>> 
irb> example_customer.name 
#=> "Evagation Governessy" 
irb> field = 'name' 
#=> "name" 
irb> example_customer.instance_variable_get(field) 
NameError: `name` is not allowed as an instance variable name 
from (irb):8:in `instance_variable_get` 
from (irb):8 
irb> example_customer.instance_variable_get('@'+field) 
#=> nil 
irb> example_customer.send(field) 
#=> "Evagation Governessy" 
irb> example_customer.send(field+'=', "Evagation Governessy Jr.") 
#=> "Evagation Governessy Jr." 
irb> example_customer.send(field) 
#=> "Evagation Governessy Jr." 
irb> example_customer.name 
#=> "Evagation Governessy Jr." 

więc można zobaczyć, jak #send(field) uzyskuje dostęp do rekordu informacji, a próby uzyskania dostępu do atrybutów nie. Możemy również użyć #send(field+'='), aby zmienić informacje dotyczące zapisu.

+0

Witam, tak Uczeń jest podklasą klasy "ActiveRecord :: Base" uczeń klasy Vicer

+1

Dostęp do zawartości kolumn za pomocą metod dostępowych w ActiveRecord. W języku Ruby nie ma pojęcia "tylko nazwy kolumn". – Chuck

+0

Witam, Po prostu spraw, aby problem stał się trochę bardziej zaawansowany. Załóżmy, że Twój obiekt 'example_customer' ma metodę o nazwie get_details_of_membership ('membership_type') ". Tutaj "typ członkostwa" może być "platynowy", "roczny", "miesięczny" itp. Ale jeśli użyłem tego polecenia: przyklad_customer.send ('get_details_of_membership (' platinum ')') , nie będzie praca. rzeczywiście chcę zapisać 'get_details_of_membership ciąg (' platynę ')' w zmiennej jak: polu = 'get_details_of_membership (' platyna ')' a następnie wykonaj: example_customer.send (pole) Czy ktoś pokaż mi sposób na rozwiązanie tego problemu? – Vicer

4

spojrzenie na metody instance_eval ...

jeśli masz 'atrybut' i trzeba zrobić

object.attribute = 'ololo' 

można zrobić:

object.instance_eval('attribute') = 'ololo' 
Powiązane problemy