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

Fixes #259 - Implements is_first_version and is_last_version attributes #287

Merged
merged 6 commits into from
Apr 26, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ The tests are run using Guard, either:

or in case the listening does not work, force the use of file polling:

$ guard --force-polling
$ bin/guard guard --force-polling

Press enter to execute all tests. Guard will monitor for changes and the relevant tests will be run as files are modified.

Expand Down
4 changes: 2 additions & 2 deletions app/controllers/admin/scripts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def new
def edit
@script = Script.find(params[:id])

unless @script.is_latest_version?
unless @script.is_last_version?
redirect_to edit_admin_script_path(@script.latest_version), notice: 'You have been redirected to update the latest version of this Script.'
end
end
Expand All @@ -51,7 +51,7 @@ def create
def update
@script = Script.find(params[:id])

unless @script.is_latest_version?
unless @script.is_last_version?
respond_to do |format|
format.html { redirect_to edit_admin_script_path(@script.latest_version), notice: 'You have been redirected to update the latest version of this Script.' }
format.json { respond_change_fail }
Expand Down
27 changes: 10 additions & 17 deletions app/controllers/scripts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ class ScriptsController < ApplicationController
def index
do_authorize_class

respond_to do |format|
format.json {
@scripts, opts = Settings.api_response.response_advanced(
api_filter_params,
get_recent_scripts,
Script,
Script.filter_settings
)
respond_index(opts)
}
end
@scripts, opts = Settings.api_response.response_advanced(
api_filter_params,
get_scripts,
Script,
Script.filter_settings
)
respond_index(opts)

end

# GET /admin/scripts/:id
# GET /scripts/:id
def show
do_load_resource
do_authorize_instance
Expand All @@ -39,15 +36,11 @@ def filter
respond_filter(filter_response, opts)
end


private


def get_scripts
Script.order(name: :asc).order(created_at: :desc)
end

def get_recent_scripts
Script.all_most_recent_version
end

end
125 changes: 93 additions & 32 deletions app/models/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Script < ActiveRecord::Base
validate :check_version_increase, on: :create

# for the first script in a group, make sure group_id is set to the script's id
after_create :ensure_updated_by_set
after_create :set_group_id, :set_versions

def display_name
"#{self.name} - v. #{self.version}"
Expand All @@ -27,51 +27,103 @@ def latest_version
.first
end

def is_latest_version?
self.id == latest_version.id
end

def most_recent_in_group
def earliest_version
Script
.where(group_id: self.group_id)
.order(created_at: :desc)
.order(version: :asc)
.first
end

def is_most_recent_in_group?
self.id == most_recent_in_group.id
def last_version
self.read_attribute(:last_version)
end

def master_script
Script
.where(group_id: self.group_id)
.where(id: self.group_id)
.first
def is_last_version?
self.version == self.last_version
end

def all_versions
Script.where(group_id: self.group_id).order(created_at: :desc)
def first_version
self.read_attribute(:first_version)
end

def is_first_version?
self.version == self.first_version
end

def self.all_most_recent_version
Script.find_by_sql(
'SELECT s1.*
FROM scripts s1
WHERE s1.version = (
SELECT max(s2.version)
FROM scripts s2
WHERE s1.group_id = s2.group_id
GROUP BY s2.group_id
)
ORDER BY s1.group_id, s1.version;'
)
# override the default query for the model
def self.default_scope
query = <<-SQL
INNER JOIN (
SELECT "group_id", max("version") AS "last_version", min("version") AS "first_version"
FROM "scripts"
GROUP BY "group_id"
) s2 on ("scripts"."group_id" = "s2"."group_id")
SQL

joins(query).select('"scripts".*, "s2"."last_version", "s2"."first_version"')
end

# a fake reference to the aliased table defined in the default scope
@script_group = Arel::Table.new('s2', @arel_engine)

# HACK: reload item - this is a poor version of Persistence::reload
# https://github.com/rails/rails/blob/1f98eb60e59f4f70ef66ac2454ad029f46e3b27c/activerecord/lib/active_record/persistence.rb#L432
# The only difference is the `unscoped` method is removed.
def reload(options = nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

self.class.connection.clear_query_cache

fresh_object =
if options && options[:lock]
self.class.lock(options[:lock]).find(id)
else
self.class.find(id)
end

@attributes = fresh_object.instance_variable_get('@attributes')
@new_record = false
self
end

def all_versions
Script.where(group_id: self.group_id).order(created_at: :desc)
end

def self.filter_settings
{
valid_fields: [:id, :name, :description, :analysis_identifier, :executable_settings_media_type, :version, :created_at, :creator_id],
render_fields: [:id, :name, :description, :analysis_identifier, :executable_settings, :executable_settings_media_type, :version, :created_at, :creator_id],
valid_fields: [:id, :group_id, :name, :description, :analysis_identifier, :executable_settings_media_type,
:version, :created_at, :creator_id, :is_last_version, :is_first_version],
render_fields: [:id, :group_id, :name, :description, :analysis_identifier, :executable_settings,
:executable_settings_media_type, :version, :created_at, :creator_id],
text_fields: [:name, :description, :analysis_identifier, :executable_settings_media_type],
custom_fields: lambda { |item, user|
virtual_fields = {
is_last_version: item.is_last_version?,
is_first_version: item.is_first_version?
}
[item, virtual_fields]
},
field_mappings: [
{
name: :is_last_version,
value: Arel::Nodes::Grouping.new(
Arel::Nodes::InfixOperation.new(
'='.to_sym,
@script_group[:last_version],
Script.arel_table[:version]
)
)
},
{
name: :is_first_version,
value: Arel::Nodes::Grouping.new(
Arel::Nodes::InfixOperation.new(
'='.to_sym,
@script_group[:first_version],
Script.arel_table[:version]
)
)
}
],
controller: :scripts,
action: :filter,
defaults: {
Expand All @@ -86,18 +138,27 @@ def self.filter_settings
def check_version_increase
matching_or_higher_versions =
Script
.unscoped
.where(group_id: self.group_id)
.where('version >= ?', self.version)
if matching_or_higher_versions.count > 0
errors.add(:version, "must be higher than previous versions (#{matching_or_higher_versions.pluck(:version).flatten.join(', ')})")
end
end

def ensure_updated_by_set
def set_group_id
if self.group_id.blank?
self.group_id = self.id
self.save
self.save!
end

end

# this is needed because the default scope query is not run when creating
# should only be called :after_create
def set_versions
# HACK: another select has to be run
self.reload
end

end
Loading