class PageRecord::Base

Attributes

id[R]
id?[R]

Public Class Methods

add_attributes(extra_attributes) click to toggle source

Add some new attributes to the already availabe attributes

@param extra_attributes [Array] The additional attributes the page regognises

Example:

“‘ruby class TopDivisonPage < PageRecord::Base

add_attributes [:full_name, :address_line]

end “‘

# File lib/page_record/base.rb, line 178
def self.add_attributes(extra_attributes)
  @attributes.concat(extra_attributes)
  # TODO: check if we can optimise this to only add the new methods
  define_class_methods(self)
  define_instance_methods(self)
  @attributes
end
attributes(new_attributes = nil) click to toggle source

Set’s the attributes this page recognises. This will override any types inherited from the host class. When you don’t specify a parameter, or a nil parameter .attributes will return the current set of attributes

@param new_attributes [Array] The attributes the page regognises

@return [Array] returns the array of attributes the page recognises Example:

“‘ruby class TopDivisonPage < PageRecord::Base

attributes [:name, :position, :ranking]

end “‘

# File lib/page_record/base.rb, line 153
def self.attributes(new_attributes = nil)
  if new_attributes
    undefine_class_methods(self)
    undefine_instance_methods(self)
    @attributes = new_attributes
    define_class_methods(self)
    define_instance_methods(self)
  end
  @attributes
end
filter(new_filter = nil) click to toggle source

Set’s the default filter for this class

Example:

“‘ruby class TeamPage < PageRecord::Base

filter ".champions-league"

end “‘

@param new_filter [String] The default filter to be used for all finders

# File lib/page_record/base.rb, line 66
def self.filter(new_filter = nil)
  @filter = new_filter if new_filter
  @filter
end
host_class(new_host_class = nil) click to toggle source

Set’s the page host class

@param new_host_class an ActiveRecord like class

@return [Class]

# File lib/page_record/base.rb, line 102
def self.host_class (new_host_class = nil)
  if new_host_class
    @host_class = new_host_class
    @host_name =  new_host_class.to_s
    @type = @host_name.underscore
    get_attribute_names
    define_class_methods(self)
    define_instance_methods(self)
  end
  @host_class
end
inherited(base) click to toggle source

@private

# File lib/page_record/base.rb, line 72
def self.inherited(base)
  base.class_eval do
    set_type_name(base)
    get_attribute_names
  end
  define_class_methods(base)
  define_instance_methods(base)
end
new(id = nil, selector = nil, filter = nil) click to toggle source
# File lib/page_record/base.rb, line 13
def initialize(id = nil, selector = nil, filter = nil)
  @page = self.class.page
  @type = self.class.instance_variable_get('@type')
  @id = id.to_i if id 
  find_record(selector, filter)
end
page(new_page = nil) click to toggle source

Set’s the page {PageRecord::Base} uses for all page operations. when no parameter is given or the parameter is nil, just return the current value

@param new_page [Cabybara::Session] The Capybara page

@return [Capybara::Session]

rubocop:disable AvoidClassVars:

# File lib/page_record/base.rb, line 90
def self.page (new_page = nil)
  new_page ? @@page = new_page : @@page
end
selector(new_selector = nil) click to toggle source

Set’s the default selector for this class

Example:

“‘ruby class TeamPage < PageRecord::Base

selector "#first-table"

end “‘ @param new_selector [String] The default selector to be used for all finders

# File lib/page_record/base.rb, line 47
def self.selector(new_selector = nil)
  @selector = new_selector if new_selector
  @selector
end
type(new_type = nil) click to toggle source

Set’s the default type for this class

@param new_type [Symbol] The default type to be used for all finders. If type is nil just return the current type

@return [Symbol] the type set.

Example:

“‘ruby class TopDivisonPage < PageRecord::Base

type :team

end

TopDivisonPage.type # returns :team “‘

# File lib/page_record/base.rb, line 132
def self.type(new_type = nil)
  new_type ? @type = new_type : @type
end

Private Class Methods

context_for_selector(selector) click to toggle source

@private

# File lib/page_record/base.rb, line 269
def self.context_for_selector(selector)
  if selector.blank?
    page
  else
    begin
      page.find(selector)
    rescue Capybara::Ambiguous
      raise MultipleRecords, "Found multiple HTML segments with selector #{selector} on page"
    rescue Capybara::ElementNotFound
      raise RecordNotFound, "#{selector} not found on page"
    end
  end
end
define_accessor_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 207
def self.define_accessor_methods(base)
  base.instance_eval do
    @attributes.each do | attribute |
      define_method("#{attribute}?") do
        read_attribute?(attribute)
      end
      define_method(attribute) do
        read_attribute(attribute)
      end
      define_method("#{attribute}=") do | value|
        write_attribute(attribute, value)
      end
    end
  end
end
define_class_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 245
def self.define_class_methods(base)
  eigenclass = class << base; self; end
  attributes = base.instance_variable_get('@attributes')
  eigenclass.instance_eval do
    attributes.each do | attribute|
      define_method "find_by_#{attribute}" do | value, selector = '', filter = ''|
        find_by_attribute(attribute, value, selector, filter)
      end
    end
  end
end
define_instance_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 235
def self.define_instance_methods(base)
  define_accessor_methods(base)
end
get_attribute_names() click to toggle source

@private

# File lib/page_record/base.rb, line 199
def self.get_attribute_names
  @attributes = @host_class.attribute_names.clone
  @attributes.delete('id') # id is a special case attribute
  rescue NameError
    @attributes = []
end
set_type_name(base) click to toggle source

@private

# File lib/page_record/base.rb, line 189
def self.set_type_name(base)
  @host_name =  base.to_s.gsub('Page', '')
  @type = @host_name.underscore
  @host_class = @host_name.constantize
  rescue NameError
    @host_name =  ''
    @host_class = ''
end
undefine_accessor_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 224
def self.undefine_accessor_methods(base)
  base.instance_eval do
    @attributes.each do | attribute |
      remove_method("#{attribute}?")
      remove_method(attribute)
      remove_method("#{attribute}=")
    end
  end
end
undefine_class_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 258
def self.undefine_class_methods(base)
  eigenclass = class << base; self; end
  attributes = base.instance_variable_get('@attributes')
  eigenclass.instance_eval do
    attributes.each do | attribute|
      remove_method "find_by_#{attribute}"
    end
  end
end
undefine_instance_methods(base) click to toggle source

@private

# File lib/page_record/base.rb, line 240
def self.undefine_instance_methods(base)
  undefine_accessor_methods(base)
end

Public Instance Methods

element?() click to toggle source

Return the Capybara element containg the record

Example:

“‘ruby

team_1 = TeamPage.find(1) # Get the first team
team_1.element? # access the Capybara context

end “‘

# File lib/page_record/base.rb, line 31
def element?
  @record
end

Private Instance Methods

find_record(selector, filter) click to toggle source
# File lib/page_record/base.rb, line 285
def find_record(selector, filter)
  selector ||= @selector
  filter ||= @filter
  id_text = @id.blank? ? '' : "='#{@id}'"
  begin
    context = self.class.context_for_selector(selector)
    @record = context.find("[data-#{@type}-id#{id_text}]#{filter}")
    @id = @record["data-#{@type}-id"].to_i if @id.blank?
  rescue Capybara::Ambiguous
    raise MultipleRecords, "Found multiple #{@type} record with id #{@id} on page"
  rescue Capybara::ElementNotFound
    raise RecordNotFound, "#{@type} record with id #{@id} not found on page"
  end
end