रेल हैश को वस्तु


147

मेरे पास निम्न वस्तु है जो बनाई गई है

@post = Post.create(:name => 'test', :post_number => 20, :active => true)

एक बार इसे सहेजने के बाद, मैं ऑब्जेक्ट को हैश में वापस लाने में सक्षम होना चाहता हूं, जैसे कि कुछ करके जैसे:

@object.to_hash

रेल के भीतर से यह कैसे संभव है?

जवाबों:


295

यदि आप केवल विशेषताओं की तलाश कर रहे हैं, तो आप उन्हें प्राप्त कर सकते हैं:

@post.attributes

30
लूपिंग, महंगी विधि का उपयोग न करें । As_json
AnkitG

5
.to_jsonयदि मॉडल पूरा नहीं होता है तो DB को क्वेरी करेगा
ykhrustalev

1
के साथ काम करता है joinsऔर select, Person.joins(:address).select("addresses.street, persons.name").find_by_id(id).attributesवापसी करेगा { street: "", name: "" }
2:15 पर जुंग

3
@AnkitG मैं नहीं मानता कि as_json किसी भी कम खर्चीला है। यदि आप स्रोत कोड को देखते हैं as_json, तो यह कॉल करेगा serializable_hash, जो बदले में, कॉल करेगा attributes! तो आपकी सलाह वास्तव में जटिलता की दो परतों को जोड़ attributesरही है, जिससे यह और भी महंगा हो गया है।
सैंड्रे89

2
.as_jsonरूबी हैश के लिए वस्तु को क्रमबद्ध करेगा
1919 को

45

रेल के सबसे हाल के संस्करण में (यह नहीं बता सकता कि कौन सा ठीक है), आप इस 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"
}

बेशक इसका मतलब है कि आपको स्पष्ट रूप से निर्दिष्ट करना होगा कि कौन सी विशेषताएँ प्रदर्शित होनी चाहिए।

उम्मीद है की यह मदद करेगा।

संपादित करें:

इसके अलावा आप हाशिफेबल रत्न की जांच कर सकते हैं ।


ओपी ने JSON के लिए नहीं पूछा, लेकिन एक हैश के लिए।
डेविड हेम्पी

5
@DavidHempy कृपया नीचे उत्तर देने से पहले मेरे उत्तर को अच्छी तरह से पढ़ लें। जैसा कि मेरे उदाहरणों में दिखाया गया है, यह ठीक वैसा ही है जैसा कि #as_json करता है और जिसका उद्देश्य है: api.rubyonrails.org/classes/ActiveModel/Serializers/… । मैंने उस तरीके का नाम नहीं चुना।
रफ

25
@object.as_json

as_json के पास मॉडल संबंधों के अनुसार जटिल वस्तु को कॉन्फ़िगर करने का बहुत लचीला तरीका है

उदाहरण

मॉडल अभियान खरीदारी के अंतर्गत आता है और इसकी एक सूची होती है

मॉडल सूची में कई list_tasks हैं और प्रत्येक list_tasks में कई टिप्पणियां हैं

हम एक जसन प्राप्त कर सकते हैं जो उन सभी डेटा को आसानी से जोड़ती है।

@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 के लिए आधिकारिक दस्तावेज


इसे खोजने से ठीक पहले एक कस्टम फंक्शन बनाया था। वर्ग के लिए एक फ़ंक्शन को परिभाषित करने के बजाय एक एकल-उपयोग विधि की अधिक आवश्यकता थी। किसी कारण से XML क्रमांकन विधियों के साथ काम करने के बाद भी यह याद किया। to_संस्करण लगभग बिल्कुल के रूप में ही काम करने के लिए लगता है as_, संस्करण उद्धृत उत्पादन के लिए छोड़कर। केवल एक चीज जो मुझे पसंद नहीं थी, वह मेरे फ़िल्टर मानदंडों के क्रम को संरक्षित नहीं करना था। ऐसा लगता है कि वर्णानुक्रम में हल किया गया है। मैंने सोचा था कि मेरे वातावरण में जो भयानक_प्रिंट रत्न है, उससे संबंधित था, लेकिन मुझे नहीं लगता कि ऐसा है।
पिसिस

8

आप एक हैश के रूप में लौटाए गए मॉडल ऑब्जेक्ट की विशेषताओं को प्राप्त कर सकते हैं

@post.attributes

या

@post.as_json

as_jsonआपको संघों और उनकी विशेषताओं को शामिल करने की अनुमति देता है और निर्दिष्ट करता है कि कौन सी विशेषताओं को शामिल करना / बहिष्कृत करना है ( प्रलेखन देखें )। हालाँकि, यदि आपको केवल आधार ऑब्जेक्ट की विशेषताओं की आवश्यकता है, तो रूबी 2.2.3 और रेल 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)

as_json डेटाबेस क्वेरी को फिर से कॉल करेगा, यदि आप मेथो में शामिल होने के साथ नेस्टेड रिज़ॉर्ट चला रहे हैं
टोनी Hsieh

6

यहाँ कुछ बेहतरीन सुझाव दिए गए हैं।

मुझे लगता है कि यह ध्यान देने योग्य है कि आप ActiveRecord मॉडल को हैश की तरह मान सकते हैं:

@customer = Customer.new( name: "John Jacob" )
@customer.name    # => "John Jacob"
@customer[:name]  # => "John Jacob"
@customer['name'] # => "John Jacob"

इसलिए, विशेषताओं के हैश उत्पन्न करने के बजाय, आप ऑब्जेक्ट को हैश के रूप में उपयोग कर सकते हैं।


6

आप सभी विशेषताओं को वापस करने के लिए निश्चित रूप से विशेषताओं का उपयोग कर सकते हैं, लेकिन आप पोस्ट करने के लिए एक इंस्टेंस विधि जोड़ सकते हैं, इसे "to_hash" कह सकते हैं और यह एक हैश में आपके द्वारा पसंद किए गए डेटा को वापस कर देगा। कुछ इस तरह

def to_hash
 { name: self.name, active: true }
end

2

यकीन नहीं होता है कि क्या आप की जरूरत है, लेकिन रूबी कंसोल में यह कोशिश:

h = Hash.new
h["name"] = "test"
h["post_number"] = 20
h["active"] = true
h

जाहिर है यह आपको सांत्वना में एक हैश लौटाएगा। अगर आप किसी विधि के भीतर से हैश लौटना चाहते हैं - तो "h" के बजाय "वापसी 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

पोस्टर Rails में ActiveRecord मॉडल के बारे में पूछ रहा है।
जेफरी हैरिंगटन


0

स्वानंद का जवाब बहुत अच्छा है।

यदि आप FactoryGirl का उपयोग कर रहे हैं, तो आप buildकुंजी के बिना विशेषता हैश उत्पन्न करने के लिए इसकी विधि का उपयोग कर सकते हैं id। जैसे

build(:post).attributes

0

पुराना सवाल, लेकिन भारी संदर्भ ... मुझे लगता है कि ज्यादातर लोग अन्य तरीकों का उपयोग करते हैं, लेकिन एक to_hashविधि है, इसे सही तरीके से सेटअप करना है। आमतौर पर, प्लक 4 के बाद एक बेहतर जवाब होता है ... इसका मुख्य रूप से जवाब देना क्योंकि मुझे इस धागे को खोजने के लिए एक गुच्छा खोजना पड़ा या कुछ भी उपयोगी और दूसरों को मानने से एक ही समस्या आ रही है ...

नोट: हर किसी के लिए यह सिफारिश नहीं है, लेकिन किनारे के मामले!


माणिक पर रेल से एपि ... 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"},
      ...
     ] ...
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.