Четверг, 22 марта 2018 15:48

Active Model. Use validations in model without any DB relations

Оцените материал
(1 Голосовать)

Рассмотрим случай, когда предпочтительно использовать в Rails-приложении именно встроенные валидации Ruby on Rails.

Внимательно читаем этот guide, лучше все равно не расскажешь. Итак, валидации используются, чтобы быть уверенными, что только валидные данные сохраняются в вашу базу данных.

Замечательно, но возникает как минимум один вопрос. Как быть, если для нас нет необходимости сохранять данные в базу данных? Возможно, данные формы, веденные пользователем, должны быть использованы лишь единожды, как использовать валидации Ruby on Rails в этом случае?

 

Active Model. Use validations in model without any DB relations на форуме.

 

Знакомство с темой оптимально начать с материалов форума, описывающих классический пример реализации Rails validation на основе ActiveModel. Здесь же разберем чуть более сложный случай, построив погодный веб-информер, способный получить актуальное состояние погоды по версии OpenWeatherMap - по ID города, введенному в поле формы.

На собственно форме отправки данных здесь останавливаться не будем, сделайте ее тем способом, который посчитаете нужным; хелперы Rails или же simple_form к вашим услугам, сгодится на первых порах и самый обычный HTML. Пример того, как отобразить сообщение о проваленной валидации Active Model на веб-страничке вашего rails-app - также доступен на форуме.

 

Блог на рельсах. Live Demo.

 

Примем, что имя поля формы, посредством которого реализован ввод ID населенного пункта - "request", т.е. name="request". И вот что у нас получилось:

code.rb (или вариант с rescue вместо elsif; там же, по ссылке на форуме)

class FormController < ApplicationController
	include Action
	def weather
		@weather = Form.new(form_params)
		if @weather.valid?
			@lookup = Weather.call([params[:request]].join(","))
			if @lookup.empty?
				flash.now[:error] = 'Error. Invalid ID: ' + params[:request] + '. Data not received. Server response: ' + response.status.to_s
			else
				flash.now[:notice] = 'Success. ID: ' + params[:request] + '. Server response: ' + response.status.to_s
			end
		end    
	end  
	private
	def form_params
		params.permit(:request)
	end
end

 

action.rb

module Action
	extend ActiveSupport::Concern
		class Weather
		include HTTParty
		key_openweathermap = ENV['KEY_OPENWEATHERMAP']
		base_uri 'http://api.openweathermap.org/data/2.5/group?appid=' + key_openweathermap + '&units=metric'
		format :json

		#call the api with HTTParty and parse the JSON response 
		def self.call list_ids
			response = HTTParty.get(base_uri + '&id=' + list_ids)
			body = JSON.parse(response.body)
			# Rails.logger.debug response.body 
			body.fetch('list'){[]}.compact
		end

		#create a hash to store city : temp values 
		def self.make_hash list, value
			hash = Hash.new
			list.each do |l|
				temp = l["main"][value]
				city = l["name"]
				hash[city] = temp
			end
		end

		#create hash with city: cloud cover
		def self.cloud_hash list
			hash = Hash.new
			list.each do |l|
				cloud = l["clouds"]["all"]
				city = l["name"]
				hash[city] = cloud
			end
		end
	end

 

 form.rb

class Form
     include ActiveModel::Model
    attr_accessor :request
    validates :request, presence: true, numericality: { only_integer: true }, length: {in:6..7}
end



Ну вот как-то так. Разумеется, варианты улучшений/исправлений всегда приветствуются.

 
Последнее изменениеПонедельник, 26 сентября 2022 04:09

Оставить комментарий

Добавьте ваш комментарий