क्या रैलिंग हेल्पिंग हेल्पर्स (यानी mymodel_path (मॉडल)) को मॉडल्स में इस्तेमाल किया जा सकता है?


368

कहते हैं मेरे पास एक रेलिंग मॉडल है जिसे थिंग कहा जाता है। थिंग में एक url विशेषता है जो वैकल्पिक रूप से इंटरनेट पर किसी URL पर सेट की जा सकती है। कोड देखने में, मुझे तर्क की आवश्यकता है जो निम्न कार्य करता है:

<% if thing.url.blank? %>
<%= link_to('Text', thing_path(thing)) %>
<% else %>
<%= link_to('Text', thing.url) %>
<% end %>

देखने में यह सशर्त तर्क बदसूरत है। बेशक, मैं एक सहायक समारोह का निर्माण कर सकता हूं, जो इस के लिए दृश्य को बदल देगा:

<%= thing_link('Text', thing) %>

यह वर्बोसिटी समस्या को हल करता है, लेकिन मैं वास्तव में मॉडल में ही कार्यक्षमता होना पसंद करूंगा। किस स्थिति में, दृश्य कोड होगा:

<%= link_to('Text', thing.link) %>

यह, जाहिर है, मॉडल पर एक लिंक विधि की आवश्यकता होगी। यहां यह है कि इसमें क्या शामिल होगा:

def link
  (self.url.blank?) ? thing_path(self) : self.url
end

प्रश्न के बिंदु तक, thing_path () मॉडल कोड के अंदर एक अपरिभाषित विधि है। मैं मान रहा हूँ कि मॉडल में कुछ सहायक विधियों को "खींचना" संभव है, लेकिन कैसे? और क्या कोई वास्तविक कारण है कि रूटिंग केवल ऐप के कंट्रोलर और व्यू लेयर्स पर काम करता है? मैं बहुत सारे मामलों के बारे में सोच सकता हूं जहां मॉडल कोड को यूआरएल (बाहरी प्रणालियों के साथ एकीकरण, आदि) से निपटने की आवश्यकता हो सकती है।


एक उपयोग मामला यह होगा: aftersave में goo.gl से छोटा url उत्पन्न करने के लिए,
lulalala

2
यदि आप व्यू लॉजिक को जोड़ना चाहते हैं, तो आपको शायद एक प्रस्तोता में मॉडल लपेटना चाहिए, इससे एमवीसी की परतें अलग रहेंगी। ड्रेपर देखें ( github.com/jcasimir/draper )।
क्रिस

जवाबों:


698

रेल 3, 4, और 5 में आप उपयोग कर सकते हैं:

Rails.application.routes.url_helpers

जैसे

Rails.application.routes.url_helpers.posts_path
Rails.application.routes.url_helpers.posts_url(:host => "example.com")

14
Ypu इसे किसी भी मॉड्यूल में शामिल कर सकता है और इसके बाद आप url-helpers तक पहुँच सकते हैं। Thx
वायाचेस्लाव मोलोकोव

41
अपने आप को :hostहर जगह अपने विकल्प को कॉपी करने से बचाएं और इसे एक बार अपने पर्यावरण के विन्यास फाइल में सेट करें:Rails.application.routes.default_url_options[:host] = 'localhost:3000'
एंड्रयू

5
include Rails.application.routes.url_helpersमेरे लिए काम करता है रेल 4.1
Jan

1
यदि आपको केवल उस पथ की आवश्यकता है जो आप उपयोग कर सकते हैं: only_path => मेजबान पैरामीटर को पारित किए बिना एक विकल्प के रूप में सच है।
सचिनविसो

1
यह अच्छा विकल्प प्रतीत होता है: hawkins.io/2012/03/…
Renars Sirotins

182

मुझे यह करने के बारे में जवाब मिल गया है कि यह कैसे करना है। मॉडल कोड के अंदर, बस:

रेल के लिए <= 2:

include ActionController::UrlWriter

रेल के लिए 3:

include Rails.application.routes.url_helpers

यह जादुई रूप से thing_path(self)वर्तमान चीज़ के लिए URL लौटाता है, या other_model_path(self.association_to_other_model)कोई अन्य URL लौटाता है।


27
बस एक अपडेट, क्योंकि ऊपर लिखा हुआ है। यह वर्तमान में शामिल हैं:include Rails.application.routes.url_helpers
yalestar

2
मैं (# के लिए अपरिभाषित विधि `optimize_routes_generation '<ActionView :: आधार: 0x007fe8c0eecbd0>?) NoMethodError जब मैं यह कोशिश
moger777

118

आपको प्रत्येक विधि को शामिल करने की तुलना में निम्नलिखित दृष्टिकोण क्लीनर भी मिल सकता है:

class Thing
  delegate :url_helpers, to: 'Rails.application.routes' 

  def url
    url_helpers.thing_path(self)
  end
end

7
इस पर प्रलेखन कठिन लग रहा था, इसलिए यहां ActiveSupport में प्रतिनिधि के उपयोग के संबंध में एक सभ्य लिंक है। simonecarletti.com/blog/2009/12/inside-ruby-on-rails-delegate
tlbrack

2
मुझे एक undefined local variable or method 'url_helpers' for Event:Classत्रुटि मिलती है ... :(
अगस्टिन रिडिंगर

मुझे मिलता है undefined method url_helpers। मैं क्या करने वाला हूँ?
asiniy

@asiniy, क्या आप सुनिश्चित हैं कि आपने url_helpers के लिए प्रतिनिधि विकल्प का उपयोग किया है जो वर्ग घोषणा के बाद लिखा गया है?
Krzysztof Witczak

काम नहीं करता है, लेकिन यह हो सकता है कि यह केवल तभी काम करता है जब आप अपना निर्माण करते हैं class, जैसा कि उत्तर में दिखाया गया है। यदि आपका मॉडल वर्ग पहले से ही विस्तारित है तो < ApplicationRecordयह काम नहीं करेगा?
skplunkerin

13

दृश्य में प्रदर्शित होने वाले किसी भी तर्क के साथ एक सहायक विधि को सौंपा जाना चाहिए, क्योंकि डेटा को संभालने के लिए मॉडल में तरीके कड़ाई से हैं।

यहाँ आप क्या कर सकते हैं:

# In the helper...

def link_to_thing(text, thing)
  (thing.url?) ? link_to(text, thing_path(thing)) : link_to(text, thing.url)
end

# In the view...

<%= link_to_thing("text", @thing) %>

1
मुझे इस मामले में सहायक विधियों के बारे में क्या पसंद नहीं है: जब मैं link_to_thing () को देखता हूं, तो मुझे यह तय करना होगा कि क्या यह एक विशिष्ट-विशिष्ट या एप्लिकेशन-वाइड सहायक है (यह आसानी से हो सकता है)। मुझे स्रोत के लिए 2 फ़ाइलों की जांच करने पर विचार करने की आवश्यकता है। source.link स्रोत फ़ाइल के बारे में कोई प्रश्न नहीं छोड़ता है।
एरोन लोंगवेल

इसके अलावा, क्या होगा अगर मुझे इस कार्यशीलता को एक रेक कार्य में उपयोग करने की आवश्यकता है (चीज URL का CSV फ़ाइल शायद निर्यात करने के लिए) ... सीधे मॉडल पर जाना उस मामले में भी बेहतर होगा।
एरोन लोंगवेल

लेकिन अंतर यह है कि link_to मॉडल में उपलब्ध नहीं होगा, क्योंकि यह एक ActionView सहायक है। तो, यह काम नहीं करेगा। आप मॉडल में कुछ विशेषता डिफॉल्ट्स को हैक कर सकते हैं, इसलिए यदि यह सेट नहीं है, तो यह किसी चीज़ को डिफॉल्ट करता है, लेकिन यह आपके ऊपर है।
जोश डेल्समैन

12
वेब सेवाओं के एपीआई बढ़ने के साथ, कई बार मॉडल को अपने स्वयं के डेटा के साथ बाहरी संसाधनों से संपर्क करने और कॉलबैक URL प्रदान करने की आवश्यकता होती है। उदाहरण के लिए, एक फोटो ऑब्जेक्ट को सोशलमॉड पर पोस्ट करने की आवश्यकता है, जो मॉडरेशन किए जाने पर उस फोटो के URL पर वापस कॉल करेगा। After_create () हुक का अर्थ सोशलमॉड पर पोस्ट करना होगा, लेकिन आप कॉलबैक URL को कैसे जानते हैं? मुझे लगता है कि लेखक का खुद का जवाब अच्छा है।
जेसनस्मिथ

3
जब भी आप कड़ाई से तकनीकी अर्थों में सही होते हैं, ऐसे समय होते हैं जब लोगों को हर याक को दाढ़ी के बिना काम करने के लिए चीजों की आवश्यकता होती है, कुछ पवित्र डिजाइन पैटर्न का उल्लंघन करने से बचने के लिए या आपके पास क्या है, हो सकता है कि उन्हें url प्राप्त करने की आवश्यकता हो, और वास्तव में संग्रहीत करें डेटाबेस में, तब यह आसान होगा कि एक मॉडल के लिए सिर्फ यह जानना है कि आगे और पीछे की चीजों को पारित करने के बजाय, कभी-कभी नियमों को तोड़ा जा सकता है।
नाइटकेडर

2

मैं वास्तव में स्वच्छ समाधान का पालन करना पसंद करता हूं।

class Router
  include Rails.application.routes.url_helpers

  def self.default_url_options
    ActionMailer::Base.default_url_options
  end
end

router = Router.new
router.posts_url  # http://localhost:3000/posts
router.posts_path # /posts

यह http://hawkins.io/2012/03/generating_urls_whenever_and_wherever_you_want/ से है


1

हालांकि एक ऐसा तरीका हो सकता है कि मैं उस तरह के तर्क को मॉडल से बाहर रखना चाहूंगा। मैं मानता हूं कि आपको इसे नज़र में नहीं रखना चाहिए ( इसे पतला रखना ) लेकिन जब तक मॉडल नियंत्रक को डेटा के एक टुकड़े के रूप में एक यूआरएल नहीं लौटा रहा है, रूटिंग सामान नियंत्रक में होना चाहिए।


4
पुन: "जब तक मॉडल डेटा के एक टुकड़े के रूप में URL वापस नहीं कर रहा है"। ठीक वैसा ही यहां हो रहा है ... मॉडल डेटा के इस टुकड़े का "मालिक" है, जो या तो ऑन-साइट या ऑफ-साइट यूआरएल का लिंक है। कुछ मामलों में URL रेल रूटिंग से उत्पन्न होता है। अन्य मामलों में, URL उपयोगकर्ता द्वारा प्रदत्त डेटा है।
एरोन लोंगवेल

0

(संपादित करें: मेरे पिछले बच्चे को भूल जाओ ...)

ठीक है, ऐसी परिस्थितियाँ हो सकती हैं जहाँ आप या तो मॉडल या किसी अन्य यूआरएल पर जाएंगे ... लेकिन मुझे नहीं लगता कि यह मॉडल में है, दृश्य (या शायद मॉडल) अधिक उपयुक्त लगता है।

मार्गों के बारे में, जहां तक ​​मुझे पता है कि मार्ग नियंत्रकों में कार्यों के लिए है (जो आमतौर पर "जादुई रूप से" एक दृश्य का उपयोग करता है), सीधे विचारों के लिए नहीं। नियंत्रक को सभी अनुरोधों को संभालना चाहिए, दृश्य को परिणाम प्रस्तुत करना चाहिए और मॉडल को डेटा को संभालना चाहिए और इसे दृश्य या नियंत्रक को देना चाहिए। मैंने यहां बहुत से लोगों को मॉडल के बारे में बात करते हुए सुना है (इस बिंदु पर मैं इसे शुरू करने के लिए सबसे अधिक शुरुआत कर रहा हूं), लेकिन जैसा कि मैं इसे समझता हूं: मार्ग नियंत्रकों के पास जाते हैं। बेशक बहुत सारे नियंत्रक एक मॉडल के लिए नियंत्रक होते हैं और अक्सर इसे कहा जाता है <modelname>sController(उदाहरण के लिए "UsersController" मॉडल "उपयोगकर्ता" का नियंत्रक है)।

यदि आप अपने आप को एक दृश्य में तर्क की मात्राओं को लिखते हुए पाते हैं, तो तर्क को कहीं अधिक उपयुक्त तरीके से स्थानांतरित करने का प्रयास करें; अनुरोध और आंतरिक संचार तर्क संभवतः नियंत्रक में है, डेटा से संबंधित तर्क को मॉडल में रखा जा सकता है (लेकिन प्रदर्शन तर्क नहीं है, जिसमें लिंक टैग आदि शामिल हैं) और तर्क जो विशुद्ध रूप से प्रदर्शन से संबंधित है उसे सहायक में रखा जाएगा।


मान लें कि आपके पास एक छवि मॉडल है। यदि छवि में इसके साथ संबद्ध बाहरी URL है, तो उस URL को इंगित करें। अन्यथा, छवि अपलोड करने के लिए छवि के शो पृष्ठ पर इंगित करें? एक विचार है।
जोश डेल्समैन

इस कम सामान्य उदाहरण के बारे में कैसे: link_to "पूर्ण आकार छवि", image.link मॉडल में लिंक विधि या तो ऑन-साइट URL (image_path) से लिंक करेगी, या कहें, फ़्लिकर URL यदि उपयोगकर्ता एक प्रदान करता है .url छवि पर सेट किया गया था।
एरोन लोंगवेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.