Ответ 1
Если вы ищете только атрибуты, вы можете получить их:
@post.attributes
У меня есть следующий объект, который был создан
@post = Post.create(:name => 'test', :post_number => 20, :active => true)
Как только это будет сохранено, я хочу, чтобы вернуть объект к хешу, например. делая что-то вроде:
@object.to_hash
Как это возможно изнутри рельсов?
Если вы ищете только атрибуты, вы можете получить их:
@post.attributes
В самой последней версии Rails (не могу сказать, какой именно), вы можете использовать метод as_json
:
@post = Post.first
hash = @post.as_json
puts hash.pretty_inspect
Будет выводиться:
{
:name => "test",
:post_number => 20,
:active => true
}
Чтобы идти немного дальше, вы можете переопределить этот метод, чтобы настроить способ отображения ваших атрибутов, выполнив что-то вроде этого:
class Post < ActiveRecord::Base
def as_json(*args)
{
:name => "My name is '#{self.name}'",
:post_number => "Post ##{self.post_number}",
}
end
end
Затем, с тем же экземпляром, что и выше, выведет:
{
:name => "My name is 'test'",
:post_number => "Post #20"
}
Это, конечно, означает, что вам нужно явно указать, какие атрибуты должны появиться.
Надеюсь, что это поможет.
EDIT:
Также вы можете проверить Hashifiable gem.
@object.as_json
as_json имеет очень гибкий способ настройки сложного объекта в соответствии с модельными отношениями
Пример
Модель кампании принадлежит магазину и имеет один список
В списке есть list_tasks, и у каждого из list_tasks есть много комментариев
Мы можем получить один json, который легко объединяет все эти данные.
@campaign.as_json(
{
except: [:created_at, :updated_at],
include: {
shop: {
except: [:created_at, :updated_at, :customer_id],
include: {customer: {except: [:created_at, :updated_at]}}},
list: {
except: [:created_at, :updated_at, :observation_id],
include: {
list_tasks: {
except: [:created_at, :updated_at],
include: {comments: {except: [:created_at, :updated_at]}}
}
}
},
},
methods: :tags
})
Обратите внимание на методы:: теги могут помочь вам подключить любой дополнительный объект, который не имеет отношений с другими. Вам просто нужно определить метод с именем теги в кампании . Этот метод должен возвращать все, что вам нужно (например, Tags.all)
Официальная документация для as_json
Здесь есть несколько замечательных предложений.
Я думаю, стоит отметить, что вы можете рассматривать модель ActiveRecord как хэш, например:
@customer = Customer.new( name: "John Jacob" )
@customer.name # => "John Jacob"
@customer[:name] # => "John Jacob"
@customer['name'] # => "John Jacob"
Следовательно, вместо генерации хэша атрибутов вы можете использовать сам объект как хэш.
Вы можете определенно использовать атрибуты, чтобы возвращать все атрибуты, но вы могли бы добавить метод экземпляра в Post, называть его "to_hash" и вернуть его в хэш. Что-то вроде
def to_hash
{ name: self.name, active: true }
end
Вы можете получить атрибуты объекта модели, возвращенные как хэш, используя
@post.attributes
или
@post.as_json
as_json
позволяет включать ассоциации и их атрибуты, а также указать, какие атрибуты включать/исключать (см. документация). Однако, если вам нужны только атрибуты базового объекта, бенчмаркинг в моем приложении с ruby 2.2.3 и rails 4.2.2 демонстрирует, что attributes
требуется меньше половины времени as_json
.
>> p = Problem.last
Problem Load (0.5ms) SELECT "problems".* FROM "problems" ORDER BY "problems"."id" DESC LIMIT 1
=> #<Problem id: 137, enabled: true, created_at: "2016-02-19 11:20:28", updated_at: "2016-02-26 07:47:34">
>>
>> p.attributes
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> p.as_json
=> {"id"=>137, "enabled"=>true, "created_at"=>Fri, 19 Feb 2016 11:20:28 UTC +00:00, "updated_at"=>Fri, 26 Feb 2016 07:47:34 UTC +00:00}
>>
>> n = 1000000
>> Benchmark.bmbm do |x|
?> x.report("attributes") { n.times { p.attributes } }
?> x.report("as_json") { n.times { p.as_json } }
>> end
Rehearsal ----------------------------------------------
attributes 6.910000 0.020000 6.930000 ( 7.078699)
as_json 14.810000 0.160000 14.970000 ( 15.253316)
------------------------------------ total: 21.900000sec
user system total real
attributes 6.820000 0.010000 6.830000 ( 7.004783)
as_json 14.990000 0.050000 15.040000 ( 15.352894)
не уверен, что вам нужно, но попробуйте это в консоли ruby:
h = Hash.new
h["name"] = "test"
h["post_number"] = 20
h["active"] = true
h
очевидно, он вернет вам хэш в консоли. если вы хотите вернуть хэш из метода - вместо "h" попробуйте использовать "return h.inspect", что-то похожее на:
def wordcount(str)
h = Hash.new()
str.split.each do |key|
if h[key] == nil
h[key] = 1
else
h[key] = h[key] + 1
end
end
return h.inspect
end
Hash [post.attributes.map {| | [a, post [a]]}]
Ответ Swanand велик.
если вы используете FactoryGirl, вы можете использовать его метод build
для генерации хэша атрибута без ключа id
. например.
build(:post).attributes
Старый вопрос, но сильно ссылки... Я думаю, что большинство людей используют другие методы, но есть метод infact a to_hash
, он должен быть настроен правильно. Как правило, pluck - лучший ответ после рельсов 4... отвечающий на это в основном потому, что мне приходилось искать кучу, чтобы найти эту нить или что-нибудь полезное и предположить, что другие сталкиваются с одной и той же проблемой...
Примечание: не рекомендуется для всех, но для случаев с краями!
Из ruby on rails api... http://api.rubyonrails.org/classes/ActiveRecord/Result.html...
This class encapsulates a result returned from calling #exec_query on any database connection adapter. For example:
result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
result # => #<ActiveRecord::Result:0xdeadbeef>
...
# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
{"id" => 2, "title" => "title_2", "body" => "body_2"},
...
] ...