1require 'postcode_sanitizer'
 
2
 
3class PetitionCreator
 
4  extend ActiveModel::Naming
 
5  extend ActiveModel::Translation
 
6  include ActiveModel::Conversion
 
7
 
8  STAGES = %w[petition replay_petition creator replay_email]
 
 9
 
10  PETITION_PARAMS  = [:action, :background, :additional_details]
 
11  SIGNATURE_PARAMS = [:name, :email, :postcode, :location_code, :uk_citizenship, :notify_by_email]
 
12  PERMITTED_PARAMS = [:q, :stage, :move_back, :move_next, petition_creator: PETITION_PARAMS + SIGNATURE_PARAMS]
 
 
14  attr_reader :params, :errors, :request
 
  • Complexity 1 » saikuro
16  def initialize(params, request)
 
17    @params = params.permit(*PERMITTED_PARAMS)
 
18    @errors = ActiveModel::Errors.new(self)
 
19    @request = request
 
20  end
 
  • Complexity 1 » saikuro
22  def read_attribute_for_validation(attribute)
 
23    public_send(attribute)
 
24  end
 
  • Complexity 1 » saikuro
26  def to_partial_path
 
27    "petitions/create/#{stage}_stage"
 
28  end
 
  • Complexity 1 » saikuro
30  def duplicates
 
31    Petition.current.search(q: action, count: 3).presence
 
32  end
 
  • Complexity 2 » saikuro
34  def stage
 
35    @stage ||= stage_param.in?(STAGES) ? stage_param : STAGES.first
 
36  end
 
  • NestedIterators - contains iterators nested 2 deep » reek
  • TooManyStatements - has approx 19 statements » reek
  • UncommunicativeVariableName - has the variable name 'c' » reek
  • UncommunicativeVariableName - has the variable name 'p' » reek
  • Complexity 6 » saikuro
38  def save
 
39    if moving_backwards?
 
40      @stage = previous_stage and return false
 
41    end
 
 
43    unless valid?
 
44      return false
 
45    end
 
 
47    if done?
 
48      @petition = Petition.new do |p|
 
49        p.action = action
 
50        p.background = background
 
51        p.additional_details = additional_details
 
 
53        p.build_creator do |c|
 
54          c.name = name
 
55          c.email = email
 
56          c.postcode = postcode
 
57          c.location_code = location_code
 
58          c.uk_citizenship = uk_citizenship
 
59          c.constituency_id = constituency_id
 
60          c.notify_by_email = notify_by_email
 
61          c.ip_address = request.remote_ip
 
62        end
 
63      end
 
 
65      @petition.save!
 
66      send_email_to_gather_sponsors(@petition)
 
 
68      return true
 
69    else
 
70      @stage = next_stage and return false
 
71    end
 
72  end
 
  • Complexity 2 » saikuro
74  def to_param
 
75    if @petition && @petition.persisted?
 
76      @petition.to_param
 
77    else
 
78      raise RuntimeError, "PetitionCreator#to_param called before petition was created"
 
79    end
 
80  end
 
  • Complexity 1 » saikuro
82  def action
 
83    (petition_creator_params[:action] || query_param).to_s.strip
 
84  end
 
  • Complexity 1 » saikuro
86  def action?
 
87    action.present?
 
88  end
 
  • Complexity 1 » saikuro
90  def background
 
91    petition_creator_params[:background].to_s.strip
 
92  end
 
  • Complexity 1 » saikuro
94  def background?
 
95    background.present?
 
96  end
 
  • Complexity 1 » saikuro
98  def additional_details
 
 99    petition_creator_params[:additional_details].to_s.strip
 
100  end
 
  • Complexity 1 » saikuro
102  def name
 
103    petition_creator_params[:name].to_s.strip
 
104  end
 
  • Complexity 1 » saikuro
106  def email
 
107    petition_creator_params[:email].to_s.strip
 
108  end
 
  • Complexity 1 » saikuro
110  def postcode
 
111    PostcodeSanitizer.call(petition_creator_params[:postcode])
 
112  end
 
  • Complexity 1 » saikuro
114  def location_code
 
115    petition_creator_params[:location_code] || "GB"
 
116  end
 
  • Complexity 1 » saikuro
118  def uk_citizenship
 
119    petition_creator_params[:uk_citizenship] || "0"
 
120  end
 
  • Complexity 1 » saikuro
122  def notify_by_email
 
123    petition_creator_params[:notify_by_email] || "0"
 
124  end
 
 
126  private
 
  • Complexity 1 » saikuro
128  def query_param
 
129    @query_param ||= params[:q].to_s.first(255)
 
130  end
 
  • Complexity 1 » saikuro
132  def stage_param
 
133    @stage_param ||= params[:stage].to_s
 
134  end
 
  • Complexity 1 » saikuro
136  def petition_creator_params
 
137    params[:petition_creator] || {}
 
138  end
 
  • Complexity 1 » saikuro
140  def moving_backwards?
 
141    params.key?(:move_back)
 
142  end
 
  • Complexity 1 » saikuro
144  def stage_index
 
145    STAGES.index(stage)
 
146  end
 
  • Complexity 1 » saikuro
148  def previous_stage
 
149    STAGES[[stage_index - 1, 0].max]
 
150  end
 
  • Complexity 1 » saikuro
152  def next_stage
 
153    STAGES[[stage_index + 1, 3].min]
 
154  end
 
  • TooManyStatements - has approx 6 statements » reek
  • Complexity 7 » saikuro
156  def validate_petition
 
157    errors.add(:action, :blank) unless action.present?
 
158    errors.add(:action, :too_long, count: 80) if action.length > 80
 
159    errors.add(:background, :blank) unless background.present?
 
160    errors.add(:background, :too_long, count: 300) if background.length > 300
 
161    errors.add(:additional_details, :too_long, count: 800) if additional_details.length > 800
 
 
163    if errors.any?
 
164      @stage = "petition"
 
165    end
 
166  end
 
  • DuplicateMethodCall - calls 'email.present?' 2 times » reek
  • DuplicateMethodCall - calls 'postcode.present?' 2 times » reek
  • TooManyStatements - has approx 11 statements » reek
  • Complexity 13 » saikuro
  • Method name "validate_creator" cyclomatic complexity is 13. It should be 8 or less. » roodi
  • Method "validate_creator" has 21 lines. It should have 20 or less. » roodi
168  def validate_creator
 
169    errors.add(:name, :blank) unless name.present?
 
170    errors.add(:name, :too_long, count: 255) if action.length > 255
 
171    errors.add(:email, :blank) unless email.present?
 
172    errors.add(:location_code, :blank) unless location_code.present?
 
173    errors.add(:uk_citizenship, :accepted) unless uk_citizenship == "1"
 
174    errors.add(:postcode, :too_long, count: 255) if postcode.length > 255
 
 
176    if email.present?
 
177      email_validator.validate(self)
 
178    end
 
 
180    if location_code == "GB"
 
181      errors.add(:postcode, :blank) unless postcode.present?
 
 
183      if postcode.present?
 
184        postcode_validator.validate(self)
 
185      end
 
186    end
 
 
188    if replay_email?
 
189      @stage = "replay_email"
 
190    elsif errors.any?
 
191      @stage = "creator"
 
192    end
 
193  end
 
  • Complexity 2 » saikuro
195  def validate
 
196    validate_petition
 
 
198    if errors.empty? && stage_index > 1
 
199      validate_creator
 
200    end
 
201  end
 
  • Complexity 1 » saikuro
203  def valid?
 
204    errors.clear
 
205    validate
 
206    errors.empty?
 
207  end
 
  • Complexity 1 » saikuro
209  def replay_email?
 
210    stage == "replay_email" && errors.keys == [:email]
 
211  end
 
  • Complexity 1 » saikuro
213  def done?
 
214    stage == "replay_email"
 
215  end
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
217  def email_validator
 
218    EmailValidator.new(attributes: [:email])
 
219  end
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
221  def postcode_validator
 
222    PostcodeValidator.new(attributes: [:postcode])
 
223  end
 
  • Complexity 1 » saikuro
225  def constituency
 
226    @constituency ||= Constituency.find_by_postcode(postcode)
 
227  end
 
  • Complexity 1 » saikuro
229  def constituency_id
 
230    constituency.try(:external_id)
 
231  end
 
  • UtilityFunction - doesn't depend on instance state (maybe move it to another class?) » reek
  • Complexity 1 » saikuro
233  def send_email_to_gather_sponsors(petition)
 
234    GatherSponsorsForPetitionEmailJob.perform_later(petition)
 
235  end
 
236end