Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[frontend] Use nested module syntax for Kiwi classes #4080

Merged
merged 1 commit into from
Oct 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 105 additions & 103 deletions src/api/app/models/kiwi/image.rb
Original file line number Diff line number Diff line change
@@ -1,126 +1,128 @@
class Kiwi::Image < ApplicationRecord
#### Includes and extends

#### Constants
DEFAULT_KIWI_BODY = '<?xml version="1.0" encoding="utf-8"?>
<image schemaversion="6.2" name="suse-13.2-live">
<description type="system">
</description>
<preferences>
<type image="oem" primary="true" boot="oemboot/suse-13.2"/>
</preferences>
</image>
'.freeze

#### Self config
#### Attributes

#### Associations macros (Belongs to, Has one, Has many)
has_one :package, foreign_key: 'kiwi_image_id', class_name: '::Package', dependent: :nullify, inverse_of: :kiwi_image
has_many :repositories, -> { order(order: :asc) }, dependent: :destroy, index_errors: true
has_many :package_groups, -> { order(:id) }, dependent: :destroy, index_errors: true
has_many :kiwi_packages, -> { where(kiwi_package_groups: { kiwi_type: Kiwi::PackageGroup.kiwi_types[:image] }) },
through: :package_groups, source: :packages, inverse_of: :kiwi_image

#### Callbacks macros: before_save, after_save, etc.

#### Scopes (first the default_scope macro if is used)

#### Validations macros
validates :name, presence: true
validate :check_use_project_repositories
validate :check_package_groups
accepts_nested_attributes_for :repositories, allow_destroy: true
accepts_nested_attributes_for :package_groups, allow_destroy: true
accepts_nested_attributes_for :kiwi_packages, allow_destroy: true

#### Class methods using self. (public and then private)

#### To define class methods as private use private_class_method
#### private

#### Instance methods (public and then protected/private)

#### Alias of methods
def self.build_from_xml(xml_string, md5)
Kiwi::Image::XmlParser.new(xml_string, md5).parse
end
module Kiwi
class Image < ApplicationRecord
#### Includes and extends

#### Constants
DEFAULT_KIWI_BODY = '<?xml version="1.0" encoding="utf-8"?>
<image schemaversion="6.2" name="suse-13.2-live">
<description type="system">
</description>
<preferences>
<type image="oem" primary="true" boot="oemboot/suse-13.2"/>
</preferences>
</image>
'.freeze

#### Self config
#### Attributes

#### Associations macros (Belongs to, Has one, Has many)
has_one :package, foreign_key: 'kiwi_image_id', class_name: '::Package', dependent: :nullify, inverse_of: :kiwi_image
has_many :repositories, -> { order(order: :asc) }, dependent: :destroy, index_errors: true
has_many :package_groups, -> { order(:id) }, dependent: :destroy, index_errors: true
has_many :kiwi_packages, -> { where(kiwi_package_groups: { kiwi_type: Kiwi::PackageGroup.kiwi_types[:image] }) },
through: :package_groups, source: :packages, inverse_of: :kiwi_image

#### Callbacks macros: before_save, after_save, etc.

#### Scopes (first the default_scope macro if is used)

#### Validations macros
validates :name, presence: true
validate :check_use_project_repositories
validate :check_package_groups
accepts_nested_attributes_for :repositories, allow_destroy: true
accepts_nested_attributes_for :package_groups, allow_destroy: true
accepts_nested_attributes_for :kiwi_packages, allow_destroy: true

#### Class methods using self. (public and then private)

#### To define class methods as private use private_class_method
#### private

#### Instance methods (public and then protected/private)

#### Alias of methods
def self.build_from_xml(xml_string, md5)
Kiwi::Image::XmlParser.new(xml_string, md5).parse
end

def to_xml
Kiwi::Image::XmlBuilder.new(self).build
end
def to_xml
Kiwi::Image::XmlBuilder.new(self).build
end

def write_to_backend
return false unless package
def write_to_backend
return false unless package

Package.transaction do
file_name = package.kiwi_image_file || "#{package.name}.kiwi"
package.save_file({ filename: file_name, file: to_xml })
self.md5_last_revision = package.kiwi_file_md5
save!
Package.transaction do
file_name = package.kiwi_image_file || "#{package.name}.kiwi"
package.save_file({ filename: file_name, file: to_xml })
self.md5_last_revision = package.kiwi_file_md5
save!
end
end
end

def outdated?
return false unless package
def outdated?
return false unless package

package.kiwi_image_outdated?
end
package.kiwi_image_outdated?
end

def default_package_group
package_groups.type_image.first || package_groups.create(kiwi_type: :image, pattern_type: 'onlyRequired')
end
def default_package_group
package_groups.type_image.first || package_groups.create(kiwi_type: :image, pattern_type: 'onlyRequired')
end

def self.find_binaries_by_name(query, project, repositories, options = {})
finder = /\A#{Regexp.quote(query)}/
binaries_available(project, options[:use_project_repositories], repositories).select { |package, _| finder.match(package.to_s) }
end
def self.find_binaries_by_name(query, project, repositories, options = {})
finder = /\A#{Regexp.quote(query)}/
binaries_available(project, options[:use_project_repositories], repositories).select { |package, _| finder.match(package.to_s) }
end

def self.binaries_available(project, use_project_repositories, repositories)
Rails.cache.fetch("kiwi_image_binaries_available_#{project}_#{use_project_repositories}_#{repositories}", expires_in: 5.minutes) do
if use_project_repositories
Backend::Api::BuildResults::Binaries.available_in_project(project)
else
return [] if repositories.blank?
obs_repository_paths = repositories.select { |url| url.starts_with?("obs://")}.map {|url| url[6..-1] }
non_obs_repository_urls = repositories.reject { |url| url.starts_with?("obs://")}
Backend::Api::BuildResults::Binaries.available_in_repositories(project, non_obs_repository_urls, obs_repository_paths)
def self.binaries_available(project, use_project_repositories, repositories)
Rails.cache.fetch("kiwi_image_binaries_available_#{project}_#{use_project_repositories}_#{repositories}", expires_in: 5.minutes) do
if use_project_repositories
Backend::Api::BuildResults::Binaries.available_in_project(project)
else
return [] if repositories.blank?
obs_repository_paths = repositories.select { |url| url.starts_with?("obs://")}.map {|url| url[6..-1] }
non_obs_repository_urls = repositories.reject { |url| url.starts_with?("obs://")}
Backend::Api::BuildResults::Binaries.available_in_repositories(project, non_obs_repository_urls, obs_repository_paths)
end
end
end
end

# This method is for parse the error messages and group them to make them more understandable.
# The nested errors messages are like `Model[0] attributes` and this is not easy to understand.
def parsed_errors(title, packages)
message = { title: title }
message["Image Errors:"] = errors.messages[:base] if errors.messages[:base].present?

{ repository: repositories, package: packages }.each do |key, records|
records.each do |record|
if record.errors.present?
message["#{key.capitalize}: #{record.name}"] ||= []
message["#{key.capitalize}: #{record.name}"] << record.errors.messages.values
message["#{key.capitalize}: #{record.name}"].flatten!
# This method is for parse the error messages and group them to make them more understandable.
# The nested errors messages are like `Model[0] attributes` and this is not easy to understand.
def parsed_errors(title, packages)
message = { title: title }
message["Image Errors:"] = errors.messages[:base] if errors.messages[:base].present?

{ repository: repositories, package: packages }.each do |key, records|
records.each do |record|
if record.errors.present?
message["#{key.capitalize}: #{record.name}"] ||= []
message["#{key.capitalize}: #{record.name}"] << record.errors.messages.values
message["#{key.capitalize}: #{record.name}"].flatten!
end
end
end
end

message
end
message
end

private
private

def check_use_project_repositories
return unless use_project_repositories? && repositories.present?
def check_use_project_repositories
return unless use_project_repositories? && repositories.present?

errors.add(:base,
"A repository with source_path \"obsrepositories:/\" has been set. If you want to use it, please remove the other repositories.")
end
errors.add(:base,
"A repository with source_path \"obsrepositories:/\" has been set. If you want to use it, please remove the other repositories.")
end

def check_package_groups
return if package_groups.group_by(&:kiwi_type).select { |_key, value| value.count > 1 }.keys.empty?
def check_package_groups
return if package_groups.group_by(&:kiwi_type).select { |_key, value| value.count > 1 }.keys.empty?

errors.add(:base, "Multiple package groups with same type are not allowed.")
errors.add(:base, "Multiple package groups with same type are not allowed.")
end
end
end

Expand Down
24 changes: 13 additions & 11 deletions src/api/app/models/kiwi/package.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
class Kiwi::Package < ApplicationRecord
belongs_to :package_group
has_one :kiwi_image, through: :package_groups
module Kiwi
class Package < ApplicationRecord
belongs_to :package_group
has_one :kiwi_image, through: :package_groups

validates :name, presence: { message: 'Package name can\'t be blank'}
validates :name, presence: { message: 'Package name can\'t be blank'}

def to_h
hash = { name: name }
hash[:arch] = arch if arch.present?
hash[:replaces] = replaces if replaces.present?
hash[:bootinclude] = bootinclude if bootinclude.present?
hash[:bootdelete] = bootdelete if bootdelete.present?
hash
def to_h
hash = { name: name }
hash[:arch] = arch if arch.present?
hash[:replaces] = replaces if replaces.present?
hash[:bootinclude] = bootinclude if bootinclude.present?
hash[:bootdelete] = bootdelete if bootdelete.present?
hash
end
end
end

Expand Down
48 changes: 25 additions & 23 deletions src/api/app/models/kiwi/package_group.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
class Kiwi::PackageGroup < ApplicationRecord
has_many :packages, dependent: :destroy
belongs_to :image
module Kiwi
class PackageGroup < ApplicationRecord
has_many :packages, dependent: :destroy
belongs_to :image

# we need to add a prefix, to avoid generating class methods that already
# exist in Active Record, such as "delete"
enum kiwi_type: %i[bootstrap delete docker image iso lxc oem pxe split testsuite vmx], _prefix: :type
# we need to add a prefix, to avoid generating class methods that already
# exist in Active Record, such as "delete"
enum kiwi_type: %i[bootstrap delete docker image iso lxc oem pxe split testsuite vmx], _prefix: :type

scope :type_image, -> { where(kiwi_type: :image) }
scope :type_image, -> { where(kiwi_type: :image) }

validates :kiwi_type, presence: true
validates :kiwi_type, presence: true

accepts_nested_attributes_for :packages, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :packages, reject_if: :all_blank, allow_destroy: true

def to_xml
return '' if packages.empty?
group_attributes = { type: kiwi_type }
group_attributes[:profiles] = profiles if profiles.present?
group_attributes[:patternType] = pattern_type if pattern_type.present?
def to_xml
return '' if packages.empty?
group_attributes = { type: kiwi_type }
group_attributes[:profiles] = profiles if profiles.present?
group_attributes[:patternType] = pattern_type if pattern_type.present?

builder = Nokogiri::XML::Builder.new
builder.packages(group_attributes) do |group|
packages.each do |package|
group.package(package.to_h)
builder = Nokogiri::XML::Builder.new
builder.packages(group_attributes) do |group|
packages.each do |package|
group.package(package.to_h)
end
end
end

builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION | Nokogiri::XML::Node::SaveOptions::FORMAT
end
builder.to_xml save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION | Nokogiri::XML::Node::SaveOptions::FORMAT
end

def kiwi_type_image?
kiwi_type == 'image'
def kiwi_type_image?
kiwi_type == 'image'
end
end
end

Expand Down
Loading