顯示具有 CRUD 標籤的文章。 顯示所有文章
顯示具有 CRUD 標籤的文章。 顯示所有文章

2016年10月25日 星期二

Cloud9-RoR-fullcalendar-rails & CRUD Part.1

*2016/11/1-更新calendar.coffee、calendar.controller,將_form.html.erb改回new.html.erb。

參考來源(jquery-ui):https://rubygems.org/gems/fullcalendar-rails/versions
參考來源(CRUD):http://vinsol.com/fullcalendar-demo

C:會套用前幾篇中提到的one-to-many頁面。
R:使用jquery-ui的套件,將事件的detail顯示在dialog裡。
U:本篇不做。
D:依附在read底下,點選某一日曆上的事件時才會載入delete按鈕,如該事件已有人回復/預訂,則不可刪除。

首先安裝 jquery-ui-rails
打開Gemfile檔,加入
# jquery-ui
gem 'jquery-ui-rails'

編輯application.js,加入
//= require jquery-ui

編輯application.css,加入
*= require jquery-ui

執行指令
$ bundle install


CRUP實做
編輯calendars_controller.rb
  before_action :set_calendar, :only => [ :destroy]
  def index
    @calendars = Calendar.
    select("calendars.id", "IF(calendars.user_id = '#{current_user.id}', 1, 0) AS isedit",
    "IF(rcalendars.fb_nickname IS NULL, 1, 0) AS reserved",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, ':00:00') AS dt", 
    "CONCAT(users.username, ' ', IFNULL(rcalendars.fb_nickname, '')) AS title",
    "CONCAT(calendars.vdate , ' ', calendars.vtime, '點<br/>', IFNULL(rcalendars.content, '')) AS description").
    joins("LEFT JOIN users ON users.id = calendars.user_id LEFT JOIN rcalendars ON rcalendars.calendar_id = calendars.id")
    #if json file(index.json.jbuilder) like to link use json.url calendar_path(calendar)
  end

  def new
    @calendar = []
    15.times do
      @calendar << Calendar.new
    end
    render :layout => false
  end
  
  def create
    if params.has_key?("calendar")
      @calendar = Calendar.create(calendar_params(params["calendar"]))
    else
      params["calendars"].each do |calendar|
        if calendar["issave"] && calendar["vdate"] != ""
          @calendar = Calendar.create(calendar_params(calendar))
        end
      end
    end
    
    #json
    respond_to do |format|
      if @calendar.save
        format.html { redirect_to calendars_url, notice: 'calendar was successfully created.' }
        format.json { render action: 'index', status: :created, location: @calendar }
      else
        format.html { render action: 'new' }
        format.json { render json: @calendar.errors, status: :unprocessable_entity }
      end
    end 
    #json
  end  

  def destroy
    @calendar.destroy
    redirect_to calendars_url
    flash[:alert] = "calendar was successfully deleted"
  end
  
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_calendar
      @calendar = Calendar.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def calendar_params(my_params)
      my_params.permit(:user_id, :vdate, :vtime)
    end  

編輯calendar.coffee
$(document).ready ->
  # page is now ready, initialize the calendar...
  $('#new_event').click (event) ->
    $.get '/calendars/new', (data) ->
      #初始將a.html include div#iframe
      $('#create_event').html data
      return
    $('#create_event_dialog').dialog
      title: '新增'
      modal: true
      width: 500
      close: (event, ui) ->
        $('#create_event_dialog').dialog 'destroy'
        return
    return
    
  $('#create_event_dialog, #desc_dialog').on 'submit', '#event_form', (event) ->
    $spinner = $('.spinner')
  
    show_spinner = ->
      $spinner.show()
      return
  
    hide_spinner = ->
      $spinner.hide()
      return
  
    handle_error = (xhr) ->
      alert xhr.responseText
      return
  
    event.preventDefault()
    $.ajax
      type: 'POST'
      data: $(this).serialize()
      url: $(this).attr('action')
      beforeSend: show_spinner
      complete: hide_spinner
      success: refetch_events_and_close_dialog
      error: handle_error
    return
    
  $('#calendar').fullCalendar
    header:
      left: 'prev,next today'
      center: 'title'
      right: 'month'
    defaultView: 'month'
    loading: (bool) ->
      if bool
        $('#loading').show()
      else
        $('#loading').hide()
      return
    events: '/calendars.json'
    timeFormat: 'Ahh點'
    eventClick: (event, jsEvent, view) ->
      showEventDetails event
      return  
  return

showEventDetails = (event) ->
  $('#event_desc').html event.description
  title = event.title
  if event.isedit and event.reserved
    $('#delete_event').html '<form class="button_to" method="post" action="/calendars/' + event.id + '"><input type="hidden" name="_method" value="delete" /><input type="hidden" name="authenticity_token" value="' + $('meta[name="csrf-token"]').attr('content') + '" /><input data-confirm="Are you sure?" type="submit" value="Delete" /></form>'
  else
    $('#delete_event').html ''
  $('#desc_dialog').dialog
    title: title
    modal: true
    width: 500
    close: (event, ui) ->
      $('#desc_dialog').dialog 'destroy'
      return
  return

refetch_events_and_close_dialog = ->
  $('#calendar').fullCalendar 'refetchEvents'
  $('.dialog:visible').dialog 'destroy'
  return

編輯calendars.scss
.fc-h-event {
    cursor: pointer;
}

編輯calendars/index.html.erb
<div><%=link_to '新增', new_calendar_path, :id => 'new_event' %></div>

<div id="calendar"></div>

<!--隱藏表單 //-->
<div id = "desc_dialog" class="dialog" style ="display:none;">
  <div id = "event_desc">
  </div>
  <br/>
  <br/>
  <div id = "event_actions">
    <span id = "edit_event"></span>
    <span id = "delete_event"></span>
  </div>
</div>
<div id = "create_event_dialog" class="dialog" style ="display:none;">
  <div id = "create_event">
  </div>
</div>

新增的畫面

點開日曆事件時的畫面
可編輯自己的部份:

不可編輯他人的資料:

後台總算告個段落,只剩下套版了。

2015年9月8日 星期二

Cloud9-RoR-打造自己的CRUD

參考文章:https://ihower.tw/rails4/basic.html

CRUD:對資料庫做Create、Read、Update、Delete操作。

想要一步一步了解的人,可以照著參考文章練習,我只記錄檔案最後的樣子,以及要下的指令。

這個單元要建立的是一個類似Blog的功能,參考文章較像後台的樣子,所以就把它當成後台的建置唄。

產生一個Model
$ rails g model event cnttype:integer title:string description:text author:string is_public:boolean  public_date:date share:integer like:integer

執行指令建立資料表
$ bin/rake db:migrate

因為我是記錄正式站的建立步驟,所以直接跳到「實做基本的CRUD應用程式」,不過練習時還是所有乖乖把所有步驟都完成滴。

在config/routes.rb最後插入一行,這樣就不用每一條路徑都要進到routes.rb設定了
  # ....
  match ':controller(/:action(/:id(.:format)))', :via => :all
end

執行以下指令
$ rails g controller events

編輯app/controllers/events_controller.rb,灰字的部份是原來就存在檔案中的,我們要貼上的是綠色的部份
class EventsController < ApplicationController
  before_action :set_event, :only => [ :show, :edit, :update, :destroy]
  def index
    #@events = Event.all
    @events = Event.page(params[:page]).per(5)
  end
  
  def new
    @event = Event.new
  end
  def create
    @event = Event.new(event_params)
    if @event.save
      redirect_to :action => :index
    else
      render :action => :new
    end
    flash[:notice] = "event was successfully created"
  end
  
  def show
    #@event = Event.find(params[:id])
    @page_title = @event.title
  end
  
  def edit
    #@event = Event.find(params[:id])
  end
  def update
    #@event = Event.find(params[:id])
    if @event.update(event_params)
      redirect_to :action => :show, :id => @event
    else
      render :action => :edit
    end
    flash[:notice] = "event was successfully updated"
  end
  
  def destroy
    #@event = Event.find(params[:id])
    @event.destroy
  
    redirect_to :action => :index
    flash[:alert] = "event was successfully deleted"
  end
  
  #private以下的所有方法都會變成private方法,所以記得放在檔案的最底下。
  private
  
  def event_params
    params.require(:event).permit(:cnttype, :description, :author, :is_public, :public_date)
  end
  
  def set_event
    @event = Event.find(params[:id])
  end
end

Event.all會抓出所有的資料,回傳一個陣列給實例變數(instance variables)指派給@events。在Rails會讓Action裡的實例變數(也就是有@開頭的變數)通通傳到View樣板裡面可以使用。這個Action預設使用的樣板是app/views/events/目錄下與Action同名的檔案。

在app/view/s/events新增一個index.html.erb的檔案,內容如下
<ul>
<% @events.each do |event| %>
  <li>
    <%= event.title %>
  <%= link_to 'Show', :controller => 'events', :action => 'show', :id => event %>
  <%= link_to 'Edit', :controller => 'events', :action => 'edit', :id => event %>
  <%= link_to 'Delete', :controller => 'events', :action => 'destroy', :id => event %>
  </li>
<% end %>
</ul>
<%= link_to 'New Event', :controller => 'events', :action => 'new' %>
<%= paginate @events %>

新增app/views/events/new.html.erb檔案,內容如下
<%= form_for @event, :url => { :controller => 'events', :action => 'create' } do |f| %>
    <%= render :partial => 'form', :locals => { :f => f } %>

    <%= f.submit "Create" %>
    <%= link_to 'Back to index', :controller => 'events', :action => 'index' %>
<% end %>

新增app/views/events/show.html.erb檔案,內容如下
<%= @event.title %>
<table border="0">
  <tr>
    <td><%= @event.public_date %></td>
    <td><%= @event.author %></td>
  </tr>
</table>
<%= simple_format(@event.description) %>

<p><%= link_to 'Back to index', :controller => 'events', :action => 'index' %></p>

新增app/views/events/edit.html.erb檔案,內容如下
<%= form_for @event, :url => { :controller => 'events', :action => 'update', :id => @event } do |f| %>
    <%= render :partial => 'form', :locals => { :f => f } %>
    <%= f.submit "Update" %>
    <%= link_to 'Back to index', :controller => 'events', :action => 'index' %>
<% end %>

修改app/views/layouts/application.html.erb檔案中的<title>
<title><%= @page_title || "Event application" %></title>
show頁面的title會顯示活動名稱。其他頁面因為沒有設定@page_title,就會是「Event application」。

因為new.html.erb和edit.html.erb的內容都相同,所以我們做個局部樣板(Partial Template),新增app/views/events/_form.html.erb檔案,內容如下
<div>
<%= f.label :title, "文章" %>
<%= f.text_field :title, size: "50" %>
</div>
<div>
<%= f.label :cnttype, "類別" %>
<%= f.select(:cnttype, [['公益計畫', 1], ['案例平台', 2]]) %>
</div>
<div>
<%= f.label :author, "作者/出處" %>
<%= f.text_field :author, size: "30" %>
</div>
<div>
<%= f.text_area :description, size: "60x20"  %>
</div>
<div>
<%= f.label :public_date, "公開日" %>
<%= f.date_field :public_date %>
</div>
<div>
<%= f.check_box :is_public %>
<%= f.label :is_public, "草稿" %>
</div>
<div>
<% if @event.errors.any? %>
      <ul>
      <% @event.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
<% end %>
</div>
http://guides.rubyonrails.org/form_helpers.html,各種form元件的寫法。

指令處安裝分頁元件
$ gem install kaminari

安裝完成後,在Gemfile檔加上兩行
# page kaminari
gem 'kaminari'
分頁就能使用了。

這樣就做出基本的讀取、新增、修改、刪除功能溜!