PageRenderTime 82ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 3ms

/text/src/test/resources/examples/ruby/rails4.in.rb

https://github.com/rimolive/core
Ruby | 15296 lines | 9112 code | 1840 blank | 4344 comment | 628 complexity | b0245bf2875f2473b31162a1cc38de04 MD5 | raw file
Possible License(s): EPL-1.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. require 'mail'
  2. require 'action_mailer/collector'
  3. require 'active_support/core_ext/string/inflections'
  4. require 'active_support/core_ext/hash/except'
  5. require 'active_support/core_ext/module/anonymous'
  6. require 'action_mailer/log_subscriber'
  7. module ActionMailer
  8. # Action Mailer allows you to send email from your application using a mailer model and views.
  9. #
  10. # = Mailer Models
  11. #
  12. # To use Action Mailer, you need to create a mailer model.
  13. #
  14. # $ rails generate mailer Notifier
  15. #
  16. # The generated model inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods
  17. # used to generate an email message. In these methods, you can setup variables to be used in
  18. # the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments.
  19. #
  20. # class Notifier < ActionMailer::Base
  21. # default from: 'no-reply@example.com',
  22. # return_path: 'system@example.com'
  23. #
  24. # def welcome(recipient)
  25. # @account = recipient
  26. # mail(to: recipient.email_address_with_name,
  27. # bcc: ["bcc@example.com", "Order Watcher <watcher@example.com>"])
  28. # end
  29. # end
  30. #
  31. # Within the mailer method, you have access to the following methods:
  32. #
  33. # * <tt>attachments[]=</tt> - Allows you to add attachments to your email in an intuitive
  34. # manner; <tt>attachments['filename.png'] = File.read('path/to/filename.png')</tt>
  35. #
  36. # * <tt>attachments.inline[]=</tt> - Allows you to add an inline attachment to your email
  37. # in the same manner as <tt>attachments[]=</tt>
  38. #
  39. # * <tt>headers[]=</tt> - Allows you to specify any header field in your email such
  40. # as <tt>headers['X-No-Spam'] = 'True'</tt>. Note, while most fields like <tt>To:</tt>
  41. # <tt>From:</tt> can only appear once in an email header, other fields like <tt>X-Anything</tt>
  42. # can appear multiple times. If you want to change a field that can appear multiple times,
  43. # you need to set it to nil first so that Mail knows you are replacing it and not adding
  44. # another field of the same name.
  45. #
  46. # * <tt>headers(hash)</tt> - Allows you to specify multiple headers in your email such
  47. # as <tt>headers({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'})</tt>
  48. #
  49. # * <tt>mail</tt> - Allows you to specify email to be sent.
  50. #
  51. # The hash passed to the mail method allows you to specify any header that a Mail::Message
  52. # will accept (any valid Email header including optional fields).
  53. #
  54. # The mail method, if not passed a block, will inspect your views and send all the views with
  55. # the same name as the method, so the above action would send the +welcome.text.erb+ view
  56. # file as well as the +welcome.text.html.erb+ view file in a +multipart/alternative+ email.
  57. #
  58. # If you want to explicitly render only certain templates, pass a block:
  59. #
  60. # mail(to: user.email) do |format|
  61. # format.text
  62. # format.html
  63. # end
  64. #
  65. # The block syntax is also useful in providing information specific to a part:
  66. #
  67. # mail(to: user.email) do |format|
  68. # format.text(content_transfer_encoding: "base64")
  69. # format.html
  70. # end
  71. #
  72. # Or even to render a special view:
  73. #
  74. # mail(to: user.email) do |format|
  75. # format.text
  76. # format.html { render "some_other_template" }
  77. # end
  78. #
  79. # = Mailer views
  80. #
  81. # Like Action Controller, each mailer class has a corresponding view directory in which each
  82. # method of the class looks for a template with its name.
  83. #
  84. # To define a template to be used with a mailing, create an <tt>.erb</tt> file with the same
  85. # name as the method in your mailer model. For example, in the mailer defined above, the template at
  86. # <tt>app/views/notifier/welcome.text.erb</tt> would be used to generate the email.
  87. #
  88. # Variables defined in the model are accessible as instance variables in the view.
  89. #
  90. # Emails by default are sent in plain text, so a sample view for our model example might look like this:
  91. #
  92. # Hi <%= @account.name %>,
  93. # Thanks for joining our service! Please check back often.
  94. #
  95. # You can even use Action Pack helpers in these views. For example:
  96. #
  97. # You got a new note!
  98. # <%= truncate(@note.body, length: 25) %>
  99. #
  100. # If you need to access the subject, from or the recipients in the view, you can do that through message object:
  101. #
  102. # You got a new note from <%= message.from %>!
  103. # <%= truncate(@note.body, length: 25) %>
  104. #
  105. #
  106. # = Generating URLs
  107. #
  108. # URLs can be generated in mailer views using <tt>url_for</tt> or named routes. Unlike controllers from
  109. # Action Pack, the mailer instance doesn't have any context about the incoming request, so you'll need
  110. # to provide all of the details needed to generate a URL.
  111. #
  112. # When using <tt>url_for</tt> you'll need to provide the <tt>:host</tt>, <tt>:controller</tt>, and <tt>:action</tt>:
  113. #
  114. # <%= url_for(host: "example.com", controller: "welcome", action: "greeting") %>
  115. #
  116. # When using named routes you only need to supply the <tt>:host</tt>:
  117. #
  118. # <%= users_url(host: "example.com") %>
  119. #
  120. # You should use the <tt>named_route_url</tt> style (which generates absolute URLs) and avoid using the
  121. # <tt>named_route_path</tt> style (which generates relative URLs), since clients reading the mail will
  122. # have no concept of a current URL from which to determine a relative path.
  123. #
  124. # It is also possible to set a default host that will be used in all mailers by setting the <tt>:host</tt>
  125. # option as a configuration option in <tt>config/application.rb</tt>:
  126. #
  127. # config.action_mailer.default_url_options = { host: "example.com" }
  128. #
  129. # When you decide to set a default <tt>:host</tt> for your mailers, then you need to make sure to use the
  130. # <tt>only_path: false</tt> option when using <tt>url_for</tt>. Since the <tt>url_for</tt> view helper
  131. # will generate relative URLs by default when a <tt>:host</tt> option isn't explicitly provided, passing
  132. # <tt>only_path: false</tt> will ensure that absolute URLs are generated.
  133. #
  134. # = Sending mail
  135. #
  136. # Once a mailer action and template are defined, you can deliver your message or create it and save it
  137. # for delivery later:
  138. #
  139. # Notifier.welcome(david).deliver # sends the email
  140. # mail = Notifier.welcome(david) # => a Mail::Message object
  141. # mail.deliver # sends the email
  142. #
  143. # You never instantiate your mailer class. Rather, you just call the method you defined on the class itself.
  144. #
  145. # = Multipart Emails
  146. #
  147. # Multipart messages can also be used implicitly because Action Mailer will automatically detect and use
  148. # multipart templates, where each template is named after the name of the action, followed by the content
  149. # type. Each such detected template will be added as a separate part to the message.
  150. #
  151. # For example, if the following templates exist:
  152. # * signup_notification.text.erb
  153. # * signup_notification.text.html.erb
  154. # * signup_notification.text.xml.builder
  155. # * signup_notification.text.yaml.erb
  156. #
  157. # Each would be rendered and added as a separate part to the message, with the corresponding content
  158. # type. The content type for the entire message is automatically set to <tt>multipart/alternative</tt>,
  159. # which indicates that the email contains multiple different representations of the same email
  160. # body. The same instance variables defined in the action are passed to all email templates.
  161. #
  162. # Implicit template rendering is not performed if any attachments or parts have been added to the email.
  163. # This means that you'll have to manually add each part to the email and set the content type of the email
  164. # to <tt>multipart/alternative</tt>.
  165. #
  166. # = Attachments
  167. #
  168. # Sending attachment in emails is easy:
  169. #
  170. # class ApplicationMailer < ActionMailer::Base
  171. # def welcome(recipient)
  172. # attachments['free_book.pdf'] = File.read('path/to/file.pdf')
  173. # mail(to: recipient, subject: "New account information")
  174. # end
  175. # end
  176. #
  177. # Which will (if it had both a <tt>welcome.text.erb</tt> and <tt>welcome.text.html.erb</tt>
  178. # template in the view directory), send a complete <tt>multipart/mixed</tt> email with two parts,
  179. # the first part being a <tt>multipart/alternative</tt> with the text and HTML email parts inside,
  180. # and the second being a <tt>application/pdf</tt> with a Base64 encoded copy of the file.pdf book
  181. # with the filename +free_book.pdf+.
  182. #
  183. # If you need to send attachments with no content, you need to create an empty view for it,
  184. # or add an empty body parameter like this:
  185. #
  186. # class ApplicationMailer < ActionMailer::Base
  187. # def welcome(recipient)
  188. # attachments['free_book.pdf'] = File.read('path/to/file.pdf')
  189. # mail(to: recipient, subject: "New account information", body: "")
  190. # end
  191. # end
  192. #
  193. # = Inline Attachments
  194. #
  195. # You can also specify that a file should be displayed inline with other HTML. This is useful
  196. # if you want to display a corporate logo or a photo.
  197. #
  198. # class ApplicationMailer < ActionMailer::Base
  199. # def welcome(recipient)
  200. # attachments.inline['photo.png'] = File.read('path/to/photo.png')
  201. # mail(to: recipient, subject: "Here is what we look like")
  202. # end
  203. # end
  204. #
  205. # And then to reference the image in the view, you create a <tt>welcome.html.erb</tt> file and
  206. # make a call to +image_tag+ passing in the attachment you want to display and then call
  207. # +url+ on the attachment to get the relative content id path for the image source:
  208. #
  209. # <h1>Please Don't Cringe</h1>
  210. #
  211. # <%= image_tag attachments['photo.png'].url -%>
  212. #
  213. # As we are using Action View's +image_tag+ method, you can pass in any other options you want:
  214. #
  215. # <h1>Please Don't Cringe</h1>
  216. #
  217. # <%= image_tag attachments['photo.png'].url, alt: 'Our Photo', class: 'photo' -%>
  218. #
  219. # = Observing and Intercepting Mails
  220. #
  221. # Action Mailer provides hooks into the Mail observer and interceptor methods. These allow you to
  222. # register classes that are called during the mail delivery life cycle.
  223. #
  224. # An observer class must implement the <tt>:delivered_email(message)</tt> method which will be
  225. # called once for every email sent after the email has been sent.
  226. #
  227. # An interceptor class must implement the <tt>:delivering_email(message)</tt> method which will be
  228. # called before the email is sent, allowing you to make modifications to the email before it hits
  229. # the delivery agents. Your class should make any needed modifications directly to the passed
  230. # in Mail::Message instance.
  231. #
  232. # = Default Hash
  233. #
  234. # Action Mailer provides some intelligent defaults for your emails, these are usually specified in a
  235. # default method inside the class definition:
  236. #
  237. # class Notifier < ActionMailer::Base
  238. # default sender: 'system@example.com'
  239. # end
  240. #
  241. # You can pass in any header value that a <tt>Mail::Message</tt> accepts. Out of the box,
  242. # <tt>ActionMailer::Base</tt> sets the following:
  243. #
  244. # * <tt>mime_version: "1.0"</tt>
  245. # * <tt>charset: "UTF-8",</tt>
  246. # * <tt>content_type: "text/plain",</tt>
  247. # * <tt>parts_order: [ "text/plain", "text/enriched", "text/html" ]</tt>
  248. #
  249. # <tt>parts_order</tt> and <tt>charset</tt> are not actually valid <tt>Mail::Message</tt> header fields,
  250. # but Action Mailer translates them appropriately and sets the correct values.
  251. #
  252. # As you can pass in any header, you need to either quote the header as a string, or pass it in as
  253. # an underscored symbol, so the following will work:
  254. #
  255. # class Notifier < ActionMailer::Base
  256. # default 'Content-Transfer-Encoding' => '7bit',
  257. # content_description: 'This is a description'
  258. # end
  259. #
  260. # Finally, Action Mailer also supports passing <tt>Proc</tt> objects into the default hash, so you
  261. # can define methods that evaluate as the message is being generated:
  262. #
  263. # class Notifier < ActionMailer::Base
  264. # default 'X-Special-Header' => Proc.new { my_method }
  265. #
  266. # private
  267. #
  268. # def my_method
  269. # 'some complex call'
  270. # end
  271. # end
  272. #
  273. # Note that the proc is evaluated right at the start of the mail message generation, so if you
  274. # set something in the defaults using a proc, and then set the same thing inside of your
  275. # mailer method, it will get over written by the mailer method.
  276. #
  277. # It is also possible to set these default options that will be used in all mailers through
  278. # the <tt>default_options=</tt> configuration in <tt>config/application.rb</tt>:
  279. #
  280. # config.action_mailer.default_options = { from: "no-reply@example.org" }
  281. #
  282. # = Callbacks
  283. #
  284. # You can specify callbacks using before_action and after_action for configuring your messages.
  285. # This may be useful, for example, when you want to add default inline attachments for all
  286. # messages sent out by a certain mailer class:
  287. #
  288. # class Notifier < ActionMailer::Base
  289. # before_action :add_inline_attachment!
  290. #
  291. # def welcome
  292. # mail
  293. # end
  294. #
  295. # private
  296. #
  297. # def add_inline_attachment!
  298. # attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
  299. # end
  300. # end
  301. #
  302. # Callbacks in ActionMailer are implemented using AbstractController::Callbacks, so you
  303. # can define and configure callbacks in the same manner that you would use callbacks in
  304. # classes that inherit from ActionController::Base.
  305. #
  306. # Note that unless you have a specific reason to do so, you should prefer using before_action
  307. # rather than after_action in your ActionMailer classes so that headers are parsed properly.
  308. #
  309. # = Configuration options
  310. #
  311. # These options are specified on the class level, like
  312. # <tt>ActionMailer::Base.raise_delivery_errors = true</tt>
  313. #
  314. # * <tt>default_options</tt> - You can pass this in at a class level as well as within the class itself as
  315. # per the above section.
  316. #
  317. # * <tt>logger</tt> - the logger is used for generating information on the mailing run if available.
  318. # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.
  319. #
  320. # * <tt>smtp_settings</tt> - Allows detailed configuration for <tt>:smtp</tt> delivery method:
  321. # * <tt>:address</tt> - Allows you to use a remote mail server. Just change it from its default
  322. # "localhost" setting.
  323. # * <tt>:port</tt> - On the off chance that your mail server doesn't run on port 25, you can change it.
  324. # * <tt>:domain</tt> - If you need to specify a HELO domain, you can do it here.
  325. # * <tt>:user_name</tt> - If your mail server requires authentication, set the username in this setting.
  326. # * <tt>:password</tt> - If your mail server requires authentication, set the password in this setting.
  327. # * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the
  328. # authentication type here.
  329. # This is a symbol and one of <tt>:plain</tt> (will send the password in the clear), <tt>:login</tt> (will
  330. # send password Base64 encoded) or <tt>:cram_md5</tt> (combines a Challenge/Response mechanism to exchange
  331. # information and a cryptographic Message Digest 5 algorithm to hash important information)
  332. # * <tt>:enable_starttls_auto</tt> - When set to true, detects if STARTTLS is enabled in your SMTP server
  333. # and starts to use it.
  334. # * <tt>:openssl_verify_mode</tt> - When using TLS, you can set how OpenSSL checks the certificate. This is
  335. # really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name
  336. # of an OpenSSL verify constant ('none', 'peer', 'client_once','fail_if_no_peer_cert') or directly the
  337. # constant (OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER,...).
  338. #
  339. # * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method.
  340. # * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>.
  341. # * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i -t</tt> with <tt>-f sender@address</tt>
  342. # added automatically before the message is sent.
  343. #
  344. # * <tt>file_settings</tt> - Allows you to override options for the <tt>:file</tt> delivery method.
  345. # * <tt>:location</tt> - The directory into which emails will be written. Defaults to the application
  346. # <tt>tmp/mails</tt>.
  347. #
  348. # * <tt>raise_delivery_errors</tt> - Whether or not errors should be raised if the email fails to be delivered.
  349. #
  350. # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default),
  351. # <tt>:sendmail</tt>, <tt>:test</tt>, and <tt>:file</tt>. Or you may provide a custom delivery method
  352. # object e.g. MyOwnDeliveryMethodClass. See the Mail gem documentation on the interface you need to
  353. # implement for a custom delivery agent.
  354. #
  355. # * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you
  356. # call <tt>.deliver</tt> on an mail message or on an Action Mailer method. This is on by default but can
  357. # be turned off to aid in functional testing.
  358. #
  359. # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with
  360. # <tt>delivery_method :test</tt>. Most useful for unit and functional testing.
  361. class Base < AbstractController::Base
  362. include DeliveryMethods
  363. abstract!
  364. include AbstractController::Logger
  365. include AbstractController::Rendering
  366. include AbstractController::Layouts
  367. include AbstractController::Helpers
  368. include AbstractController::Translation
  369. include AbstractController::AssetPaths
  370. include AbstractController::Callbacks
  371. self.protected_instance_variables = [:@_action_has_layout]
  372. helper ActionMailer::MailHelper
  373. private_class_method :new #:nodoc:
  374. class_attribute :default_params
  375. self.default_params = {
  376. mime_version: "1.0",
  377. charset: "UTF-8",
  378. content_type: "text/plain",
  379. parts_order: [ "text/plain", "text/enriched", "text/html" ]
  380. }.freeze
  381. class << self
  382. # Register one or more Observers which will be notified when mail is delivered.
  383. def register_observers(*observers)
  384. observers.flatten.compact.each { |observer| register_observer(observer) }
  385. end
  386. # Register one or more Interceptors which will be called before mail is sent.
  387. def register_interceptors(*interceptors)
  388. interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
  389. end
  390. # Register an Observer which will be notified when mail is delivered.
  391. # Either a class or a string can be passed in as the Observer. If a string is passed in
  392. # it will be <tt>constantize</tt>d.
  393. def register_observer(observer)
  394. delivery_observer = (observer.is_a?(String) ? observer.constantize : observer)
  395. Mail.register_observer(delivery_observer)
  396. end
  397. # Register an Interceptor which will be called before mail is sent.
  398. # Either a class or a string can be passed in as the Interceptor. If a string is passed in
  399. # it will be <tt>constantize</tt>d.
  400. def register_interceptor(interceptor)
  401. delivery_interceptor = (interceptor.is_a?(String) ? interceptor.constantize : interceptor)
  402. Mail.register_interceptor(delivery_interceptor)
  403. end
  404. def mailer_name
  405. @mailer_name ||= anonymous? ? "anonymous" : name.underscore
  406. end
  407. attr_writer :mailer_name
  408. alias :controller_path :mailer_name
  409. def default(value = nil)
  410. self.default_params = default_params.merge(value).freeze if value
  411. default_params
  412. end
  413. # Allows to set defaults through app configuration:
  414. #
  415. # config.action_mailer.default_options = { from: "no-reply@example.org" }
  416. alias :default_options= :default
  417. # Receives a raw email, parses it into an email object, decodes it,
  418. # instantiates a new mailer, and passes the email object to the mailer
  419. # object's +receive+ method. If you want your mailer to be able to
  420. # process incoming messages, you'll need to implement a +receive+
  421. # method that accepts the raw email string as a parameter:
  422. #
  423. # class MyMailer < ActionMailer::Base
  424. # def receive(mail)
  425. # ...
  426. # end
  427. # end
  428. def receive(raw_mail)
  429. ActiveSupport::Notifications.instrument("receive.action_mailer") do |payload|
  430. mail = Mail.new(raw_mail)
  431. set_payload_for_mail(payload, mail)
  432. new.receive(mail)
  433. end
  434. end
  435. # Wraps an email delivery inside of Active Support Notifications instrumentation. This
  436. # method is actually called by the <tt>Mail::Message</tt> object itself through a callback
  437. # when you call <tt>:deliver</tt> on the Mail::Message, calling +deliver_mail+ directly
  438. # and passing a Mail::Message will do nothing except tell the logger you sent the email.
  439. def deliver_mail(mail) #:nodoc:
  440. ActiveSupport::Notifications.instrument("deliver.action_mailer") do |payload|
  441. set_payload_for_mail(payload, mail)
  442. yield # Let Mail do the delivery actions
  443. end
  444. end
  445. def respond_to?(method, include_private = false) #:nodoc:
  446. super || action_methods.include?(method.to_s)
  447. end
  448. protected
  449. def set_payload_for_mail(payload, mail) #:nodoc:
  450. payload[:mailer] = name
  451. payload[:message_id] = mail.message_id
  452. payload[:subject] = mail.subject
  453. payload[:to] = mail.to
  454. payload[:from] = mail.from
  455. payload[:bcc] = mail.bcc if mail.bcc.present?
  456. payload[:cc] = mail.cc if mail.cc.present?
  457. payload[:date] = mail.date
  458. payload[:mail] = mail.encoded
  459. end
  460. def method_missing(method_name, *args)
  461. if respond_to?(method_name)
  462. new(method_name, *args).message
  463. else
  464. super
  465. end
  466. end
  467. end
  468. attr_internal :message
  469. # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
  470. # will be initialized according to the named method. If not, the mailer will
  471. # remain uninitialized (useful when you only need to invoke the "receive"
  472. # method, for instance).
  473. def initialize(method_name=nil, *args)
  474. super()
  475. @_mail_was_called = false
  476. @_message = Mail.new
  477. process(method_name, *args) if method_name
  478. end
  479. def process(*args) #:nodoc:
  480. lookup_context.skip_default_locale!
  481. super
  482. @_message = NullMail.new unless @_mail_was_called
  483. end
  484. class NullMail #:nodoc:
  485. def body; '' end
  486. def method_missing(*args)
  487. nil
  488. end
  489. end
  490. def mailer_name
  491. self.class.mailer_name
  492. end
  493. # Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> object
  494. # which will add them to itself.
  495. #
  496. # headers['X-Special-Domain-Specific-Header'] = "SecretValue"
  497. #
  498. # You can also pass a hash into headers of header field names and values, which
  499. # will then be set on the Mail::Message object:
  500. #
  501. # headers 'X-Special-Domain-Specific-Header' => "SecretValue",
  502. # 'In-Reply-To' => incoming.message_id
  503. #
  504. # The resulting Mail::Message will have the following in its header:
  505. #
  506. # X-Special-Domain-Specific-Header: SecretValue
  507. def headers(args = nil)
  508. if args
  509. @_message.headers(args)
  510. else
  511. @_message
  512. end
  513. end
  514. # Allows you to add attachments to an email, like so:
  515. #
  516. # mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
  517. #
  518. # If you do this, then Mail will take the file name and work out the mime type
  519. # set the Content-Type, Content-Disposition, Content-Transfer-Encoding and
  520. # base64 encode the contents of the attachment all for you.
  521. #
  522. # You can also specify overrides if you want by passing a hash instead of a string:
  523. #
  524. # mail.attachments['filename.jpg'] = {mime_type: 'application/x-gzip',
  525. # content: File.read('/path/to/filename.jpg')}
  526. #
  527. # If you want to use a different encoding than Base64, you can pass an encoding in,
  528. # but then it is up to you to pass in the content pre-encoded, and don't expect
  529. # Mail to know how to decode this data:
  530. #
  531. # file_content = SpecialEncode(File.read('/path/to/filename.jpg'))
  532. # mail.attachments['filename.jpg'] = {mime_type: 'application/x-gzip',
  533. # encoding: 'SpecialEncoding',
  534. # content: file_content }
  535. #
  536. # You can also search for specific attachments:
  537. #
  538. # # By Filename
  539. # mail.attachments['filename.jpg'] # => Mail::Part object or nil
  540. #
  541. # # or by index
  542. # mail.attachments[0] # => Mail::Part (first attachment)
  543. #
  544. def attachments
  545. @_message.attachments
  546. end
  547. # The main method that creates the message and renders the email templates. There are
  548. # two ways to call this method, with a block, or without a block.
  549. #
  550. # Both methods accept a headers hash. This hash allows you to specify the most used headers
  551. # in an email message, these are:
  552. #
  553. # * <tt>:subject</tt> - The subject of the message, if this is omitted, Action Mailer will
  554. # ask the Rails I18n class for a translated <tt>:subject</tt> in the scope of
  555. # <tt>[mailer_scope, action_name]</tt> or if this is missing, will translate the
  556. # humanized version of the <tt>action_name</tt>
  557. # * <tt>:to</tt> - Who the message is destined for, can be a string of addresses, or an array
  558. # of addresses.
  559. # * <tt>:from</tt> - Who the message is from
  560. # * <tt>:cc</tt> - Who you would like to Carbon-Copy on this email, can be a string of addresses,
  561. # or an array of addresses.
  562. # * <tt>:bcc</tt> - Who you would like to Blind-Carbon-Copy on this email, can be a string of
  563. # addresses, or an array of addresses.
  564. # * <tt>:reply_to</tt> - Who to set the Reply-To header of the email to.
  565. # * <tt>:date</tt> - The date to say the email was sent on.
  566. #
  567. # You can set default values for any of the above headers (except :date) by using the <tt>default</tt>
  568. # class method:
  569. #
  570. # class Notifier < ActionMailer::Base
  571. # self.default from: 'no-reply@test.lindsaar.net',
  572. # bcc: 'email_logger@test.lindsaar.net',
  573. # reply_to: 'bounces@test.lindsaar.net'
  574. # end
  575. #
  576. # If you need other headers not listed above, you can either pass them in
  577. # as part of the headers hash or use the <tt>headers['name'] = value</tt>
  578. # method.
  579. #
  580. # When a <tt>:return_path</tt> is specified as header, that value will be used as the 'envelope from'
  581. # address for the Mail message. Setting this is useful when you want delivery notifications
  582. # sent to a different address than the one in <tt>:from</tt>. Mail will actually use the
  583. # <tt>:return_path</tt> in preference to the <tt>:sender</tt> in preference to the <tt>:from</tt>
  584. # field for the 'envelope from' value.
  585. #
  586. # If you do not pass a block to the +mail+ method, it will find all templates in the
  587. # view paths using by default the mailer name and the method name that it is being
  588. # called from, it will then create parts for each of these templates intelligently,
  589. # making educated guesses on correct content type and sequence, and return a fully
  590. # prepared Mail::Message ready to call <tt>:deliver</tt> on to send.
  591. #
  592. # For example:
  593. #
  594. # class Notifier < ActionMailer::Base
  595. # default from: 'no-reply@test.lindsaar.net',
  596. #
  597. # def welcome
  598. # mail(to: 'mikel@test.lindsaar.net')
  599. # end
  600. # end
  601. #
  602. # Will look for all templates at "app/views/notifier" with name "welcome".
  603. # If no welcome template exists, it will raise an ActionView::MissingTemplate error.
  604. #
  605. # However, those can be customized:
  606. #
  607. # mail(template_path: 'notifications', template_name: 'another')
  608. #
  609. # And now it will look for all templates at "app/views/notifications" with name "another".
  610. #
  611. # If you do pass a block, you can render specific templates of your choice:
  612. #
  613. # mail(to: 'mikel@test.lindsaar.net') do |format|
  614. # format.text
  615. # format.html
  616. # end
  617. #
  618. # You can even render text directly without using a template:
  619. #
  620. # mail(to: 'mikel@test.lindsaar.net') do |format|
  621. # format.text { render text: "Hello Mikel!" }
  622. # format.html { render text: "<h1>Hello Mikel!</h1>" }
  623. # end
  624. #
  625. # Which will render a <tt>multipart/alternative</tt> email with <tt>text/plain</tt> and
  626. # <tt>text/html</tt> parts.
  627. #
  628. # The block syntax also allows you to customize the part headers if desired:
  629. #
  630. # mail(to: 'mikel@test.lindsaar.net') do |format|
  631. # format.text(content_transfer_encoding: "base64")
  632. # format.html
  633. # end
  634. #
  635. def mail(headers = {}, &block)
  636. @_mail_was_called = true
  637. m = @_message
  638. # At the beginning, do not consider class default for content_type
  639. content_type = headers[:content_type]
  640. # Call all the procs (if any)
  641. class_default = self.class.default
  642. default_values = class_default.merge(class_default) do |k,v|
  643. v.respond_to?(:to_proc) ? instance_eval(&v) : v
  644. end
  645. # Handle defaults
  646. headers = headers.reverse_merge(default_values)
  647. headers[:subject] ||= default_i18n_subject
  648. # Apply charset at the beginning so all fields are properly quoted
  649. m.charset = charset = headers[:charset]
  650. # Set configure delivery behavior
  651. wrap_delivery_behavior!(headers.delete(:delivery_method),headers.delete(:delivery_method_options))
  652. # Assign all headers except parts_order, content_type and body
  653. assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path)
  654. assignable.each { |k, v| m[k] = v }
  655. # Render the templates and blocks
  656. responses = collect_responses(headers, &block)
  657. create_parts_from_responses(m, responses)
  658. # Setup content type, reapply charset and handle parts order
  659. m.content_type = set_content_type(m, content_type, headers[:content_type])
  660. m.charset = charset
  661. if m.multipart?
  662. m.body.set_sort_order(headers[:parts_order])
  663. m.body.sort_parts!
  664. end
  665. m
  666. end
  667. protected
  668. def set_content_type(m, user_content_type, class_default)
  669. params = m.content_type_parameters || {}
  670. case
  671. when user_content_type.present?
  672. user_content_type
  673. when m.has_attachments?
  674. if m.attachments.detect { |a| a.inline? }
  675. ["multipart", "related", params]
  676. else
  677. ["multipart", "mixed", params]
  678. end
  679. when m.multipart?
  680. ["multipart", "alternative", params]
  681. else
  682. m.content_type || class_default
  683. end
  684. end
  685. # Translates the +subject+ using Rails I18n class under <tt>[mailer_scope, action_name]</tt> scope.
  686. # If it does not find a translation for the +subject+ under the specified scope it will default to a
  687. # humanized version of the <tt>action_name</tt>.
  688. # If the subject has interpolations, you can pass them through the +interpolations+ parameter.
  689. def default_i18n_subject(interpolations = {})
  690. mailer_scope = self.class.mailer_name.tr('/', '.')
  691. I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
  692. end
  693. def collect_responses(headers) #:nodoc:
  694. responses = []
  695. if block_given?
  696. collector = ActionMailer::Collector.new(lookup_context) { render(action_name) }
  697. yield(collector)
  698. responses = collector.responses
  699. elsif headers[:body]
  700. responses << {
  701. body: headers.delete(:body),
  702. content_type: self.class.default[:content_type] || "text/plain"
  703. }
  704. else
  705. templates_path = headers.delete(:template_path) || self.class.mailer_name
  706. templates_name = headers.delete(:template_name) || action_name
  707. each_template(Array(templates_path), templates_name) do |template|
  708. self.formats = template.formats
  709. responses << {
  710. body: render(template: template),
  711. content_type: template.type.to_s
  712. }
  713. end
  714. end
  715. responses
  716. end
  717. def each_template(paths, name, &block) #:nodoc:
  718. templates = lookup_context.find_all(name, paths)
  719. if templates.empty?
  720. raise ActionView::MissingTemplate.new(paths, name, paths, false, 'mailer')
  721. else
  722. templates.uniq { |t| t.formats }.each(&block)
  723. end
  724. end
  725. def create_parts_from_responses(m, responses) #:nodoc:
  726. if responses.size == 1 && !m.has_attachments?
  727. responses[0].each { |k,v| m[k] = v }
  728. elsif responses.size > 1 && m.has_attachments?
  729. container = Mail::Part.new
  730. container.content_type = "multipart/alternative"
  731. responses.each { |r| insert_part(container, r, m.charset) }
  732. m.add_part(container)
  733. else
  734. responses.each { |r| insert_part(m, r, m.charset) }
  735. end
  736. end
  737. def insert_part(container, response, charset) #:nodoc:
  738. response[:charset] ||= charset
  739. part = Mail::Part.new(response)
  740. container.add_part(part)
  741. end
  742. ActiveSupport.run_load_hooks(:action_mailer, self)
  743. end
  744. end
  745. require 'abstract_controller/collector'
  746. require 'active_support/core_ext/hash/reverse_merge'
  747. require 'active_support/core_ext/array/extract_options'
  748. module ActionMailer
  749. class Collector
  750. include AbstractController::Collector
  751. attr_reader :responses
  752. def initialize(context, &block)
  753. @context = context
  754. @responses = []
  755. @default_render = block
  756. end
  757. def any(*args, &block)
  758. options = args.extract_options!
  759. raise ArgumentError, "You have to supply at least one format" if args.empty?
  760. args.each { |type| send(type, options.dup, &block) }
  761. end
  762. alias :all :any
  763. def custom(mime, options = {})
  764. options.reverse_merge!(content_type: mime.to_s)
  765. @context.formats = [mime.to_sym]
  766. options[:body] = block_given? ? yield : @default_render.call
  767. @responses << options
  768. end
  769. end
  770. end
  771. require 'tmpdir'
  772. module ActionMailer
  773. # This module handles everything related to mail delivery, from registering
  774. # new delivery methods to configuring the mail object to be sent.
  775. module DeliveryMethods
  776. extend ActiveSupport::Concern
  777. included do
  778. class_attribute :delivery_methods, :delivery_method
  779. # Do not make this inheritable, because we always want it to propagate
  780. cattr_accessor :raise_delivery_errors
  781. self.raise_delivery_errors = true
  782. cattr_accessor :perform_deliveries
  783. self.perform_deliveries = true
  784. self.delivery_methods = {}.freeze
  785. self.delivery_method = :smtp
  786. add_delivery_method :smtp, Mail::SMTP,
  787. address: "localhost",
  788. port: 25,
  789. domain: 'localhost.localdomain',
  790. user_name: nil,
  791. password: nil,
  792. authentication: nil,
  793. enable_starttls_auto: true
  794. add_delivery_method :file, Mail::FileDelivery,
  795. location: defined?(Rails.root) ? "#{Rails.root}/tmp/mails" : "#{Dir.tmpdir}/mails"
  796. add_delivery_method :sendmail, Mail::Sendmail,
  797. location: '/usr/sbin/sendmail',
  798. arguments: '-i -t'
  799. add_delivery_method :test, Mail::TestMailer
  800. end
  801. module ClassMethods
  802. # Provides a list of emails that have been delivered by Mail::TestMailer
  803. delegate :deliveries, :deliveries=, to: Mail::TestMailer
  804. # Adds a new delivery method through the given class using the given
  805. # symbol as alias and the default options supplied.
  806. #
  807. # add_delivery_method :sendmail, Mail::Sendmail,
  808. # location: '/usr/sbin/sendmail',
  809. # arguments: '-i -t'
  810. def add_delivery_method(symbol, klass, default_options={})
  811. class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
  812. send(:"#{symbol}_settings=", default_options)
  813. self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
  814. end
  815. def wrap_delivery_behavior(mail, method=nil, options=nil) # :nodoc:
  816. method ||= self.delivery_method
  817. mail.delivery_handler = self
  818. case method
  819. when NilClass
  820. raise "Delivery method cannot be nil"
  821. when Symbol
  822. if klass = delivery_methods[method]
  823. mail.delivery_method(klass,(send(:"#{method}_settings") || {}).merge!(options || {}))
  824. else
  825. raise "Invalid delivery method #{method.inspect}"
  826. end
  827. else
  828. mail.delivery_method(method)
  829. end
  830. mail.perform_deliveries = perform_deliveries
  831. mail.raise_delivery_errors = raise_delivery_errors
  832. end
  833. end
  834. def wrap_delivery_behavior!(*args) # :nodoc:
  835. self.class.wrap_delivery_behavior(message, *args)
  836. end
  837. end
  838. end
  839. module ActionMailer
  840. class LogSubscriber < ActiveSupport::LogSubscriber
  841. def deliver(event)
  842. return unless logger.info?
  843. recipients = Array(event.payload[:to]).join(', ')
  844. info("\nSent mail to #{recipients} (#{event.duration.round(1)}ms)")
  845. debug(event.payload[:mail])
  846. end
  847. def receive(event)
  848. return unless logger.info?
  849. info("\nReceived mail (#{event.duration.round(1)}ms)")
  850. debug(event.payload[:mail])
  851. end
  852. def logger
  853. ActionMailer::Base.logger
  854. end
  855. end
  856. end
  857. ActionMailer::LogSubscriber.attach_to :action_mailer
  858. module ActionMailer
  859. module MailHelper
  860. # Take the text and format it, indented two spaces for each line, and
  861. # wrapped at 72 columns.
  862. def block_format(text)
  863. formatted = text.split(/\n\r?\n/).collect { |paragraph|
  864. format_paragraph(paragraph)
  865. }.join("\n\n")
  866. # Make list points stand on their own line
  867. formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" }
  868. formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" }
  869. formatted
  870. end
  871. # Access the mailer instance.
  872. def mailer
  873. @_controller
  874. end
  875. # Access the message instance.
  876. def message
  877. @_message
  878. end
  879. # Access the message attachments list.
  880. def attachments
  881. @_message.attachments
  882. end
  883. # Returns +text+ wrapped at +len+ columns and indented +indent+ spaces.
  884. #
  885. # my_text = 'Here is a sample text with more than 40 characters'
  886. #
  887. # format_paragraph(my_text, 25, 4)
  888. # # => " Here is a sample text with\n more than 40 characters"
  889. def format_paragraph(text, len = 72, indent = 2)
  890. sentences = [[]]
  891. text.split.each do |word|
  892. if sentences.first.present? && (sentences.last + [word]).join(' ').length > len
  893. sentences << [word]
  894. else
  895. sentences.last << word
  896. end
  897. end
  898. sentences.map { |sentence|
  899. "#{" " * indent}#{sentence.join(' ')}"
  900. }.join "\n"
  901. end
  902. end
  903. end
  904. require "action_mailer"
  905. require "rails"
  906. require "abstract_controller/railties/routes_helpers"
  907. module ActionMailer
  908. class Railtie < Rails::Railtie # :nodoc:
  909. config.action_mailer = ActiveSupport::OrderedOptions.new
  910. config.eager_load_namespaces << ActionMailer
  911. initializer "action_mailer.logger" do
  912. ActiveSupport.on_load(:action_mailer) { self.logger ||= Rails.logger }
  913. end
  914. initializer "action_mailer.set_configs" do |app|
  915. paths = app.config.paths
  916. options = app.config.action_mailer
  917. options.assets_dir ||= paths["public"].first
  918. options.javascripts_dir ||= paths["public/javascripts"].first
  919. options.stylesheets_dir ||= paths["public/stylesheets"].first
  920. # make sure readers methods get compiled
  921. options.asset_host ||= app.config.asset_host
  922. options.relative_url_root ||= app.config.relative_url_root
  923. ActiveSupport.on_load(:action_mailer) do
  924. include AbstractController::UrlFor
  925. extend ::AbstractController::Railties::RoutesHelpers.with(app.routes)
  926. include app.routes.mounted_helpers
  927. register_interceptors(options.delete(:interceptors))
  928. register_observers(options.delete(:observers))
  929. options.each { |k,v| send("#{k}=", v) }
  930. end
  931. end
  932. initializer "action_mailer.compile_config_methods" do
  933. ActiveSupport.on_load(:action_mailer) do
  934. config.compile_methods! if config.respond_to?(:compile_methods!)
  935. end
  936. end
  937. end
  938. end
  939. require 'active_support/test_case'
  940. module ActionMailer
  941. class NonInferrableMailerError < ::StandardError
  942. def initialize(name)
  943. super "Unable to determine the mailer to test from #{name}. " +
  944. "You'll need to specify it using tests YourMailer in your " +
  945. "test case definition"
  946. end
  947. end
  948. class TestCase < ActiveSupport::TestCase
  949. module Behavior
  950. extend ActiveSupport::Concern
  951. include ActiveSupport::Testing::ConstantLookup
  952. include TestHelper
  953. included do
  954. class_attribute :_mailer_class
  955. setup :initialize_test_deliveries
  956. setup :set_expected_mail
  957. end
  958. module ClassMethods
  959. def tests(mailer)
  960. case mailer
  961. when String, Symbol
  962. self._mailer_class = mailer.to_s.camelize.constantize
  963. when Module
  964. self._mailer_class = mailer
  965. else
  966. raise NonInferrableMailerError.new(mailer)
  967. end
  968. end
  969. def mailer_class
  970. if mailer = self._mailer_class
  971. mailer
  972. else
  973. tests determine_default_mailer(name)
  974. end
  975. end
  976. def determine_default_mailer(name)
  977. mailer = determine_constant_from_test_name(name) do |constant|
  978. Class === constant && constant < ActionMailer::Base
  979. end
  980. raise NonInferrableMailerError.new(name) if mailer.nil?
  981. mailer
  982. end
  983. end
  984. protected
  985. def initialize_test_deliveries
  986. ActionMailer::Base.delivery_method = :test
  987. ActionMailer::Base.perform_deliveries = true
  988. ActionMailer::Base.deliveries.clear
  989. end
  990. def set_expected_mail
  991. @expected = Mail.new
  992. @expected.content_type ["text", "plain", { "charset" => charset }]
  993. @expected.mime_version = '1.0'
  994. end
  995. private
  996. def charset
  997. "UTF-8"
  998. end
  999. def encode(subject)
  1000. Mail::Encodings.q_value_encode(subject, charset)
  1001. end
  1002. def read_fixture(action)
  1003. IO.readlines(File.join(Rails.root, 'test', 'fixtures', self.class.mailer_class.name.underscore, action))
  1004. end
  1005. end
  1006. include Behavior
  1007. end
  1008. end
  1009. module ActionMailer
  1010. module TestHelper
  1011. # Asserts that the number of emails sent matches the given number.
  1012. #
  1013. # def test_emails
  1014. # assert_emails 0
  1015. # ContactMailer.welcome.deliver
  1016. # assert_emails 1
  1017. # ContactMailer.welcome.deliver
  1018. # assert_emails 2
  1019. # end
  1020. #
  1021. # If a block is passed, that block should cause the specified number of
  1022. # emails to be sent.
  1023. #
  1024. # def test_emails_again
  1025. # assert_emails 1 do
  1026. # ContactMailer.welcome.deliver
  1027. # end
  1028. #
  1029. # assert_emails 2 do
  1030. # ContactMailer.welcome.deliver
  1031. # ContactMailer.welcome.deliver
  1032. # end
  1033. # end
  1034. def assert_emails(number)
  1035. if block_given?
  1036. original_count = ActionMailer::Base.deliveries.size
  1037. yield
  1038. new_count = ActionMailer::Base.deliveries.size
  1039. assert_equal original_count + number, new_count, "#{number} emails expected, but #{new_count - original_count} were sent"
  1040. else
  1041. assert_equal number, ActionMailer::Base.deliveries.size
  1042. end
  1043. end
  1044. # Assert that no emails have been sent.
  1045. #
  1046. # def test_emails
  1047. # assert_no_emails
  1048. # ContactMailer.welcome.deliver
  1049. # assert_emails 1
  1050. # end
  1051. #
  1052. # If a block is passed, that block should not cause any emails to be sent.
  1053. #
  1054. # def test_emails_again
  1055. # assert_no_emails do
  1056. # # No emails should be sent from this block
  1057. # end
  1058. # end
  1059. #
  1060. # Note: This assertion is simply a shortcut for:
  1061. #
  1062. # assert_emails 0
  1063. def assert_no_emails(&block)
  1064. assert_emails 0, &block
  1065. end
  1066. end
  1067. end
  1068. module ActionMailer
  1069. module VERSION #:nodoc:
  1070. MAJOR = 4
  1071. MINOR = 0
  1072. TINY = 0
  1073. PRE = "beta"
  1074. STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
  1075. end
  1076. end
  1077. #--
  1078. # Copyright (c) 2004-2013 David Heinemeier Hansson
  1079. #
  1080. # Permission is hereby granted, free of charge, to any person obtaining
  1081. # a copy of this software and associated documentation files (the
  1082. # "Software"), to deal in the Software without restriction, including
  1083. # without limitation the rights to use, copy, modify, merge, publish,
  1084. # distribute, sublicense, and/or sell copies of the Software, and to
  1085. # permit persons to whom the Software is furnished to do so, subject to
  1086. # the following conditions:
  1087. #
  1088. # The above copyright notice and this permission notice shall be
  1089. # included in all copies or substantial portions of the Software.
  1090. #
  1091. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  1092. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  1093. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  1094. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  1095. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  1096. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  1097. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  1098. #++
  1099. require 'abstract_controller'
  1100. require 'action_view'
  1101. require 'action_mailer/version'
  1102. # Common Active Support usage in Action Mailer
  1103. require 'active_support/rails'
  1104. require 'active_support/core_ext/class'
  1105. require 'active_support/core_ext/module/attr_internal'
  1106. require 'active_support/core_ext/string/inflections'
  1107. require 'active_support/lazy_load_hooks'
  1108. module ActionMailer
  1109. extend ::ActiveSupport::Autoload
  1110. eager_autoload do
  1111. autoload :Collector
  1112. end
  1113. autoload :Base
  1114. autoload :DeliveryMethods
  1115. autoload :MailHelper
  1116. autoload :TestCase
  1117. autoload :TestHelper
  1118. end
  1119. module Rails
  1120. module Generators
  1121. class MailerGenerator < NamedBase
  1122. source_root File.expand_path("../templates", __FILE__)
  1123. argument :actions, type: :array, default: [], banner: "method method"
  1124. check_class_collision
  1125. def create_mailer_file
  1126. template "mailer.rb", File.join('app/mailers', class_path, "#{file_name}.rb")
  1127. end
  1128. hook_for :template_engine, :test_framework
  1129. end
  1130. end
  1131. end
  1132. <% module_namespacing do -%>
  1133. class <%= class_name %> < ActionMailer::Base
  1134. default from: "from@example.com"
  1135. <% actions.each do |action| -%>
  1136. # Subject can be set in your I18n file at config/locales/en.yml
  1137. # with the following lookup:
  1138. #
  1139. # en.<%= file_path.tr("/",".") %>.<%= action %>.subject
  1140. #
  1141. def <%= action %>
  1142. @greeting = "Hi"
  1143. mail to: "to@example.org"
  1144. end
  1145. <% end -%>
  1146. end
  1147. <% end -%>
  1148. module AbstractController
  1149. module AssetPaths #:nodoc:
  1150. extend ActiveSupport::Concern
  1151. included do
  1152. config_accessor :asset_host, :assets_dir, :javascripts_dir,
  1153. :stylesheets_dir, :default_asset_host_protocol, :relative_url_root
  1154. end
  1155. end
  1156. end
  1157. require 'erubis'
  1158. require 'set'
  1159. require 'active_support/configurable'
  1160. require 'active_support/descendants_tracker'
  1161. require 'active_support/core_ext/module/anonymous'
  1162. module AbstractController
  1163. class Error < StandardError #:nodoc:
  1164. end
  1165. class ActionNotFound < StandardError #:nodoc:
  1166. end
  1167. # <tt>AbstractController::Base</tt> is a low-level API. Nobody should be
  1168. # using it directly, and subclasses (like ActionController::Base) are
  1169. # expected to provide their own +render+ method, since rendering means
  1170. # different things depending on the context.
  1171. class Base
  1172. attr_internal :response_body
  1173. attr_internal :action_name
  1174. attr_internal :formats
  1175. include ActiveSupport::Configurable
  1176. extend ActiveSupport::DescendantsTracker
  1177. undef_method :not_implemented
  1178. class << self
  1179. attr_reader :abstract
  1180. alias_method :abstract?, :abstract
  1181. # Define a controller as abstract. See internal_methods for more
  1182. # details.
  1183. def abstract!
  1184. @abstract = true
  1185. end
  1186. def inherited(klass) # :nodoc:
  1187. # define the abstract ivar on subclasses so that we don't get
  1188. # uninitialized ivar warnings
  1189. unless klass.instance_variable_defined?(:@abstract)
  1190. klass.instance_variable_set(:@abstract, false)
  1191. end
  1192. super
  1193. end
  1194. # A list of all internal methods for a controller. This finds the first
  1195. # abstract superclass of a controller, and gets a list of all public
  1196. # instance methods on that abstract class. Public instance methods of
  1197. # a controller would normally be considered action methods, so methods
  1198. # declared on abstract classes are being removed.
  1199. # (ActionController::Metal and ActionController::Base are defined as abstract)
  1200. def internal_methods
  1201. controller = self
  1202. controller = controller.superclass until controller.abstract?
  1203. controller.public_instance_methods(true)
  1204. end
  1205. # The list of hidden actions. Defaults to an empty array.
  1206. # This can be modified by other modules or subclasses
  1207. # to specify particular actions as hidden.
  1208. #

Large files files are truncated, but you can click here to view the full file