我正在尝试学习如何使用Rails 5(通常),但具体来说,我试图学习如何使用服务类。
我正在尝试编写一个服务类,该服务类将用户的给定电子邮件地址(用户具有名为:email的属性)映射到组织的域名。组织具有名为:email_format的属性。我使用该属性来保存" @"。
之后的电子邮件地址部分当用户创建帐户时,我想要使用他们用来注册的电子邮件地址,并将@之后的位与我所知道的每个组织匹配,并尝试找到匹配的组织。< / p>
我对此的尝试显然是错误的,但我正在努力弄清楚原因。
我有称为User,Organization和OrgRequest的资源。协会是:
用户
belongs_to :organisation, optional: true
has_one :org_request
组织
has_many :org_requests
has_many :users
OrgRequest
belongs_to :user
belongs_to :organisation
我曾尝试将服务类编写为:
class User::OrganisationMapperService #< ActiveRecord::Base
def self.call(user: u)
new(user: user).call
end
def initialize(user: u)
self.user = user
end
def call
if matching_organisation.present?
# user.organisation_request.new(organisation_id: matching_organisation.id)
# user.update_attributes!(organisation_id: matching_organisation.id)
else
#SystemMailer.unmatched_organisation(user: user).deliver_now
end
end
private
attr_accessor :user
def matching_organisation
# User::OrganisationMapperService.new(user).matching_organisation
User::OrganisationMapperService.new(user: user)
end
end
然后我有一个组织请求控制器:
class Users::OrgRequestsController < ApplicationController
before_action :authenticate_user!, except: [:new, :create, :requested]
before_action :set_org_request, only: [:approved, :rejected, :removed]
# skip_before_action :redirect_for_unrequested_organisation
# skip_before_action :redirect_for_unknown_organisation
def index
organisation = Organisation.find_by(owner_id: current_user.id)
return redirect_to(user_path(current_user.id)) if organisation.nil?
@org_requests = organisation.org_requests
end
def new
@all_organisations = Organisation.select(:title, :id).map { |org| [org.title, org.id] }
@org_request = OrgRequest.new#form(OrganisationRequest::Create)
matched_organisation = User::OrganisationMapperService.new(current_user).matching_organisation
@org_request.organisation_id = matched_organisation.try(:id)
end
def create
@org_request = OrgRequest.new(org_request_params)
@org_request.user_id = current_user.id
if @org_request.save
OrgRequest::ProcessService.new(org_request).process
return redirect_to(user_path(current_user),
flash[:alert] => 'Your request is being processed.')
else
# Failure scenario below
@all_organisations = Organisation.select(:title, :id).map { |org| [org.title, org.id] }
render :new
end
end
def requested
# Need help - if this is contained in form inputs - how do i stop from overriding the submit path?
redirect_to(user_path(current_user))
#not sure about this - a similar redirect isnt required for articles or project create
end
def approve
@org_request = current_user.organisation.org_requests.find(params[:id])
if @org_request.state_machine.transition_to!(:approved)
flash[:notice] = "You've added this member."
redirect_to org_requests_path
else
flash[:error] = "You're not able to manage this organisation's members"
redirect_to :index
end
end
def remove
@org_request = current_user.organisation.org_requests.find(params[:id])
if @org_request.state_machine.transition_to!(:removed)
flash[:notice] = "Removed from the organisation."
redirect_to action: :index
# format.html { redirect_to :index }
# format.json { render :show, status: :ok, location: @project }
# redirect_to action: :show, id: project_id
# add mailer to send message to article owner that article has been approved
else
flash[:error] = "You're not able to manage this organisation's members"
redirect_to(user_path(current_user))
# redirect_to action: :show, id: project_id
end
end
def decline
@org_request = current_user.organisation.org_requests.find(params[:id])
if @org_request.state_machine.transition_to!(:declined)
flash[:notice] = "You're not eligible to join this organisation"
redirect_to action: :index
# redirect_back(fallback_location: root_path)
# format.html { redirect_to :index }
# redirect_to action: :show, id: organisation_request.profile
# add mailer to send message to article owner that article has been approved
else
flash[:error] = "You're not able to manage this organisation's members"
redirect_to(user_path(current_user))
# redirect_to action: :show, id: organisation_request.profile
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_org_request
@org_request = OrgRequest.find(params[:id])
authorize @org_request
end
# Never trust parameters from the scary internet, only allow the white list through.
def org_request_params
params.require(:org_request).permit(:organisation_id, :name) # Need help - not sure if I need to put user id and organisation id in this permission
end
end
我无法找到另一种方法。当我尝试这个时,我收到了这个错误:
wrong number of arguments (given 1, expected 0)
错误消息突出显示了我的服务类的第7行,其中包含:
def initialize(user: u)
self.user = user
end
我之前在这里询问过有关此问题的问题:superclass mismatch for class User - inheriting from ActiveRecord::Base
但我还没有设法抓住建议的偏差或导致问题的原因。这个尝试混合了我从至少10个不同的教程中收集到的建议 - 所以我很欣赏它极不可能是正确的,但是我很难理解这个工作的不同部分如何知道该怎么做尝试不同。
有人能指导我如何尝试推进此尝试吗?
组织映射器装饰器具有:
class User < ActiveRecord::Base
class OrganisationMapper < ::ApplicationDecorator
def matching_organisation
@matching_organisation ||= Organisation.by_email_format(email_format).first
end
def email_format
user.email.split('@').last
end
private
def user
@model
end
end
end
应用程序装饰器有:
class ApplicationDecorator
def initialize(model)
@model = model
end
private
def method_missing(method, *args)
args.empty? ? @model.send(method) : @model.send(method, *args)
end
end
组织请求服务类具有:
class OrgRequest::CreateService < ActiveRecord::Base
attr_accessor :org_request
def self.call(user_id: user_id, organisation_id: org_id)
new(user_id: user_id, organisation_id: organisation_id).call
end
def initialize(user_id: user_id, organisation_id: org_id)
self.user_id = user_id
self.organisation_id = organisation_id
end
def call
self.org_request \
= OrgRequest.new(user_id: current_user.id,
organisation_id: params[:org_request][:organisation_id])
if org_request.save
# send the email
true
else
false
end
end
end
下次尝试
我已经尝试了我能想到的每一个变化。我尝试的任何事情对我都没有任何意义,但我可以从任何我能找到的例子中理解。
我的服务类目前有:
class User::OrganisationMapperService #< ActiveRecord::Base
def self.call(user: u)
new(user: user).call
end
def initialize(user: u)
self.user = user
end
def call
# if matching_organisation.present?
# user.org_request.new(organisation_id: matching_organisation.id)
# if found create a request for that user to enter the organisation
if match_domain.present?
OrgRequest.create(user: @user, organisation_id: @organisation_domain.organisation.id) #if organisation
# user.update_attributes!(organisation_id: matching_organisation.id)
else
#SystemMailer.unmatched_organisation(user: user).deliver_now
end
end
private
attr_accessor :user
# def matching_organisation
# # User::OrganisationMapperService.new(user).matching_organisation
# User::OrganisationMapperService.new(user: user).Organisation.by_email_format(email_format).first
# end
# def matching_organisation
# @matching_organisation ||= Organisation.by_email_format(email_format).first
# end
def user_domain
user.email.split('@').last
end
def organisation_domain
@organisation = Organisation.find_by(email_format: user_domain)
end
# def user_email_domain
# # extract domain from users email
# user_email_domain = @user.email.split('@').last
# end
def match_domain
return unless @user_domain == @organisation.email_format
end
# find an organisation with a matching domain
# end
end
显然是错的。错误消息显示:
NameError - undefined local variable or method `organisation' for #<User::OrganisationMapperService:0x007faec6ec06b8>
我无法理解错误信息,因为我已经把&#39; @&#39;在每个组织的实例面前#39;只是试图让这个错误消失。它没有。
请帮忙。
另一个完全无法发送的错误消息
我又尝试编写方法来检查电子邮件域是否与我服务类中的组织电子邮件格式相匹配。
调用方法现在有:
def call
if user_domain == Organisation.email_format.any?
OrgRequest.create(user: @user, organisation_id: @organisation_domain.organisation.id) #if organisation
else
end
end
控制台中的错误消息显示:
NoMethodError - undefined method `email_format' for #<Class:0x007faec72d8ac0>
这必须是无稽之谈,因为我的组织表中有一个名为:email_format的属性。在控制台中,我可以写:
o = Organisation.first.email_format
Organisation Load (3.3ms) SELECT "organisations".* FROM "organisations" ORDER BY "organisations"."id" ASC LIMIT $1 [["LIMIT", 1]]
这给了我正在寻找的结果。
我尝试(以我的智慧结束)了解rails如何通信。我无法理解其中任何一个。
下次尝试
接下来猜测调用方法:
def call
if user_domain == organisation_domain?
OrgRequest.create(user: @user, organisation_id: @organisation_domain.organisation.id) #if organisation
else
end
产生此错误:
NoMethodError - undefined method `organisation_domain?' for #<User::OrganisationMapperService:0x007faec3be3600>:
我似乎无法找到不会产生此错误的单一表达形式。
答案 0 :(得分:0)
问题似乎在以下一行:
matched_organisation = User::OrganisationMapperService.new(current_user).matching_organisation
应该是这样:
matched_organisation = User::OrganisationMapperService.new(user: current_user).matching_organisation
答案 1 :(得分:0)
我有一个关于代码导师的会议。这就是答案。我希望它可以帮助其他想要学习的人。
Bar