From dc6f78e8f8abe26f3b6cc98c52abf50ae4309d0e Mon Sep 17 00:00:00 2001 From: yoshimi Date: Sun, 13 May 2012 02:04:08 +0900 Subject: [PATCH] =?UTF-8?q?search=5Fbase=E3=81=AE=E4=BB=AE=E7=B5=84?= =?UTF-8?q?=E3=81=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + lib/railstar.rb | 4 + lib/railstar/active_record_ext.rb | 39 ++++++++ lib/railstar/search_base.rb | 92 +++++++++++++++++++ .../app/controllers/projects_controller.rb | 3 +- .../dummy/app/controllers/tasks_controller.rb | 86 +++++++---------- test/dummy/app/models/search/project.rb | 14 +++ test/dummy/app/models/search/task.rb | 18 ++++ test/dummy/app/views/general/index.html.erb | 3 +- test/dummy/app/views/projects/index.html.erb | 15 ++- test/dummy/app/views/tasks/_detail.html.erb | 8 ++ test/dummy/app/views/tasks/_form.html.erb | 40 +++----- test/dummy/app/views/tasks/confirm.html.erb | 9 ++ test/dummy/app/views/tasks/destroy.html.erb | 12 +++ test/dummy/app/views/tasks/edit.html.erb | 10 +- test/dummy/app/views/tasks/index.html.erb | 56 ++++++----- test/dummy/app/views/tasks/new.html.erb | 8 +- test/dummy/app/views/tasks/show.html.erb | 24 ++--- test/dummy/config/routes.rb | 5 +- .../db/migrate/20120305073308_create_tasks.rb | 3 +- test/dummy/db/schema.rb | 3 +- test/dummy/db/seeds.rb | 4 + test/dummy/resources/code/status.csv | 6 ++ test/dummy/resources/db/projects.yml | 11 +++ test/dummy/resources/db/tasks.yml | 34 +++++++ 25 files changed, 371 insertions(+), 137 deletions(-) create mode 100644 lib/railstar/active_record_ext.rb create mode 100644 lib/railstar/search_base.rb create mode 100644 test/dummy/app/models/search/project.rb create mode 100644 test/dummy/app/models/search/task.rb create mode 100644 test/dummy/app/views/tasks/_detail.html.erb create mode 100644 test/dummy/app/views/tasks/confirm.html.erb create mode 100644 test/dummy/app/views/tasks/destroy.html.erb create mode 100644 test/dummy/db/seeds.rb create mode 100644 test/dummy/resources/code/status.csv create mode 100644 test/dummy/resources/db/projects.yml create mode 100644 test/dummy/resources/db/tasks.yml diff --git a/.gitignore b/.gitignore index 1dfe31e..f46d33d 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ test/dummy/db/*.sqlite3 test/dummy/log/*.log test/dummy/tmp/ test/dummy/.sass-cache +.DS_Store diff --git a/lib/railstar.rb b/lib/railstar.rb index 4242bed..67faad0 100644 --- a/lib/railstar.rb +++ b/lib/railstar.rb @@ -1,7 +1,11 @@ require 'railstar/engine' require 'railstar/code_holder' +require 'railstar/search_base' + require 'railstar/helper' ActionView::Base.send(:include, Railstar::Helper) +require 'railstar/active_record_ext' +ActiveRecord::Base.send(:include, Railstar::ActiveRecordExt) module Railstar def self.env diff --git a/lib/railstar/active_record_ext.rb b/lib/railstar/active_record_ext.rb new file mode 100644 index 0000000..090a247 --- /dev/null +++ b/lib/railstar/active_record_ext.rb @@ -0,0 +1,39 @@ +# encoding: utf-8 +module Railstar + module ActiveRecordExt + module ClassMethods + def truncation + return if self.count > 0 + self.truncation! + end + + def truncation! + table_name = self.to_s.underscore.pluralize + file_name = "#{table_name}.yml" + file_path = File.join(Rails.root, "resources", "db", file_name) + raise "#{file_path} file not found." unless File.exist?(file_path) + self.transaction do + case self.connection.adapter_name + when "SQLite" + self.connection.execute("DELETE FROM `#{self.table_name}`") + else + self.connection.execute("TRUNCATE TABLE `#{self.table_name}`") + end + YAML.load_file(file_path).each do |key, value| + self.create value + end + end + end + end + + module InstanceMethods + end + + def self.included(base) + base.extend ClassMethods + base.class_eval do + include InstanceMethods + end + end + end +end diff --git a/lib/railstar/search_base.rb b/lib/railstar/search_base.rb new file mode 100644 index 0000000..8ad2d02 --- /dev/null +++ b/lib/railstar/search_base.rb @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +module Railstar + class SearchBase + attr_accessor :where, :values + + def initialize(hash) + self.where = [] + self.values = {} + if hash + hash.each do |k,v| + send("#{k}=", v) + end + end + end + + def to_params + ret = {} + TARGET_COLUMN.each do |c| + unless eval(c.to_s).blank? + ret[c] = eval(c.to_s) + end + end + return ret + end + + def to_str_params + ret = to_params.map do |k,v| + begin + "#{k}=#{CGI.escape(v)}" + rescue + end + end + ret.join("&") + end + + def base + create_conditions #TODO: 毎回条件作成をしないようにしたい + target_model.where([self.where.join(" AND "), values]) + end + + private + def like(method, options={}) + value = eval(method.to_s) + unless value.blank? + column = options[:column] || method + self.where << "#{with_table_name(options[:table_name],column)} like :#{method}" + self.values[method] = "%#{value}%" + end + end + + def eq(method, options={}) + compare(method, "=", options) + end + + def inc(method, options={}) + value = eval(method.to_s) + value = value.split(",") if value.is_a?(String) && value.include?(",") + unless value.blank? + column = options[:column] || method + self.where << "#{with_table_name(options[:table_name],column)} in (:#{method})" + self.values[method] = value + end + end + + def compare(method, sign, options={}) + return unless sign =~ /^[<>=]{1,2}$/ + value = eval(method.to_s) + unless value.blank? + column = options[:column] || method + self.where << "#{with_table_name(options[:table_name],column)} #{sign} :#{method}" + self.values[method] = value + end + end + + def bit(method, options={}) + value = eval(method.to_s) + unless value.blank? + column = options[:column] || method + self.where << "#{with_table_name(options[:table_name],column)} & :#{method} = :#{method}" + self.values[method] = value + end + end + + + def with_table_name table_name, method + ret = "" + ret << "#{table_name || target_model.table_name}." if table_name + ret << method.to_s + ret + end + end +end diff --git a/test/dummy/app/controllers/projects_controller.rb b/test/dummy/app/controllers/projects_controller.rb index 0d057b2..4bda039 100644 --- a/test/dummy/app/controllers/projects_controller.rb +++ b/test/dummy/app/controllers/projects_controller.rb @@ -5,7 +5,8 @@ class ProjectsController < ApplicationController def index - @projects = Project.order("created_at desc").all + @search = Search::Project.new(params[:search]) + @projects = @search.base.joins("inner join tasks on tasks.project_id = projects.id").order("created_at desc").group("projects.id").all end def show diff --git a/test/dummy/app/controllers/tasks_controller.rb b/test/dummy/app/controllers/tasks_controller.rb index 03335c9..f307057 100644 --- a/test/dummy/app/controllers/tasks_controller.rb +++ b/test/dummy/app/controllers/tasks_controller.rb @@ -1,83 +1,61 @@ +# -*- coding: utf-8 -*- +# destroyメソッドに注意。モバイル対応&テキストリンク利用のためイレギュラーなことをしている +# restに対応した形を徹底したい場合は、削除確認ページへのリンクを以下の様に、formにする +# <%= form_tag(Task_path(task, :mode => "draft"), :method=>:delete) do %><%= submit_tag "delete", :name => "delete" %><% end %> + class TasksController < ApplicationController - # GET /tasks - # GET /tasks.json def index - @tasks = Task.all - - respond_to do |format| - format.html # index.html.erb - format.json { render json: @tasks } - end + @search = Search::Task.new(params[:search]) + @search.project_id = params[:project_id] + @tasks = @search.base.order("created_at desc").all end - # GET /tasks/1 - # GET /tasks/1.json def show @task = Task.find(params[:id]) - - respond_to do |format| - format.html # show.html.erb - format.json { render json: @task } - end + render "destroy" if params[:mode] == "draft" end - # GET /tasks/new - # GET /tasks/new.json def new - @task = Task.new - - respond_to do |format| - format.html # new.html.erb - format.json { render json: @task } - end + @task = Task.new(params[:task]) end - # GET /tasks/1/edit def edit @task = Task.find(params[:id]) end - # POST /tasks - # POST /tasks.json def create @task = Task.new(params[:task]) - - respond_to do |format| - if @task.save - format.html { redirect_to @task, notice: 'Task was successfully created.' } - format.json { render json: @task, status: :created, location: @task } - else - format.html { render action: "new" } - format.json { render json: @task.errors, status: :unprocessable_entity } - end - end + save end - # PUT /tasks/1 - # PUT /tasks/1.json def update @task = Task.find(params[:id]) - - respond_to do |format| - if @task.update_attributes(params[:task]) - format.html { redirect_to @task, notice: 'Task was successfully updated.' } - format.json { head :no_content } - else - format.html { render action: "edit" } - format.json { render json: @task.errors, status: :unprocessable_entity } - end - end + @task.attributes = params[:task] + save end - # DELETE /tasks/1 - # DELETE /tasks/1.json def destroy @task = Task.find(params[:id]) - @task.destroy + if params.key?("back") + redirect_to(task_url) + elsif params[:mode] != "draft" + @task.destroy + redirect_to(task_url, :notice => "deleted success.") + end + end - respond_to do |format| - format.html { redirect_to tasks_url } - format.json { head :no_content } + + private + def save + if !params.key?("back") && @task.valid? + if params[:mode] == "draft" + render :action => 'confirm' + else + @task.save! + redirect_to task_path(@task), :notice => 'saved success.' + end + else + render (@task.new_record? ? :new : :edit) end end end diff --git a/test/dummy/app/models/search/project.rb b/test/dummy/app/models/search/project.rb new file mode 100644 index 0000000..1e8cff7 --- /dev/null +++ b/test/dummy/app/models/search/project.rb @@ -0,0 +1,14 @@ +class Search::Project < Railstar::SearchBase + TARGET_COLUMN = %w(name like_name) + attr_accessor *TARGET_COLUMN + + private + def create_conditions + eq(:name) + like(:like_name, column: :name, table_name: "tasks") + end + + def target_model + ::Project + end +end diff --git a/test/dummy/app/models/search/task.rb b/test/dummy/app/models/search/task.rb new file mode 100644 index 0000000..572a12a --- /dev/null +++ b/test/dummy/app/models/search/task.rb @@ -0,0 +1,18 @@ +class Search::Task < Railstar::SearchBase + TARGET_COLUMN = %w(name like_name status project_id from_price to_price) + attr_accessor *TARGET_COLUMN + + private + def create_conditions + eq(:project_id) + eq(:name) + like(:like_name, column: :name) + inc(:status) + compare(:from_price, ">=", column: :price) + compare(:to_price, "<=", column: :price) + end + + def target_model + ::Task + end +end diff --git a/test/dummy/app/views/general/index.html.erb b/test/dummy/app/views/general/index.html.erb index 6e543c5..3bcafcd 100644 --- a/test/dummy/app/views/general/index.html.erb +++ b/test/dummy/app/views/general/index.html.erb @@ -1 +1,2 @@ -<%= link_to "Railstar", railstar.root_path %> +<%= link_to "Railstar", railstar.root_path %>
+<%= link_to "TestProject", projects_path %>
diff --git a/test/dummy/app/views/projects/index.html.erb b/test/dummy/app/views/projects/index.html.erb index 7cc32ef..0abfde7 100644 --- a/test/dummy/app/views/projects/index.html.erb +++ b/test/dummy/app/views/projects/index.html.erb @@ -1,10 +1,16 @@

Listing projects

+<%= form_tag(nil, :method => :get) do %> +<%= label :search, :name %>:<%= text_field :search, :name %>
+<%= label :search, :like_name %>:<%= text_field :search, :like_name %>
+<%= submit_tag :search %> +<% end %> + - - + + @@ -14,9 +20,8 @@ <% @projects.each do |project| %> - - - + + diff --git a/test/dummy/app/views/tasks/_detail.html.erb b/test/dummy/app/views/tasks/_detail.html.erb new file mode 100644 index 0000000..f672196 --- /dev/null +++ b/test/dummy/app/views/tasks/_detail.html.erb @@ -0,0 +1,8 @@ +
NameName
Name<%= project.name %><%= link_to 'Show', project %><%= link_to project.name, project_tasks_path(:project_id => project.id) %><%= link_to 'Show', project %> <%= link_to 'Edit', edit_project_path(project) %> <%= link_to 'Delete', project_path(project, :mode => "draft") %>
+ + + + + + +
Name<%= @task.name %>
diff --git a/test/dummy/app/views/tasks/_form.html.erb b/test/dummy/app/views/tasks/_form.html.erb index 0963429..5dc589f 100644 --- a/test/dummy/app/views/tasks/_form.html.erb +++ b/test/dummy/app/views/tasks/_form.html.erb @@ -1,29 +1,17 @@ -<%= form_for(@task) do |f| %> - <% if @task.errors.any? %> -
-

<%= pluralize(@task.errors.count, "error") %> prohibited this task from being saved:

+<%= form_for(@task, :url => save_action(@task, :mode => "draft")) do |f| %> +<% if @task.errors.any? %> +<% @task.errors.full_messages.each do |msg| %> +

<%= msg %>

+<% end %> +<% end %> + - -
- <% end %> + + + + + +
<%= f.label :name %><%= f.text_field :name %>
-
- <%= f.label :name %>
- <%= f.text_field :name %> -
-
- <%= f.label :project_id %>
- <%= f.number_field :project_id %> -
-
- <%= f.label :status %>
- <%= f.number_field :status %> -
-
- <%= f.submit %> -
+<%= f.submit :class => "btn primary" %> <% end %> diff --git a/test/dummy/app/views/tasks/confirm.html.erb b/test/dummy/app/views/tasks/confirm.html.erb new file mode 100644 index 0000000..8f8d08a --- /dev/null +++ b/test/dummy/app/views/tasks/confirm.html.erb @@ -0,0 +1,9 @@ +

Confirm task

+ +<%= render :partial => 'detail' %> + +<%= form_tag({}, :method => request.request_method) do %> +<%= raw params_to_hidden_tag :task %> + + +<% end %> diff --git a/test/dummy/app/views/tasks/destroy.html.erb b/test/dummy/app/views/tasks/destroy.html.erb new file mode 100644 index 0000000..6fbc04e --- /dev/null +++ b/test/dummy/app/views/tasks/destroy.html.erb @@ -0,0 +1,12 @@ +

Destroy task

+ +<%= render :partial => 'detail' %> + +<%= form_tag({}, :method => "delete") do -%> + + +<% end -%> + +
+ <%= link_to 'Back', tasks_path, :class => "btn" %> +
diff --git a/test/dummy/app/views/tasks/edit.html.erb b/test/dummy/app/views/tasks/edit.html.erb index bde6546..d295d71 100644 --- a/test/dummy/app/views/tasks/edit.html.erb +++ b/test/dummy/app/views/tasks/edit.html.erb @@ -1,6 +1,8 @@ -

Editing task

+

Editing project

-<%= render 'form' %> +<%= render :partial => 'form' %> -<%= link_to 'Show', @task %> | -<%= link_to 'Back', tasks_path %> +
+ <%= link_to 'Show', project_path(@project), :class => "btn" %> + <%= link_to 'Back', projects_path, :class => "btn" %> +
diff --git a/test/dummy/app/views/tasks/index.html.erb b/test/dummy/app/views/tasks/index.html.erb index 2c7ae67..f13a297 100644 --- a/test/dummy/app/views/tasks/index.html.erb +++ b/test/dummy/app/views/tasks/index.html.erb @@ -1,27 +1,41 @@

Listing tasks

- - - - - - - - - +<%= form_tag(nil, :method => :get) do %> +<%= label :search, :name %><%= text_field :search, :name %>
+<%= label :search, :like_name %><%= text_field :search, :like_name %>
+<% C.status.to_opt.each do |status| %> +<%= label :search, "status_#{status.first}" %><%= check_box_tag "search[status][]", status.last, !!@search.status ? @search.status.detect{|s| s == status.last} : false %> +<% end %>
+<%= label :search, :price %><%= text_field :search, :from_price %><%= text_field :search, :to_price %>
-<% @tasks.each do |task| %> - - - - - - - - +<%= submit_tag :search %> <% end %> -
NameProjectStatus
<%= task.name %><%= task.project_id %><%= task.status %><%= link_to 'Show', task %><%= link_to 'Edit', edit_task_path(task) %><%= link_to 'Destroy', task, confirm: 'Are you sure?', method: :delete %>
-
+ + + + + + + + + + + + + + + <% @tasks.each do |task| %> + + + + + + + + + <% end %> + +
NameStatusPrice
<%= task.name %><%= C.status[task.status].name %><%= task.price %><%= link_to 'Show', project_task_path(:id => task.id) %><%#= link_to 'Edit', edit_task_path(task) %><%#= link_to 'Delete', task_path(task, :mode => "draft") %>
-<%= link_to 'New Task', new_task_path %> +<%= link_to 'New Task', new_project_task_path %> diff --git a/test/dummy/app/views/tasks/new.html.erb b/test/dummy/app/views/tasks/new.html.erb index 59aa573..ee6dbda 100644 --- a/test/dummy/app/views/tasks/new.html.erb +++ b/test/dummy/app/views/tasks/new.html.erb @@ -1,5 +1,7 @@ -

New task

+

New project

-<%= render 'form' %> +<%= render :partial => 'form' %> -<%= link_to 'Back', tasks_path %> +
+ <%= link_to 'Back', projects_path, :class => "btn" %> +
diff --git a/test/dummy/app/views/tasks/show.html.erb b/test/dummy/app/views/tasks/show.html.erb index 82c6d12..ba8b1b3 100644 --- a/test/dummy/app/views/tasks/show.html.erb +++ b/test/dummy/app/views/tasks/show.html.erb @@ -1,20 +1,8 @@ -

<%= notice %>

+

Showing project

+<%= render :partial => 'detail' %> -

- Name: - <%= @task.name %> -

+
+ <%= link_to 'Edit', edit_project_path(@project), :class => "btn" %> + <%= link_to 'Back', projects_path, :class => "btn" %> +
-

- Project: - <%= @task.project_id %> -

- -

- Status: - <%= @task.status %> -

- - -<%= link_to 'Edit', edit_task_path(@task) %> | -<%= link_to 'Back', tasks_path %> diff --git a/test/dummy/config/routes.rb b/test/dummy/config/routes.rb index 7b14b3a..f99cdb8 100644 --- a/test/dummy/config/routes.rb +++ b/test/dummy/config/routes.rb @@ -1,7 +1,8 @@ Rails.application.routes.draw do root :to => "general#index" - resources :projects - resources :tasks + resources :projects do + resources :tasks + end mount Railstar::Engine => "/railstar" end diff --git a/test/dummy/db/migrate/20120305073308_create_tasks.rb b/test/dummy/db/migrate/20120305073308_create_tasks.rb index f5decea..8d34ae7 100644 --- a/test/dummy/db/migrate/20120305073308_create_tasks.rb +++ b/test/dummy/db/migrate/20120305073308_create_tasks.rb @@ -3,7 +3,8 @@ def change create_table :tasks do |t| t.string :name t.integer :project_id - t.integer :status + t.string :status + t.integer :price t.timestamps end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index b8ec932..e13d731 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -22,7 +22,8 @@ create_table "tasks", :force => true do |t| t.string "name" t.integer "project_id" - t.integer "status" + t.string "status" + t.integer "price" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false end diff --git a/test/dummy/db/seeds.rb b/test/dummy/db/seeds.rb new file mode 100644 index 0000000..797cace --- /dev/null +++ b/test/dummy/db/seeds.rb @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +Project.truncation! +Task.truncation! diff --git a/test/dummy/resources/code/status.csv b/test/dummy/resources/code/status.csv new file mode 100644 index 0000000..1917ce9 --- /dev/null +++ b/test/dummy/resources/code/status.csv @@ -0,0 +1,6 @@ +title,ステータス +#DATA +key,value,position,name +TODO,todo,1,TODO +DOING,doing,2,DOING +DONE,done,3,DONE \ No newline at end of file diff --git a/test/dummy/resources/db/projects.yml b/test/dummy/resources/db/projects.yml new file mode 100644 index 0000000..8e4631c --- /dev/null +++ b/test/dummy/resources/db/projects.yml @@ -0,0 +1,11 @@ +1: + id: 1 + name: プロジェクト1 + +2: + id: 2 + name: プロジェクト2 + +3: + id: 3 + name: プロジェクト3 diff --git a/test/dummy/resources/db/tasks.yml b/test/dummy/resources/db/tasks.yml new file mode 100644 index 0000000..91678ab --- /dev/null +++ b/test/dummy/resources/db/tasks.yml @@ -0,0 +1,34 @@ +1: + project_id: 1 + name: タスク1 + status: "todo" + price: 100 + +2: + project_id: 1 + name: タスク2 + status: "todo" + price: 200 + +3: + project_id: 1 + name: タスク3 + status: "doing" + price: 200 + +4: + project_id: 1 + name: タスク4 + status: "doing" + price: 300 + +5: + project_id: 1 + name: タスク5 + status: "done" + price: 400 + +6: + project_id: 2 + name: タスク6 + status: "todo" \ No newline at end of file