问:
How to handle data with two has_many associations
I'm new to Ruby on Rails. Just getting my head around modelling relationships and how to build CRUD with them. I'd like advice or suggestions on how to fix this problem.

In my system, a support user (student) has private support sessions (like classes) with their support worker (tutor). Here's how the system will be used: a support worker will log in, select a service user they work with, and record a support session, which includes things like how long the session lasted for and where it took place. Eventually, the system will produce time-sheets that can be used to invoice for the tutor's work in these private support sessions.

I'm not quite sure how to interact with this at a controller level. So far I've built my model and scaffolds - now I'm customising them.

I've been using the official tutorial to help me get started at: https://guides.rubyonrails.org/v3.2.8/getting_started.html but I think I've gone beyond that now.

```<code># Models
# Not entirely sure inverse_of is appropriate but several tutorials suggested it's worth putting in
class ServiceUser < ApplicationRecord
  has_many :support_sessions, inverse_of: :service_user
  has_many :support_workers, through: :support_sessions
end

class SupportWorker < ApplicationRecord
  has_many :support_sessions, inverse_of: :support_worker
  has_many :service_users, through: :support_sessions

class SupportSession < ApplicationRecord
  belongs_to :support_worker, inverse_of: :support_sessions
  belongs_to :service_user, inverse_of: :support_sessions
end

# Controller
class SupportSessionsController < ApplicationController
  # POST /support_sessions
  # POST /support_sessions.json
  def create
  # Auto-generated line:
  @support_session = SupportSession.new(support_session_params)

  # Get service_user_id from query string
  @service_user = ServiceUser.find(params[:service_user_id])

  # Lifted from RoR 'Getting started' article
  @support_session = @service_user.support_sessions.create(params[:service_user])

  respond_to do |format|
  if @support_session.save
  #format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
  format.html { redirect_to service_users_url, notice: 'Support session was successfully created.' }
  format.json { render :show, status: :created, location: @support_session }
  else
  format.html { render :new }
  format.json { render json: @support_session.errors, status: :unprocessable_entity }
  end
  end

  end
end

# Service user view/HTML form
# This is rendered as a partial on the service user's show.html.erb view
# select_support_workers() helper retrieves a list of ALL support workers in the system and the control value is the support_worker_id
<%= form_for([@service_user, @service_user.support_sessions.build]) do |f| %>
<tr>
  <td>
  <%= select_support_workers(f) %>
  </td>
  <td>
  <%= f.text_field :location %>
  </td>
  <td>
  <%= f.text_field :mode_of_delivery %>
  </td>
  <td>
  <%= f.text_field :started_at %>
  </td>
  <td>
  <%= f.text_field :ended_at %>
  </td>
  <td>
  <%= f.text_field :total_breaks %>
  </td>
  <td>
  <%= f.submit 'Save session' %>
  </td>
</tr>

<% end %>
</code>```

When I submit the form (which is being rendered as a partial on the service_user view show page), I seem to be ending up in the 'else' part of the if @support_session.save logic.

Error shown in my web browser is:

```<code>NameError in SupportSessions#create
Showing /Users/chris/git-local/timesheets/app/views/support_sessions/new.html.erb where line #5 raised:

undefined local variable or method `support_sessions_path' for #<#<Class:0x00007feb3412d028>:0x00007feb34163268>
Did you mean? @support_session
Extracted source (around line #5):

3 <%= render 'form', support_session: @support_session %>
4
5 <%= link_to 'Back', support_sessions_path %>

Rails.root: /Users/chris/git-local/timesheets

Application Trace | Framework Trace | Full Trace
app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb__485411543567831194_70324083953220'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'
Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"/xd16JX3LBjA7+9DVfnHwnJziucJkaICaWg/Sd6TK2rDOrugMcZu0r5qr6SO0TfqvXzzhBqvkydMIQqXp2NtrQ==",
 "support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""},
 "commit"=>"Save session",
 "service_user_id"=>"1"}
</code>```

Console output

```<code>Started GET "/service_users/" for ::1 at 2019-05-31 07:58:29 +0100
   (0.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  ↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:29 +0100
  Rendering service_users/index.html.erb within layouts/application
   (0.6ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  ↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  ServiceUser Load (0.7ms)  SELECT `service_users`.* FROM `service_users`
Processing by ServiceUsersController#show as HTML
  ↳ app/views/service_users/index.html.erb:22
  Parameters: {"id"=>"4"}
  Rendered service_users/index.html.erb within layouts/application (7.6ms)
  ServiceUser Load (2.4ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (0.9ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.2ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (7.5ms)
  Rendered service_users/show.html.erb within layouts/application (15.6ms)
Completed 200 OK in 94ms (Views: 91.2ms | ActiveRecord: 0.7ms)

Completed 200 OK in 115ms (Views: 105.7ms | ActiveRecord: 4.5ms)

Started GET "/service_users/" for ::1 at 2019-05-31 07:58:30 +0100
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:30 +0100
  Rendering service_users/index.html.erb within layouts/application
Processing by ServiceUsersController#show as HTML
  ServiceUser Load (1.5ms)  SELECT `service_users`.* FROM `service_users`
  Parameters: {"id"=>"4"}
  ↳ app/views/service_users/index.html.erb:22
  Rendered service_users/index.html.erb within layouts/application (5.9ms)
  ServiceUser Load (2.2ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (0.8ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.3ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (5.5ms)
  Rendered service_users/show.html.erb within layouts/application (12.1ms)
Completed 200 OK in 126ms (Views: 122.0ms | ActiveRecord: 1.5ms)

Completed 200 OK in 108ms (Views: 100.0ms | ActiveRecord: 4.3ms)

Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Processing by ServiceUsersController#show as HTML
  Parameters: {"id"=>"4"}
Processing by ServiceUsersController#show as HTML
  Parameters: {"id"=>"4"}
  ServiceUser Load (1.3ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  ServiceUser Load (1.5ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (1.5ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  SupportSession Load (0.7ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  Rendered collection of templates [0 times] (0.0ms)
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.4ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  SupportWorker Load (0.7ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (5.7ms)
  Rendered service_users/show.html.erb within layouts/application (11.7ms)
  Rendered support_sessions/_form.html.erb (5.8ms)
  Rendered service_users/show.html.erb within layouts/application (12.6ms)
Completed 200 OK in 80ms (Views: 71.4ms | ActiveRecord: 4.2ms)

Completed 200 OK in 82ms (Views: 74.2ms | ActiveRecord: 2.9ms)

Started POST "/service_users/4/support_sessions" for ::1 at 2019-05-31 07:58:35 +0100
Processing by SupportSessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KZGBtom/9t6vYu5FyPRq3xA3Xmb6hkzG8LEA7c/qmOkUZGmtslduK+l2as5chNz7w4ikC+5fHRYh3Ak2IZwIvA==", "support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""}, "commit"=>"Save session", "service_user_id"=>"4"}
  ServiceUser Load (0.5ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/support_sessions_controller.rb:33
   (0.3ms)  BEGIN
  ↳ app/controllers/support_sessions_controller.rb:36
   (0.3ms)  ROLLBACK
  ↳ app/controllers/support_sessions_controller.rb:36
   (0.2ms)  BEGIN
  ↳ app/controllers/support_sessions_controller.rb:41
   (0.2ms)  ROLLBACK
  ↳ app/controllers/support_sessions_controller.rb:41
  Rendering support_sessions/new.html.erb within layouts/application
  SupportWorker Load (0.5ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (3.9ms)
  Rendered support_sessions/new.html.erb within layouts/application (324.5ms)
Completed 500 Internal Server Error in 336ms (ActiveRecord: 2.0ms)

ActionView::Template::Error (undefined local variable or method `support_sessions_path' for #<#<Class:0x00007ffb0925c658>:0x00007ffb083fa100>
Did you mean?  @support_session):
    2:
    3: <%= render 'form', support_session: @support_session %>
    4:
    5: <%= link_to 'Back', support_sessions_path %>

app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb___2840892112036112501_70358075950960'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'

# Crebs:timesheets chris$ rake routes -c support_session
                           Prefix Verb   URI Pattern                                                         Controller#Action
    service_user_support_sessions GET    /service_users/:service_user_id/support_sessions(.:format)          support_sessions#index
                                  POST   /service_users/:service_user_id/support_sessions(.:format)          support_sessions#create
 new_service_user_support_session GET    /service_users/:service_user_id/support_sessions/new(.:format)      support_sessions#new
edit_service_user_support_session GET    /service_users/:service_user_id/support_sessions/:id/edit(.:format) support_sessions#edit
     service_user_support_session GET    /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#show
                                  PATCH  /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#update
                                  PUT    /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#update
                                  DELETE /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#destroy
</code>```

答:
Here's the code that got things working. Doesn't seem to work very well with validation but the data submits.</p>

```<code>def create
    #render plain: params[:support_session].inspect

    # Auto-generated line:
    #@support_session = SupportSession.new(support_session_params)

    # Get service_user_id from query string
    # This is so each new record submitted can get the id of the service_user in question
    @service_user = ServiceUser.find(params[:service_user_id])

    # Copied from RoR 'Getting started' article: https://guides.rubyonrails.org/getting_started.html
    # This calls the create method on @service_user.support_session (rather than @service_user alone)
    # so the link is made between the service_user and the support_session
    # Calls private method below to safeguard input parameters (only permitted ones)
    @support_session = @service_user.support_sessions.create(support_session_params)
    #redirect_to service_user_path(@service_user)

    respond_to do |format|
      if @support_session.save
      #if @support_session
      #if @service_user.support_sessions.create(support_session_params)
      #if @service_user.support_sessions.new(support_session_params)
        #format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
        format.html { redirect_to @service_user, notice: 'Support session was successfully created.' }
        format.json { render :show, status: :created, location: @support_session }
      else
        #format.html { render :show }
        format.html { redirect_to service_user_path(@service_user), notice: 'There was an error!' }
        format.json { render json: @support_session.errors, status: :unprocessable_entity }
      end
    end
  end
</code>```

Body:
I'm new to Ruby on Rails. Just getting my head around modelling relationships and how to build CRUD with them. I'd like advice or suggestions on how to fix this problem.

In my system, a support user (student) has private support sessions (like classes) with their support worker (tutor). Here's how the system will be used: a support worker will log in, select a service user they work with, and record a support session, which includes things like how long the session lasted for and where it took place. Eventually, the system will produce time-sheets that can be used to invoice for the tutor's work in these private support sessions.

I'm not quite sure how to interact with this at a controller level. So far I've built my model and scaffolds - now I'm customising them.

I've been using the official tutorial to help me get started at: https://guides.rubyonrails.org/v3.2.8/getting_started.html but I think I've gone beyond that now.

# Models
# Not entirely sure inverse_of is appropriate but several tutorials suggested it's worth putting in
class ServiceUser < ApplicationRecord
  has_many :support_sessions, inverse_of: :service_user
  has_many :support_workers, through: :support_sessions
end

class SupportWorker < ApplicationRecord
  has_many :support_sessions, inverse_of: :support_worker
  has_many :service_users, through: :support_sessions

class SupportSession < ApplicationRecord
  belongs_to :support_worker, inverse_of: :support_sessions
  belongs_to :service_user, inverse_of: :support_sessions
end

# Controller
class SupportSessionsController < ApplicationController
  # POST /support_sessions
  # POST /support_sessions.json
  def create
  # Auto-generated line:
  @support_session = SupportSession.new(support_session_params)

  # Get service_user_id from query string
  @service_user = ServiceUser.find(params[:service_user_id])

  # Lifted from RoR 'Getting started' article
  @support_session = @service_user.support_sessions.create(params[:service_user])

  respond_to do |format|
  if @support_session.save
  #format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
  format.html { redirect_to service_users_url, notice: 'Support session was successfully created.' }
  format.json { render :show, status: :created, location: @support_session }
  else
  format.html { render :new }
  format.json { render json: @support_session.errors, status: :unprocessable_entity }
  end
  end

  end
end

# Service user view/HTML form
# This is rendered as a partial on the service user's show.html.erb view
# select_support_workers() helper retrieves a list of ALL support workers in the system and the control value is the support_worker_id
<%= form_for([@service_user, @service_user.support_sessions.build]) do |f| %>

  <%= select_support_workers(f) %>

  <%= f.text_field :location %>

  <%= f.text_field :mode_of_delivery %>

  <%= f.text_field :started_at %>

  <%= f.text_field :ended_at %>

  <%= f.text_field :total_breaks %>

  <%= f.submit 'Save session' %>

<% end %>

When I submit the form (which is being rendered as a partial on the service_user view show page), I seem to be ending up in the 'else' part of the if @support_session.save logic.

Error shown in my web browser is:

NameError in SupportSessions#create
Showing /Users/chris/git-local/timesheets/app/views/support_sessions/new.html.erb where line #5 raised:

undefined local variable or method `support_sessions_path' for #<#<Class:0x00007feb3412d028>:0x00007feb34163268>
Did you mean? @support_session
Extracted source (around line #5):

3 <%= render 'form', support_session: @support_session %>
4
5 <%= link_to 'Back', support_sessions_path %>

Rails.root: /Users/chris/git-local/timesheets

Application Trace | Framework Trace | Full Trace
app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb__485411543567831194_70324083953220'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'
Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"/xd16JX3LBjA7+9DVfnHwnJziucJkaICaWg/Sd6TK2rDOrugMcZu0r5qr6SO0TfqvXzzhBqvkydMIQqXp2NtrQ==",
 "support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""},
 "commit"=>"Save session",
 "service_user_id"=>"1"}

Console output

Started GET "/service_users/" for ::1 at 2019-05-31 07:58:29 +0100
   (0.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  ↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:29 +0100
  Rendering service_users/index.html.erb within layouts/application
   (0.6ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
  ↳ /Users/chris/.rvm/gems/ruby-2.6.3/gems/activerecord-5.2.3/lib/active_record/log_subscriber.rb:98
  ServiceUser Load (0.7ms)  SELECT `service_users`.* FROM `service_users`
Processing by ServiceUsersController#show as HTML
  ↳ app/views/service_users/index.html.erb:22
  Parameters: {"id"=>"4"}
  Rendered service_users/index.html.erb within layouts/application (7.6ms)
  ServiceUser Load (2.4ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (0.9ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.2ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (7.5ms)
  Rendered service_users/show.html.erb within layouts/application (15.6ms)
Completed 200 OK in 94ms (Views: 91.2ms | ActiveRecord: 0.7ms)

Completed 200 OK in 115ms (Views: 105.7ms | ActiveRecord: 4.5ms)

Started GET "/service_users/" for ::1 at 2019-05-31 07:58:30 +0100
Processing by ServiceUsersController#index as HTML
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:30 +0100
  Rendering service_users/index.html.erb within layouts/application
Processing by ServiceUsersController#show as HTML
  ServiceUser Load (1.5ms)  SELECT `service_users`.* FROM `service_users`
  Parameters: {"id"=>"4"}
  ↳ app/views/service_users/index.html.erb:22
  Rendered service_users/index.html.erb within layouts/application (5.9ms)
  ServiceUser Load (2.2ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (0.8ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.3ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (5.5ms)
  Rendered service_users/show.html.erb within layouts/application (12.1ms)
Completed 200 OK in 126ms (Views: 122.0ms | ActiveRecord: 1.5ms)

Completed 200 OK in 108ms (Views: 100.0ms | ActiveRecord: 4.3ms)

Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Started GET "/service_users/4" for ::1 at 2019-05-31 07:58:34 +0100
Processing by ServiceUsersController#show as HTML
  Parameters: {"id"=>"4"}
Processing by ServiceUsersController#show as HTML
  Parameters: {"id"=>"4"}
  ServiceUser Load (1.3ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  ServiceUser Load (1.5ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/service_users_controller.rb:69
  Rendering service_users/show.html.erb within layouts/application
  Rendering service_users/show.html.erb within layouts/application
  SupportSession Load (1.5ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  ↳ app/views/service_users/show.html.erb:18
  SupportSession Load (0.7ms)  SELECT `support_sessions`.* FROM `support_sessions` WHERE `support_sessions`.`service_user_id` = 4
  Rendered collection of templates [0 times] (0.0ms)
  ↳ app/views/service_users/show.html.erb:18
  Rendered collection of templates [0 times] (0.0ms)
  SupportWorker Load (1.4ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  SupportWorker Load (0.7ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (5.7ms)
  Rendered service_users/show.html.erb within layouts/application (11.7ms)
  Rendered support_sessions/_form.html.erb (5.8ms)
  Rendered service_users/show.html.erb within layouts/application (12.6ms)
Completed 200 OK in 80ms (Views: 71.4ms | ActiveRecord: 4.2ms)

Completed 200 OK in 82ms (Views: 74.2ms | ActiveRecord: 2.9ms)

Started POST "/service_users/4/support_sessions" for ::1 at 2019-05-31 07:58:35 +0100
Processing by SupportSessionsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"KZGBtom/9t6vYu5FyPRq3xA3Xmb6hkzG8LEA7c/qmOkUZGmtslduK+l2as5chNz7w4ikC+5fHRYh3Ak2IZwIvA==", "support_session"=>{"support_worker_id"=>"3", "location"=>"", "mode_of_delivery"=>"", "started_at"=>"", "ended_at"=>"", "total_breaks"=>""}, "commit"=>"Save session", "service_user_id"=>"4"}
  ServiceUser Load (0.5ms)  SELECT  `service_users`.* FROM `service_users` WHERE `service_users`.`id` = 4 LIMIT 1
  ↳ app/controllers/support_sessions_controller.rb:33
   (0.3ms)  BEGIN
  ↳ app/controllers/support_sessions_controller.rb:36
   (0.3ms)  ROLLBACK
  ↳ app/controllers/support_sessions_controller.rb:36
   (0.2ms)  BEGIN
  ↳ app/controllers/support_sessions_controller.rb:41
   (0.2ms)  ROLLBACK
  ↳ app/controllers/support_sessions_controller.rb:41
  Rendering support_sessions/new.html.erb within layouts/application
  SupportWorker Load (0.5ms)  SELECT `support_workers`.* FROM `support_workers` ORDER BY `support_workers`.`given_name` ASC
  ↳ app/helpers/support_sessions_helper.rb:15
  Rendered support_sessions/_form.html.erb (3.9ms)
  Rendered support_sessions/new.html.erb within layouts/application (324.5ms)
Completed 500 Internal Server Error in 336ms (ActiveRecord: 2.0ms)

ActionView::Template::Error (undefined local variable or method `support_sessions_path' for #<#<Class:0x00007ffb0925c658>:0x00007ffb083fa100>
Did you mean?  @support_session):
    2:
    3: <%= render 'form', support_session: @support_session %>
    4:
    5: <%= link_to 'Back', support_sessions_path %>

app/views/support_sessions/new.html.erb:5:in `_app_views_support_sessions_new_html_erb___2840892112036112501_70358075950960'
app/controllers/support_sessions_controller.rb:46:in `block (2 levels) in create'
app/controllers/support_sessions_controller.rb:40:in `create'

# Crebs:timesheets chris$ rake routes -c support_session
                           Prefix Verb   URI Pattern                                                         Controller#Action
    service_user_support_sessions GET    /service_users/:service_user_id/support_sessions(.:format)          support_sessions#index
                                  POST   /service_users/:service_user_id/support_sessions(.:format)          support_sessions#create
 new_service_user_support_session GET    /service_users/:service_user_id/support_sessions/new(.:format)      support_sessions#new
edit_service_user_support_session GET    /service_users/:service_user_id/support_sessions/:id/edit(.:format) support_sessions#edit
     service_user_support_session GET    /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#show
                                  PATCH  /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#update
                                  PUT    /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#update
                                  DELETE /service_users/:service_user_id/support_sessions/:id(.:format)      support_sessions#destroy

Body:
Here's the code that got things working. Doesn't seem to work very well with validation but the data submits.

def create
    #render plain: params[:support_session].inspect

    # Auto-generated line:
    #@support_session = SupportSession.new(support_session_params)

    # Get service_user_id from query string
    # This is so each new record submitted can get the id of the service_user in question
    @service_user = ServiceUser.find(params[:service_user_id])

    # Copied from RoR 'Getting started' article: https://guides.rubyonrails.org/getting_started.html
    # This calls the create method on @service_user.support_session (rather than @service_user alone)
    # so the link is made between the service_user and the support_session
    # Calls private method below to safeguard input parameters (only permitted ones)
    @support_session = @service_user.support_sessions.create(support_session_params)
    #redirect_to service_user_path(@service_user)

    respond_to do |format|
      if @support_session.save
      #if @support_session
      #if @service_user.support_sessions.create(support_session_params)
      #if @service_user.support_sessions.new(support_session_params)
        #format.html { redirect_to @support_session, notice: 'Support session was successfully created.' }
        format.html { redirect_to @service_user, notice: 'Support session was successfully created.' }
        format.json { render :show, status: :created, location: @support_session }
      else
        #format.html { render :show }
        format.html { redirect_to service_user_path(@service_user), notice: 'There was an error!' }
        format.json { render json: @support_session.errors, status: :unprocessable_entity }
      end
    end
  end


来源: stackexchange

问:
how to use join table with like in codeigniter and also with multi column in like
how to use join table with like in codeigniter and also with multi column in like.

$search_input=$this->input->get('search_input', true);

```<code>   if($search_input!=''){

     $this->db->like('block.name','building.name' ,$search_input);

   }
   $tempdb = clone $this->db;
   $total_row=  $tempdb->from('block')->count_all_results();
   $this->db->limit($perpage, $page);
   $this->db->order_by("block.id", "desc");
  $this->db->join('building','building.id=block.building_name');

   $result = $this->db->select('block.id,block.name,building.name as building_name')->get('block')->result_array();
   $data=array();
   $data['block_data'] = $result;
</code>```

答:
try this code</p>

```<code>$this->db->group_start();
$this->db->like('block.name',$search_input);
$this->db->or_like('building.name', $search_input);
$this->db->group_end();
</code>```

ContentLicense: CC BY-SA 4.0

Body:
how to use join table with like in codeigniter and also with multi column in like.

$search_input=$this->input->get('search_input', true);

   if($search_input!=''){

     $this->db->like('block.name','building.name' ,$search_input);

   }
   $tempdb = clone $this->db;
   $total_row=  $tempdb->from('block')->count_all_results();
   $this->db->limit($perpage, $page);
   $this->db->order_by("block.id", "desc");
  $this->db->join('building','building.id=block.building_name');

   $result = $this->db->select('block.id,block.name,building.name as building_name')->get('block')->result_array();
   $data=array();
   $data['block_data'] = $result;

Body:
try this code

$this->db->group_start();
$this->db->like('block.name',$search_input);
$this->db->or_like('building.name', $search_input);
$this->db->group_end();


问:
anoter ajax function for another form not working
i have 2 form with different id (form_sign and form_login) and use ajax for submit it. form_sign working nice, but another form not working.

i was try to show alert when the function for form_login if form was submit, and it's work, but when i add ajax code for transaction form, ajax code not running. i was inspect the code element, but the browser not displayed the error

$(document).ready(function() {
  checkSame('#_password');
  checkChar('#password');

  $("#form_sign").on('submit', function(e) { // form 1
    e.preventDefault();
    let post_url = $(this).attr("action"); //get form action url
    let request_method = $(this).attr("method"); //get form GET/POST method
    let form_data = $(this).serialize(); //Encode form elements for submission

    $.ajax({
      url: post_url,
      type: request_method,
      data: form_data,
      success: function(data) {
        if (data == "success") {
          reseter("#form_sign");
          $('#massage').html("Save data success! silahkan login");
          $("#divMassage").fadeOut(5000);

        }
      }
    })
  });

  $("#form_login").on('submit', function(ev) { //form 2
    ev.preventDefault();
    let post_url = $(this).attr("action"); //get form action url
    let request_method = $(this).attr("method"); //get form GET/POST method
    let form_data = $(this).serialize(); //Encode form elements for submission
    // i put alert here, the alert run
    $.ajax({
      url: post_url,
      type: request_method,
      data: form_data,
      success: function(data) {

        alert("eee"); // this alert not run
      }
    })
  });
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<section class="content">
  <div class="row">
    <div class="col-md-5 col-md-offset-3">
      <div class="nav-tabs-custom" style=" box-shadow: 10px 10px 5px 5px #888888;">
        <ul class="nav nav-tabs">
          <li class="active" id="link_1"><b>Creat an Account</b></li>
          <li class="" id="link_2"><b>Login</b></li>
        </ul>
        <div class="tab-content">
          <div class="tab-pane active" id="tab_1">
            <form id="form_sign" role="form" action="<?php echo $see?>halaman/simaksi/creat-account.php" method="POST">
              <div class="box-body">
                <div class="form-group">
                  <label for="exampleInputEmail1">Username</label>
                  <input type="text" class="form-control" name="username" placeholder="Enter Username" required>
                </div>
                <div class="form-group">
                  <label for="exampleInputEmail1">Email address</label>
                  <input type="email" class="form-control" name="email" placeholder="Enter email" required>
                </div>
                <div class="form-group">
                  <label for="exampleInputEmail1">Password</label>
                  <input type="password" class="form-control" name="password" id="password" onkeyup="checkChar(this.id)" placeholder="Enter Magic Words" required>
                  <span id="mass1" class="text-red"></span>
                </div>
                <div class="form-group">
                  <label for="exampleInputEmail1">Retype Password</label>
                  <input type="password" class="form-control" name="_password" id="_password" onkeyup="checkSame(this.id)" placeholder="Retype Magic Words" required>
                  <span id="mass2" class="text-red"></span>
                </div>
                <div class="form-group">
                  <button type="submit" name="create" class="btn btn-lg btn-success btn-block" id="btn-submit" disabled>Create</button>
                  <button type="reset" class="btn btn-lg btn-warning btn-block">Clear</button>
                </div>
              </div>
            </form>
          </div>
          <!-- /.tab-pane -->
          <div class="tab-pane" id="tab_2">
            <form id="form_login" role="form" action="post" method="<?php echo $see?>halaman/simaksi/login-account.php">
              <div class="box-body">
                <div class="form-group">
                  <label for="exampleInputEmail1">Username</label>
                  <input type="text" class="form-control" name="user" placeholder="Enter Username" required>
                </div>
                <div class="form-group">
                  <label for="exampleInputEmail1">Password</label>
                  <input type="password" class="form-control" name="password" placeholder="Enter Magic Words" required>
                </div>
                <div class="form-group ">
                  <button type="submit" class="btn btn-lg btn-success btn-block" id="btn-login">Login</button>
                </div>
              </div>
            </form>
          </div>
          <!-- /.tab-pane -->
        </div>
        <!-- /.tab-content -->
      </div>
    </div>
  </div>
</section></code>```

I hope that 2 different forms can work well even though they are on the same page

sorry for my bad english
regards

答: You have your action and methods switched in the second form action="post" method="<?php echo $see?>halaman/simaksi/login-account.php">

Body:
i have 2 form with different id (form_sign and form_login) and use ajax for submit it. form_sign working nice, but another form not working.

i was try to show alert when the function for form_login if form was submit, and it's work, but when i add ajax code for transaction form, ajax code not running. i was inspect the code element, but the browser not displayed the error

$(document).ready(function() {
  checkSame('#_password');
  checkChar('#password');

  $("#form_sign").on('submit', function(e) { // form 1
    e.preventDefault();
    let post_url = $(this).attr("action"); //get form action url
    let request_method = $(this).attr("method"); //get form GET/POST method
    let form_data = $(this).serialize(); //Encode form elements for submission

    $.ajax({
      url: post_url,
      type: request_method,
      data: form_data,
      success: function(data) {
        if (data == "success") {
          reseter("#form_sign");
          $('#massage').html("Save data success! silahkan login");
          $("#divMassage").fadeOut(5000);

        }
      }
    })
  });

  $("#form_login").on('submit', function(ev) { //form 2
    ev.preventDefault();
    let post_url = $(this).attr("action"); //get form action url
    let request_method = $(this).attr("method"); //get form GET/POST method
    let form_data = $(this).serialize(); //Encode form elements for submission
    // i put alert here, the alert run
    $.ajax({
      url: post_url,
      type: request_method,
      data: form_data,
      success: function(data) {

        alert("eee"); // this alert not run
      }
    })
  });
});

Creat an Account

Login

            <form id="form_sign" role="form" action="<?php echo $see?>halaman/simaksi/creat-account.php" method="POST">

                  Username
                  <input type="text" class="form-control" name="username" placeholder="Enter Username" required>

                  Email address
                  <input type="email" class="form-control" name="email" placeholder="Enter email" required>

                  Password
                  <input type="password" class="form-control" name="password" id="password" onkeyup="checkChar(this.id)" placeholder="Enter Magic Words" required>

                  Retype Password
                  <input type="password" class="form-control" name="_password" id="_password" onkeyup="checkSame(this.id)" placeholder="Retype Magic Words" required>

                  <button type="submit" name="create" class="btn btn-lg btn-success btn-block" id="btn-submit" disabled>Create</button>
                  <button type="reset" class="btn btn-lg btn-warning btn-block">Clear</button>

            </form>

            <form id="form_login" role="form" action="post" method="<?php echo $see?>halaman/simaksi/login-account.php">

                  Username
                  <input type="text" class="form-control" name="user" placeholder="Enter Username" required>

                  Password
                  <input type="password" class="form-control" name="password" placeholder="Enter Magic Words" required>

                  <button type="submit" class="btn btn-lg btn-success btn-block" id="btn-login">Login</button>

            </form>

I hope that 2 different forms can work well even though they are on the same page

sorry for my bad english
regards


问:
How to make a splitscreen with a listview on one side
I want the right side of the activity to show different items depending which item of the listview on the left is selected. I was able to follow the Android ListView example where the listview  takes up the whole activity screen, but was unable to expand that to split screen. Here is my xml with the list view on the left and a simple button on the right for now. I'm having trouble figuring out the code that will populate my listview.

system_status.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
  <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/activity_system_status"
       android:title="@string/system_status"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:orientation="horizontal">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:layout_weight="1">

        <ListView
        android:id="@+id/my_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        </ListView>

    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:layout_weight="1">
        <ToggleButton android:text="ToggleButton" android:id="@+id/toggleButton1" android:layout_width="wrap_content" android:layout_height="wrap_content"></ToggleButton>
    </LinearLayout>
    </LinearLayout>
</code>```

UPDATE:
I figured it out with the help of Scythe's post. Here is the code that got it working. The xml above works as is.

```<code>public class SystemStatusActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ListView lv = (ListView) findViewById(R.id.my_list);
    String[] stats = getResources().getStringArray(R.array.array_system_status);
    lv.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, stats));
}
}
</code>```

list_item.xml:

```<code>     <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>
</code>```

答:
You have to set up and adapter for that ListView. Search for tutorials on creating custom Adapter classes, you can find dozens of those. You absolutely must understand custom adapters if you plan to develop for this platform.

But anyways, you can get away with the standard ArrayAdapter to get this to work:

```<code>String[] countries = <put your strings here>
yourList.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries));
</code>```

After this, set up an ItemClickListener for the list, and handle the content change on the right pane as needed.

ContentLicense: CC BY-SA 3.0

Body:
I want the right side of the activity to show different items depending which item of the listview on the left is selected. I was able to follow the Android ListView example where the listview  takes up the whole activity screen, but was unable to expand that to split screen. Here is my xml with the list view on the left and a simple button on the right for now. I'm having trouble figuring out the code that will populate my listview.

system_status.xml:

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/activity_system_status"
       android:title="@string/system_status"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:orientation="horizontal">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:layout_weight="1">

        <ListView
        android:id="@+id/my_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        </ListView>

    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical"
        android:layout_weight="1">
        <ToggleButton android:text="ToggleButton" android:id="@+id/toggleButton1" android:layout_width="wrap_content" android:layout_height="wrap_content"></ToggleButton>
    </LinearLayout>
    </LinearLayout>

UPDATE:
I figured it out with the help of Scythe's post. Here is the code that got it working. The xml above works as is.

public class SystemStatusActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ListView lv = (ListView) findViewById(R.id.my_list);
    String[] stats = getResources().getStringArray(R.array.array_system_status);
    lv.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, stats));
}
}

list_item.xml:

     <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:textSize="16sp" >
</TextView>

Body:
You have to set up and adapter for that ListView. Search for tutorials on creating custom Adapter classes, you can find dozens of those. You absolutely must understand custom adapters if you plan to develop for this platform.

But anyways, you can get away with the standard ArrayAdapter to get this to work:

String[] countries = <put your strings here>
yourList.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, countries));

After this, set up an ItemClickListener for the list, and handle the content change on the right pane as needed.


问:
Why do I needs login to access published data in Google Cloud Storage
I'd like to use Google Cloud Storage as image saver. I added "allUsers" on the rights.
I referred this page.
https://cloud.google.com/storage/docs/access-control/making-data-public

I can access the image from any account of logged in on google. But when I logout from google. I can't see the image. When I click the image of link, it's redirect to google login page.

Is it possible to access to the image without login?

ex: https://storage.cloud.google.com/image_maker_media/layout/square.png

答:
Yes. Link to publicly readable objects using one of these:

https://storage.googleapis.com/BUCKET_NAME/object_name

https://BUCKET_NAME.storage.googleapis.com/object_name

For example, your resource: http://storage.googleapis.com/image_maker_media/layout/square.png


问:
Multi-column file parsing with Kotlin
I have a four columns text file and want to create two vectors with it.
I intend to use the first and second columns as a mixed index.
So the first and second columns are integer and 3rd and 4th are double.
In FORTRAN it would be:

```<code>10 READ("4Column_file.txt",*,END=20)N,M,T1,T2
   IG=(N*(N+1))/2+M+1
   CC(IG)=T1
   CS(IG)=T2
   GOTO 10
20 CONTINUE
</code>```

How I do it with Kotlin or Java?

The input is in the form:

```<code>5   5  -0.244048470535508183D+00  -0.129800076712784507D+01
6   0  -0.468652527040705080D+01   0.000000000000000000D+00
</code>```

The output would be CC[IG] and CS[IG] vectors loaded.

For example in the first line:
 IG=(5*(5+1))/2+5+1=21
so CC[21]=-0.244048470535508183D+00 and CS[21]=-0.129800076712784507D+01.

In the second line:
 IG=(6*(6+1))/2+5+1=27
so CC[27]=-0.468652527040705080D+01 and CS[27]=0.000000000000000000D+00

答:
You can do this in Kotlin:

```<code>val length = 20 // Some default length
val cc = arrayOfNulls<String>(length)
val cs = arrayOfNulls<String>(length)

val lineRegex = "\\s+".toRegex()

File("4Column_file.txt").useLines { lineSequence ->
    for (line in lineSequence) {
        val (n, m, t1, t2) = line.split(lineRegex)
        val nInt = n.toInt()
        val mInt = m.toInt()

        val ig = (nInt * (nInt + 1)) / 2 + mInt + 1
        cc[ig] = t1
        cs[ig] = t2
    }
}
</code>```

If you don't know the length beforehand, you would need to read all the lines into some data class first. You then need find the maximum value of ig, and create the arrays of that size. Something like:

```<code>data class Row(val n: Int, val m: Int, val t1: String, val t2: String) {
    val ig: Int = (n * (n + 1)) / 2 + m + 1
}

// rowList is List<Row> after parsing
val maxIdx = rowList.maxBy { it.ig } ?: -1

val cc = arrayOfNulls<String>(maxIdx + 1)
val cs = arrayOfNulls<String>(maxIdx + 1)

for (row in rowList) {
    cc[row.ig] = row.t1
    cs[row.ig] = row.t2
}
</code>```

Title: Multi-column file parsing with Kotlin

Body:
I have a four columns text file and want to create two vectors with it.
I intend to use the first and second columns as a mixed index.
So the first and second columns are integer and 3rd and 4th are double.
In FORTRAN it would be:

10 READ("4Column_file.txt",*,END=20)N,M,T1,T2
   IG=(N*(N+1))/2+M+1
   CC(IG)=T1
   CS(IG)=T2
   GOTO 10
20 CONTINUE

How I do it with Kotlin or Java?

The input is in the form:

5   5  -0.244048470535508183D+00  -0.129800076712784507D+01
6   0  -0.468652527040705080D+01   0.000000000000000000D+00

The output would be CC[IG] and CS[IG] vectors loaded.

For example in the first line:
 IG=(5*(5+1))/2+5+1=21
so CC[21]=-0.244048470535508183D+00 and CS[21]=-0.129800076712784507D+01.

In the second line:
 IG=(6*(6+1))/2+5+1=27
so CC[27]=-0.468652527040705080D+01 and CS[27]=0.000000000000000000D+00

Body:
You can do this in Kotlin:

val length = 20 // Some default length
val cc = arrayOfNulls<String>(length)
val cs = arrayOfNulls<String>(length)

val lineRegex = "\\s+".toRegex()

File("4Column_file.txt").useLines { lineSequence ->
    for (line in lineSequence) {
        val (n, m, t1, t2) = line.split(lineRegex)
        val nInt = n.toInt()
        val mInt = m.toInt()

        val ig = (nInt * (nInt + 1)) / 2 + mInt + 1
        cc[ig] = t1
        cs[ig] = t2
    }
}

If you don't know the length beforehand, you would need to read all the lines into some data class first. You then need find the maximum value of ig, and create the arrays of that size. Something like:

data class Row(val n: Int, val m: Int, val t1: String, val t2: String) {
    val ig: Int = (n * (n + 1)) / 2 + m + 1
}

// rowList is List<Row> after parsing
val maxIdx = rowList.maxBy { it.ig } ?: -1

val cc = arrayOfNulls<String>(maxIdx + 1)
val cs = arrayOfNulls<String>(maxIdx + 1)

for (row in rowList) {
    cc[row.ig] = row.t1
    cs[row.ig] = row.t2
}


问:
Swift type of shuffle()
I want to test a function, passing in a shuffle function so I can Unit test the function adequately. In other words:

```<code>func testme(testArr: [Int], shufflefunction : Shufflefunction = .shuffle) -> [Int] {
    return tetsArr.shufflefunction
}
</code>```

I know the syntax is incorrect; and that is the question.

What is the correct type of the shuffled function so I can make a reusable function for any particular shuffle implementation, as passed in the function above.

The second part of the problem is how to pass the standard shuffle() implementation as a default parameter for testing this function.

答:
If you look at Array.shuffled, you will see that it is actually a function that takes an array, and returns a () -> [T]:

Therefore, the type of Array.shuffled could be written as

```<code>(([T]) -> (() -> [T]))
</code>```

We can then use this as our parameter type:

```<code>func testShuffle<T>(array: [T], function: (([T]) -> (() -> [T])) = Array.shuffled) {
    let shuffleFunction = function(array)
    let shuffledArray = shuffleFunction()
    // do stuff with shuffledArray...
}

// usage
extension Array {
    func myCustomShuffled() -> [Element] {
        // ...
    }
}

let arr = [1,2,3,4,5,6,7]
testShuffle(array: arr, function: Array.myCustomShuffled)
</code>```

Note that the same approach doesn't work with Array.shuffle (the mutating version), because Swift doesn't support partial applications on mutating functions.

You can also write the parameter type as ([T]) -> [T], then you would have to pass the default parameter like this:

```<code>func testShuffle<T>(array: [T], function: ([T]) -> [T] = { $0.shuffled() }) {
    let shuffledArray = function(array)
}
</code>```

Title: Swift type of shuffle()

Body:
I want to test a function, passing in a shuffle function so I can Unit test the function adequately. In other words:

func testme(testArr: [Int], shufflefunction : Shufflefunction = .shuffle) -> [Int] {
    return tetsArr.shufflefunction
}

I know the syntax is incorrect; and that is the question.

What is the correct type of the shuffled function so I can make a reusable function for any particular shuffle implementation, as passed in the function above.

The second part of the problem is how to pass the standard shuffle() implementation as a default parameter for testing this function.

Body:
If you look at Array.shuffled, you will see that it is actually a function that takes an array, and returns a () -> [T]:

Therefore, the type of Array.shuffled could be written as

(([T]) -> (() -> [T]))

We can then use this as our parameter type:

func testShuffle<T>(array: [T], function: (([T]) -> (() -> [T])) = Array.shuffled) {
    let shuffleFunction = function(array)
    let shuffledArray = shuffleFunction()
    // do stuff with shuffledArray...
}

// usage
extension Array {
    func myCustomShuffled() -> [Element] {
        // ...
    }
}

let arr = [1,2,3,4,5,6,7]
testShuffle(array: arr, function: Array.myCustomShuffled)

Note that the same approach doesn't work with Array.shuffle (the mutating version), because Swift doesn't support partial applications on mutating functions.

You can also write the parameter type as ([T]) -> [T], then you would have to pass the default parameter like this:

func testShuffle<T>(array: [T], function: ([T]) -> [T] = { $0.shuffled() }) {
    let shuffledArray = function(array)
}


问:
I want to display placeholder date as current date
I'm using date picker and when I open by default it will be the current date. But now I want to display placeholder date also as current date.

```<code>private func showDatePicker(_ sender: UITextField){
    datePickerView.datePickerMode = UIDatePicker.Mode.date
    sender.inputView = datePickerView
    let toolbar = UIToolbar();
    toolbar.sizeToFit()
    let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
    toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false) sender.inputAccessoryView = toolbar sender.inputView = datePickerView;
}

@objc func donedatePicker(){
    let formatter = DateFormatter()
    formatter.dateFormat = "dd/MM/yy"
    if (selectedDateField == 1){
        datePickerView.minimumDate = NSDate() as Date
        sOdateTxt.text = formatter.string(from:datePickerView.date)
        sOdateTxt.placeholder=formatter.string(from:datePickerView.date)
    } else if (selectedDateField == 2){
        datePickerView.minimumDate = NSDate() as Date
        sRdateTxt.text = formatter.string(from:datePickerView.date)
    } else if (selectedDateField == 3){
        datePickerView.minimumDate = NSDate() as Date
        sRecordedTxt.text = formatter.string(from:datePickerView.date)
    }
    self.view.endEditing(true)
}
@objc func cancelDatePicker(){
    self.view.endEditing(true)
}
</code>```

placeholder date should be as the current date

答:
Set placeholder for the textfields in viewDidLoad method with current date using Date()

```<code>override func viewDidLoad() {
    super.viewDidLoad()
    formatter.dateFormat = "dd/MM/yy"
    sOdateTxt.placeholder = formatter.string(from: Date())
    sRdateTxt.text = formatter.string(from: Date())
    sRecordedTxt.text = formatter.string(from: Date())
}
</code>```

You don't need to use NSDate() as Date to get current date. You can use Date()

Body:
I'm using date picker and when I open by default it will be the current date. But now I want to display placeholder date also as current date.

private func showDatePicker(_ sender: UITextField){
    datePickerView.datePickerMode = UIDatePicker.Mode.date
    sender.inputView = datePickerView
    let toolbar = UIToolbar();
    toolbar.sizeToFit()
    let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(donedatePicker));
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelDatePicker));
    toolbar.setItems([doneButton,spaceButton,cancelButton], animated: false) sender.inputAccessoryView = toolbar sender.inputView = datePickerView;
}

@objc func donedatePicker(){
    let formatter = DateFormatter()
    formatter.dateFormat = "dd/MM/yy"
    if (selectedDateField == 1){
        datePickerView.minimumDate = NSDate() as Date
        sOdateTxt.text = formatter.string(from:datePickerView.date)
        sOdateTxt.placeholder=formatter.string(from:datePickerView.date)
    } else if (selectedDateField == 2){
        datePickerView.minimumDate = NSDate() as Date
        sRdateTxt.text = formatter.string(from:datePickerView.date)
    } else if (selectedDateField == 3){
        datePickerView.minimumDate = NSDate() as Date
        sRecordedTxt.text = formatter.string(from:datePickerView.date)
    }
    self.view.endEditing(true)
}
@objc func cancelDatePicker(){
    self.view.endEditing(true)
}

placeholder date should be as the current date

Body:
Set placeholder for the textfields in viewDidLoad method with current date using Date()

override func viewDidLoad() {
    super.viewDidLoad()
    formatter.dateFormat = "dd/MM/yy"
    sOdateTxt.placeholder = formatter.string(from: Date())
    sRdateTxt.text = formatter.string(from: Date())
    sRecordedTxt.text = formatter.string(from: Date())
}

You don't need to use NSDate() as Date to get current date. You can use Date()


问:
Why scanf_s does not work anywhere other than visual studio?
When I use visual studio, it says "scanf is unsafe, try using scanf_s". But if I use scanf_s in gcc or other compilers, it doesn't work. Does scanf_s works only on visual studio? If so, why? The visual studio website says "scanf is unsafe". If it is unsafe, then why others still uses it?</p>

答:
As mentioned here

scanf_s is Microsoft-specific. Header is stdio.h but not in GCC.

As documented here

When reading a string with scanf, always specify a width for the %s format (for example, "%32s" instead of "%s"); otherwise, improperly formatted input can easily cause a buffer overrun.

  Alternately, consider using scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l or fgets.

See more at "Why didn't gcc implement _s functions?"

pmg adds in the comments that scanf_s() is Standard C11 (optional).

That means that activating c11 with gcc might be enough.

However Shawn adds:

IIRC, Microsoft's version doesn't follow the standard.

  Plus no other major C library vendor has bothered to implement Annex K, so it might as well be MS specific for all intents and purposes.

pmg confirms:

My gcc (version 6.3.0) does not recognize scanf_s() with gcc -std=c11 -pedantic ...


问:
Can I use ecmascript 6 in cocos2d JS?
Does cocos2d js support latest standard for javascript? I would like to use it in my project.</p>

答:
Cocos2d-js support some ES6 features but not all (Ex. Support: let, const, arrow function, Array.prototype.find, Array.prototype.findIndex. Not supported: default paramenter, class, etc).

You can also use ES6 and convert it to ES5 (using Babel). I found this on Cocos2d-x forum, you can take a look.

Title: Can I use ecmascript 6 in cocos2d JS?


问:
Invalid params in DynamoDB database query - Javascript - AWS
I'm using AWS to make database queries into dynamoDB with a Cognito user/IAM roles and policies.

It sounds like my parameters for my query into DynamoDB is not valid.

My Error: dynamodb.html:150 ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type

I've tried adding: ProjectionExpression: "name" because it's one of my attributes, but name is a reserved word apparently so I can't use that. Also I tried age instead because it is another attribute I have, but I get the same initial error as above. So I've deleted ProjectionExpression: altogether. Here is what I now have for my parameters:

```<code>var params = {
        ExpressionAttributeValues: {
            ":v1": {
                N: 123456788
            }
        },
        KeyConditionExpression: "userId = :v1",
        TableName: "user"
        };
</code>```

I'm not very sure how else to frame this. Please let me know what im missing or if there's any good documentation, as I'm kind of new to AWS. Thank you in advance!

EDIT:

The primary key is userId and the rest of the attributes for the table user are: age,bio,email,name in order.

Sign in and query with IAM role

```<code>var data2 = {
UserPoolId: 'xxxxxxxx',
ClientId: 'xxxxxxxx',
};

var userPool = new AmazonCognitoIdentity.CognitoUserPool(data2);
var cognitoUser = userPool.getCurrentUser();

var userData = {
    Username : 'xxxxxxxx',
    Pool : userPool
    };

var authenticationData = {
    Username : 'xxxxxxxx',
    Password : 'xxxxxxxx',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var cognitoUser2 = new AmazonCognitoIdentity.CognitoUser(userData);
   cognitoUser2.authenticateUser(authenticationDetails, {
       onSuccess: function (result) {
           var accessToken = result.getAccessToken().getJwtToken(); //user sign-in success and you can get accessToken and IdToken

       //POTENTIAL: Region needs to be set if not already set previously elsewhere.
           AWS.config.region = 'xxxxxxxx';

       AWS.config.credentials = new AWS.CognitoIdentityCredentials({
           IdentityPoolId : 'xxxxxxxx', // your identity pool id here
           Logins : {
               // Change the key below according to the specific region your user pool is in.
               // Here you need to map your idToken with your user pool domain for Cognito Identity Pool to generate a Identity with credential.
               'cognito-idp.xxxxxxxx.amazonaws.com/xxxxxxxx' : result.getIdToken().getJwtToken()
           }
       });

       //refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
       AWS.config.credentials.refresh((error) => {
           if (error) {
                console.error(error);
           } else {
               console.log('Successfully logged!');
        // Instantiate aws sdk service objects now that the credentials have been updated. So put your DynamoDB client here
        var docClient = new AWS.DynamoDB.DocumentClient({ region: AWS.config.region });
        var params = {

           ExpressionAttributeValues: {
                ":v1": {
                    N: 123456788
                }
            },
            KeyConditionExpression: "userId = :v1",
            TableName: "user"
            };
          docClient.query(params, function(err, data2) {
            if (err) {
                console.error(err);
            }else{
              console.log(data2);
            }
          });
               }
           });
       },
    onFailure: function(err) {
           alert(err.message || JSON.stringify(err));
       },
   });
</code>```

答:
Try using it without N in the ExpressionAttributeValues and use " for the user id value.

```<code>var params = {
        ExpressionAttributeValues: {
            ":v1": "123456788"
        },
        KeyConditionExpression: "userId = :v1",
        TableName: "user"
};
</code>```

Body:
I'm using AWS to make database queries into dynamoDB with a Cognito user/IAM roles and policies.

It sounds like my parameters for my query into DynamoDB is not valid.

My Error: dynamodb.html:150 ValidationException: One or more parameter values were invalid: Condition parameter type does not match schema type

I've tried adding: ProjectionExpression: "name" because it's one of my attributes, but name is a reserved word apparently so I can't use that. Also I tried age instead because it is another attribute I have, but I get the same initial error as above. So I've deleted ProjectionExpression: altogether. Here is what I now have for my parameters:

var params = {
        ExpressionAttributeValues: {
            ":v1": {
                N: 123456788
            }
        },
        KeyConditionExpression: "userId = :v1",
        TableName: "user"
        };

I'm not very sure how else to frame this. Please let me know what im missing or if there's any good documentation, as I'm kind of new to AWS. Thank you in advance!

EDIT:

The primary key is userId and the rest of the attributes for the table user are: age,bio,email,name in order.

Sign in and query with IAM role

var data2 = {
UserPoolId: 'xxxxxxxx',
ClientId: 'xxxxxxxx',
};

var userPool = new AmazonCognitoIdentity.CognitoUserPool(data2);
var cognitoUser = userPool.getCurrentUser();

var userData = {
    Username : 'xxxxxxxx',
    Pool : userPool
    };

var authenticationData = {
    Username : 'xxxxxxxx',
    Password : 'xxxxxxxx',
};
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var cognitoUser2 = new AmazonCognitoIdentity.CognitoUser(userData);
   cognitoUser2.authenticateUser(authenticationDetails, {
       onSuccess: function (result) {
           var accessToken = result.getAccessToken().getJwtToken(); //user sign-in success and you can get accessToken and IdToken

       //POTENTIAL: Region needs to be set if not already set previously elsewhere.
           AWS.config.region = 'xxxxxxxx';

       AWS.config.credentials = new AWS.CognitoIdentityCredentials({
           IdentityPoolId : 'xxxxxxxx', // your identity pool id here
           Logins : {
               // Change the key below according to the specific region your user pool is in.
               // Here you need to map your idToken with your user pool domain for Cognito Identity Pool to generate a Identity with credential.
               'cognito-idp.xxxxxxxx.amazonaws.com/xxxxxxxx' : result.getIdToken().getJwtToken()
           }
       });

       //refreshes credentials using AWS.CognitoIdentity.getCredentialsForIdentity()
       AWS.config.credentials.refresh((error) => {
           if (error) {
                console.error(error);
           } else {
               console.log('Successfully logged!');
        // Instantiate aws sdk service objects now that the credentials have been updated. So put your DynamoDB client here
        var docClient = new AWS.DynamoDB.DocumentClient({ region: AWS.config.region });
        var params = {

           ExpressionAttributeValues: {
                ":v1": {
                    N: 123456788
                }
            },
            KeyConditionExpression: "userId = :v1",
            TableName: "user"
            };
          docClient.query(params, function(err, data2) {
            if (err) {
                console.error(err);
            }else{
              console.log(data2);
            }
          });
               }
           });
       },
    onFailure: function(err) {
           alert(err.message || JSON.stringify(err));
       },
   });

Body:
Try using it without N in the ExpressionAttributeValues and use " for the user id value.

var params = {
        ExpressionAttributeValues: {
            ":v1": "123456788"
        },
        KeyConditionExpression: "userId = :v1",
        TableName: "user"
};


问:
Associate static IP to a Azure SQL server/database
I need to associate a public static IP address to points to an Azure SQL server, the server only has DNS name but doesn’t have IP address. I already tried Azure Load Balancer, Trafic Manager and DNS, and in any of the services there is an option to associate a static IP that point to the Data Base Name, for example the DB name is:  testnetmarksrv.database.windows.net
Any options…?</p>

答:
This architecture provides the answer Azure SQL Database gateway IP addresses .
The table with the Public IP addresses for each region is what you will need to use for your firewall configuration with the Public IP address of the gateway as the destination address on your firewall and also allowing traffic outbound on port 1433 as this is the only port that the gateway will listen on.
I performed a couple of test to ensure that mydatabase.windows.net resolves to the IP address displayed in the table and it seem to have worked for me. I dont know if this is the official record Microsoft has for listing the public IP addresses for their IP addresses as I could not see some of the newer data centers on that list. The other thing that you will need to do is to set your Azure SQL Datase connection to Proxy mode. The following powershell will set that.

Get SQL Server ID

```<code>$sqlserverid=(Get-AzSqlServer -ServerName sql-server-name -ResourceGroupName sql-server-group).ResourceId
</code>```

Set URI

```<code>$id="$sqlserverid/connectionPolicies/Default"
</code>```

Get current connection policy

```<code>(Get-AzResource -ResourceId $id).Properties.connectionType
</code>```

Update connection policy

```<code>Set-AzResource -ResourceId $id -Properties @{"connectionType" = "Proxy"} -f
</code>```

I am not sure about why you have a requirement to limit outbound SQL traffic but will urge you to also have a look at restricting inbound connections to your Azure SQL Databases.
This should be done on the Azure SQL Server that your Azure SQL Database lives on. Below are some resources to help to configure a Azure SQL Server firewall rule/s and provides a number of methods to set firewall rules including through the protal, through SQL and through the commandline.
Azure SQL Database and SQL Data Warehouse IP firewall rules

Hope this helps!

Body:
This architecture provides the answer Azure SQL Database gateway IP addresses .
The table with the Public IP addresses for each region is what you will need to use for your firewall configuration with the Public IP address of the gateway as the destination address on your firewall and also allowing traffic outbound on port 1433 as this is the only port that the gateway will listen on.
I performed a couple of test to ensure that mydatabase.windows.net resolves to the IP address displayed in the table and it seem to have worked for me. I dont know if this is the official record Microsoft has for listing the public IP addresses for their IP addresses as I could not see some of the newer data centers on that list. The other thing that you will need to do is to set your Azure SQL Datase connection to Proxy mode. The following powershell will set that.

Get SQL Server ID

$sqlserverid=(Get-AzSqlServer -ServerName sql-server-name -ResourceGroupName sql-server-group).ResourceId

Set URI

$id="$sqlserverid/connectionPolicies/Default"

Get current connection policy

(Get-AzResource -ResourceId $id).Properties.connectionType

Update connection policy

Set-AzResource -ResourceId $id -Properties @{"connectionType" = "Proxy"} -f

I am not sure about why you have a requirement to limit outbound SQL traffic but will urge you to also have a look at restricting inbound connections to your Azure SQL Databases.
This should be done on the Azure SQL Server that your Azure SQL Database lives on. Below are some resources to help to configure a Azure SQL Server firewall rule/s and provides a number of methods to set firewall rules including through the protal, through SQL and through the commandline.
Azure SQL Database and SQL Data Warehouse IP firewall rules

Hope this helps!


问:
In Woocommerce, How to find all products for which a certain product is a cross-sell?
In Woocommerce, I would like to get a list of products that a certain product is defined as a cross-sell for them.

So checking for which products B is a cross-sell would give: A, C

Didn't find any background for this

Example:
product A has products B, C as cross sells
Product B has products A, C, D as cross sells
Product C has products A, B, D as cross sells

So checking for which products B is a cross-sell would give: A, C

答:
You can do it with mysql query.

As WooCommerce stores crosssell IDs as serialized data - correct way seems to be reading all products via some WP loop and unserialize->analyze all crosssell IDs then search for the needed ID - but it would take too much time and memory.

That's why we need to find easier way - some trick. Here it is:

Assume ID of product A is 132, product B is 60, product C is 34.

And product A has 2 crosssell products - B and C.

So wp_postmeta table would have such row:

```<code>1098    132 _crosssell_ids  a:2:{i:0;i:60;i:1;i:34;}
</code>```

Product B present's in other products' crossell_ids meta data as a "i:60;" unique string. That's why we just need to look for that string acroos all wp_postmeta.

```<code>global $wpdb;
$product_b_id=60;

$product_that_have_B_as_crossell= $wpdb->get_col("select post_id
from $wpdb->postmeta
where
meta_key='_crosssell_ids'
and
meta_value like  '%i:".esc_sql($product_b_id).";%' ");

var_dump($product_that_have_B_as_crossell);
</code>```

Body:
You can do it with mysql query.

As WooCommerce stores crosssell IDs as serialized data - correct way seems to be reading all products via some WP loop and unserialize->analyze all crosssell IDs then search for the needed ID - but it would take too much time and memory.

That's why we need to find easier way - some trick. Here it is:

Assume ID of product A is 132, product B is 60, product C is 34.

And product A has 2 crosssell products - B and C.

So wp_postmeta table would have such row:

1098    132 _crosssell_ids  a:2:{i:0;i:60;i:1;i:34;}

Product B present's in other products' crossell_ids meta data as a "i:60;" unique string. That's why we just need to look for that string acroos all wp_postmeta.

global $wpdb;
$product_b_id=60;

$product_that_have_B_as_crossell= $wpdb->get_col("select post_id
from $wpdb->postmeta
where
meta_key='_crosssell_ids'
and
meta_value like  '%i:".esc_sql($product_b_id).";%' ");

var_dump($product_that_have_B_as_crossell);


问:
Add Event Method Is Adding Cell To Top, Not Bottom
I have the following method which is adding a cell to a tableview.  I want the added cell to be at the bottom, however right now it is adding it at the top.  Any suggestions?

addEvent method:

```<code>-(void)addEvent
{
    Routine *routine = (Routine *)[NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:managedObjectContext];

    routine.name=entered;

    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
        // Handle the error.
    }
    NSLog(@"%@", error);

    [eventsArray insertObject:routine atIndex:0];

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];

    [self.routineTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    [self.routineTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
     }
</code>```

ViewDidLoad

```<code>- (void)viewDidLoad
{
    if (managedObjectContext == nil)
    {
        managedObjectContext = [(CurlAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
    }

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil) {
        // Handle the error.
    }
    [self setEventsArray:mutableFetchResults];
    [mutableFetchResults release];
    [request release];

    UIBarButtonItem * addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showPrompt)];
    [self.navigationItem setLeftBarButtonItem:addButton];
    [addButton release];

    UIBarButtonItem *editButton = [[UIBarButtonItem alloc]initWithTitle:@"Edit" style:UIBarButtonItemStyleBordered target:self action:@selector(toggleEdit)];
    self.navigationItem.rightBarButtonItem = editButton;
    [editButton release];

    [super viewDidLoad];
}
</code>```

答:
Probably use [eventsArray addObject:] instead of insertObject:atIndex:

Also, you should be able to use [self.routineTableView reloadData]; rather than inserting rows manually -- assuming you've set up the table view controller in a normal way.

Body:
I have the following method which is adding a cell to a tableview.  I want the added cell to be at the bottom, however right now it is adding it at the top.  Any suggestions?

addEvent method:

-(void)addEvent
{
    Routine *routine = (Routine *)[NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:managedObjectContext];

    routine.name=entered;

    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
        // Handle the error.
    }
    NSLog(@"%@", error);

    [eventsArray insertObject:routine atIndex:0];

    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];

    [self.routineTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

    [self.routineTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
     }

ViewDidLoad

- (void)viewDidLoad
{
    if (managedObjectContext == nil)
    {
        managedObjectContext = [(CurlAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
    }

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil) {
        // Handle the error.
    }
    [self setEventsArray:mutableFetchResults];
    [mutableFetchResults release];
    [request release];

    UIBarButtonItem * addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showPrompt)];
    [self.navigationItem setLeftBarButtonItem:addButton];
    [addButton release];

    UIBarButtonItem *editButton = [[UIBarButtonItem alloc]initWithTitle:@"Edit" style:UIBarButtonItemStyleBordered target:self action:@selector(toggleEdit)];
    self.navigationItem.rightBarButtonItem = editButton;
    [editButton release];

    [super viewDidLoad];
}


问:
Prevent Lazy<T> caching exceptions when invoking Async delegate
I have a need for a simple AsyncLazy<T> which behaves exactly like Lazy<T> but correctly supports handling exceptions and avoids caching them.

Specifically the issue I am running into is as follows:

I can write a piece of code as such:

```<code>public class TestClass
{
    private int i = 0;

    public TestClass()
    {
        this.LazyProperty = new Lazy<string>(() =>
        {
            if (i == 0)
                throw new Exception("My exception");

            return "Hello World";

        }, LazyThreadSafetyMode.PublicationOnly);
    }

    public void DoSomething()
    {
        try
        {
            var res = this.LazyProperty.Value;
            Console.WriteLine(res);
            //Never gets here
        }
        catch { }
        i++;
        try
        {
            var res1 = this.LazyProperty.Value;
            Console.WriteLine(res1);
            //Hello World
        }
        catch { }

    }

    public Lazy<string> LazyProperty { get; }

}
</code>```

Note the use of LazyThreadSafetyMode.PublicationOnly.

If the initialization method throws an exception on any thread, the
  exception is propagated out of the Value property on that thread. The
  exception is not cached.

I then invoke it in the following way.

```<code>TestClass _testClass = new TestClass();
_testClass.DoSomething();
</code>```

and it works exactly as you would expect, where the first result is omitted because an exception occurs, the result remains uncached and the subsequent attempt to read the value succeeds returning 'Hello World'.

Unfortunately however if I change my code to something like this:

```<code>public Lazy<Task<string>> AsyncLazyProperty { get; } = new Lazy<Task<string>>(async () =>
{
    if (i == 0)
        throw new Exception("My exception");

    return await Task.FromResult("Hello World");
}, LazyThreadSafetyMode.PublicationOnly);
</code>```

The code fails the first time it is invoked and subsequent calls to the property are cached (and can therefore never recover).

This somewhat makes sense because I suspect that the exception is never actually bubbling up beyond the task, however what I cannot determine is a way to notify the Lazy<T> that the task/object initialisation has failed and should not be cached.

Anyone able to provide any input?

EDIT:

Thanks for your answer Ivan. I have successfully managed to get a basic example  with your feedback but it turns out my problem is actually more complicated than the basic example above demonstrates and undoubtedly this problem will affect others in a similar situation.

So if I change my property signature to something like this (as per Ivans suggestion)

```<code>this.LazyProperty = new Lazy<Task<string>>(() =>
{
    if (i == 0)
        throw new NotImplementedException();

    return DoLazyAsync();
}, LazyThreadSafetyMode.PublicationOnly);
</code>```

and then invoke it like this.

```<code>await this.LazyProperty.Value;
</code>```

the code works.

However if you have a method like this

```<code>this.LazyProperty = new Lazy<Task<string>>(() =>
{
    return ExecuteAuthenticationAsync();
}, LazyThreadSafetyMode.PublicationOnly);
</code>```

which then itself calls another Async method.

```<code>private static async Task<AccessTokenModel> ExecuteAuthenticationAsync()
{
    var response = await AuthExtensions.AuthenticateAsync();
    if (!response.Success)
        throw new Exception($"Could not authenticate {response.Error}");

    return response.Token;
}
</code>```

The Lazy caching bug manifests again and the problem can be reproduced.

Here is a complete example to reproduce the problem:

```<code>this.AccessToken = new Lazy<Task<string>>(() =>
{
    return OuterFunctionAsync(counter);
}, LazyThreadSafetyMode.PublicationOnly);

public Lazy<Task<string>> AccessToken { get; private set; }

private static async Task<bool> InnerFunctionAsync(int counter)
{
    await Task.Delay(1000);
    if (counter == 0)
        throw new InvalidOperationException();
    return false;
}

private static async Task<string> OuterFunctionAsync(int counter)
{
    bool res = await InnerFunctionAsync(counter);
    await Task.Delay(1000);
    return "12345";
}

try
{
    var r = await this.AccessToken.Value;
}
catch (Exception ex) { }

counter++;

try
{
    //Retry is never performed, cached task returned.
    var r1 = await this.AccessToken.Value;

}
catch (Exception ex) { }
</code>```

答:
To help you understand what's going on here is a simple program:

```<code>static void Main()
{
    var numberTask = GetNumberAsync( 0 );

    Console.WriteLine( numberTask.Status );
    Console.ReadLine();
}

private static async Task<Int32> GetNumberAsync( Int32 number )
{
    if ( number == 0 )
        throw new NotSupportedException();

    await Task.Delay( 1000 );

    return number;
}
</code>```

Try it out and you will see that the output of the program will be Faulted. The method is always returning a result which is Task which has captured the exception.

Why the capturing occurs? It occurs because of async modifier of the method. Under the covers the actual execution of the method uses AsyncMethodBuilder which captures the exception and sets it as a result of the task.

How can we change this?

```<code>private static Task<Int32> GetNumberAsync( Int32 number )
{
    if ( number == 0 )
        throw new NotSupportedException();

    return GetNumberReallyAsync();

    async Task<Int32> GetNumberReallyAsync()
    {
        await Task.Delay( 1000 );

        return number;
    }
}
</code>```

In this example you can see that the method doesn't have the async modifier and thus the exception is not captured as a faulted Task.

So for your example to work as you want, you need to remove async and await:

```<code>public Lazy<Task<string>> AsyncLazyProperty { get; } = new Lazy<Task<string>>(() =>
{
    if (i == 0)
        throw new Exception("My exception");

    return Task.FromResult("Hello World");
}, LazyThreadSafetyMode.PublicationOnly);
</code>```

Body:
I have a need for a simple AsyncLazy<T> which behaves exactly like Lazy<T> but correctly supports handling exceptions and avoids caching them.

Specifically the issue I am running into is as follows:

I can write a piece of code as such:

public class TestClass
{
    private int i = 0;

    public TestClass()
    {
        this.LazyProperty = new Lazy<string>(() =>
        {
            if (i == 0)
                throw new Exception("My exception");

            return "Hello World";

        }, LazyThreadSafetyMode.PublicationOnly);
    }

    public void DoSomething()
    {
        try
        {
            var res = this.LazyProperty.Value;
            Console.WriteLine(res);
            //Never gets here
        }
        catch { }
        i++;
        try
        {
            var res1 = this.LazyProperty.Value;
            Console.WriteLine(res1);
            //Hello World
        }
        catch { }

    }

    public Lazy<string> LazyProperty { get; }

}

Note the use of LazyThreadSafetyMode.PublicationOnly.

If the initialization method throws an exception on any thread, the
  exception is propagated out of the Value property on that thread. The
  exception is not cached.

I then invoke it in the following way.

TestClass _testClass = new TestClass();
_testClass.DoSomething();

and it works exactly as you would expect, where the first result is omitted because an exception occurs, the result remains uncached and the subsequent attempt to read the value succeeds returning 'Hello World'.

Unfortunately however if I change my code to something like this:

public Lazy<Task<string>> AsyncLazyProperty { get; } = new Lazy<Task<string>>(async () =>
{
    if (i == 0)
        throw new Exception("My exception");

    return await Task.FromResult("Hello World");
}, LazyThreadSafetyMode.PublicationOnly);

The code fails the first time it is invoked and subsequent calls to the property are cached (and can therefore never recover).

This somewhat makes sense because I suspect that the exception is never actually bubbling up beyond the task, however what I cannot determine is a way to notify the Lazy<T> that the task/object initialisation has failed and should not be cached.

Anyone able to provide any input?

EDIT:

Thanks for your answer Ivan. I have successfully managed to get a basic example  with your feedback but it turns out my problem is actually more complicated than the basic example above demonstrates and undoubtedly this problem will affect others in a similar situation.

So if I change my property signature to something like this (as per Ivans suggestion)

this.LazyProperty = new Lazy<Task<string>>(() =>
{
    if (i == 0)
        throw new NotImplementedException();

    return DoLazyAsync();
}, LazyThreadSafetyMode.PublicationOnly);

and then invoke it like this.

await this.LazyProperty.Value;

the code works.

However if you have a method like this

this.LazyProperty = new Lazy<Task<string>>(() =>
{
    return ExecuteAuthenticationAsync();
}, LazyThreadSafetyMode.PublicationOnly);

which then itself calls another Async method.

private static async Task<AccessTokenModel> ExecuteAuthenticationAsync()
{
    var response = await AuthExtensions.AuthenticateAsync();
    if (!response.Success)
        throw new Exception($"Could not authenticate {response.Error}");

    return response.Token;
}

The Lazy caching bug manifests again and the problem can be reproduced.

Here is a complete example to reproduce the problem:

this.AccessToken = new Lazy<Task<string>>(() =>
{
    return OuterFunctionAsync(counter);
}, LazyThreadSafetyMode.PublicationOnly);

public Lazy<Task<string>> AccessToken { get; private set; }

private static async Task<bool> InnerFunctionAsync(int counter)
{
    await Task.Delay(1000);
    if (counter == 0)
        throw new InvalidOperationException();
    return false;
}

private static async Task<string> OuterFunctionAsync(int counter)
{
    bool res = await InnerFunctionAsync(counter);
    await Task.Delay(1000);
    return "12345";
}

try
{
    var r = await this.AccessToken.Value;
}
catch (Exception ex) { }

counter++;

try
{
    //Retry is never performed, cached task returned.
    var r1 = await this.AccessToken.Value;

}
catch (Exception ex) { }

Body:
To help you understand what's going on here is a simple program:

static void Main()
{
    var numberTask = GetNumberAsync( 0 );

    Console.WriteLine( numberTask.Status );
    Console.ReadLine();
}

private static async Task<Int32> GetNumberAsync( Int32 number )
{
    if ( number == 0 )
        throw new NotSupportedException();

    await Task.Delay( 1000 );

    return number;
}

Try it out and you will see that the output of the program will be Faulted. The method is always returning a result which is Task which has captured the exception.

Why the capturing occurs? It occurs because of async modifier of the method. Under the covers the actual execution of the method uses AsyncMethodBuilder which captures the exception and sets it as a result of the task.

How can we change this?

private static Task<Int32> GetNumberAsync( Int32 number )
{
    if ( number == 0 )
        throw new NotSupportedException();

    return GetNumberReallyAsync();

    async Task<Int32> GetNumberReallyAsync()
    {
        await Task.Delay( 1000 );

        return number;
    }
}

In this example you can see that the method doesn't have the async modifier and thus the exception is not captured as a faulted Task.

So for your example to work as you want, you need to remove async and await:

public Lazy<Task<string>> AsyncLazyProperty { get; } = new Lazy<Task<string>>(() =>
{
    if (i == 0)
        throw new Exception("My exception");

    return Task.FromResult("Hello World");
}, LazyThreadSafetyMode.PublicationOnly);


问:
Logic behind show/hide rows in charts
I am confused about the logic that exists behind the showing and hiding of rows in charts of QlikView/QLik Sense. Here is what I thought was the case:

If, for some row, the value of a dimension is NULL, and for that dimension "Supress NULL" is on (QV) or "Include NULLs" is off(QS), then the row is not shown.

If, for some row, all its expressions/measures are zero or NULL, and the object-level setting "Supress Zero Values" is on (QV), or "Include Zero Values" is off (QS), then the row is not shown.

The rest of the rows are shown.

However, I get a confusing example of a measure which causes rows to disappear even though I have suppress zero values off/ inlude zero values on. Here is a small script of some sample customers and their consultation:

```<code>customer:
LOAD * INLINE [
custcode,descr
C1,pan1
C2,pan2
C3,pan3
];

consultation:
LOAD * INLINE [
custcode,grp,val,x
C2,eye,sth1,1
C2,age,20,1
C3,legs,sth2,1
C3,skin,sth5,1
C3,age,20,1
C3,age,30,1
];
</code>```

As you can see, custcode C1 has no consultation lines. I proceed to create a straight table with custcode as dimension and sum(x) as measure. Here is what I get:

```<code>+----------+--------+
| custcode | sum(x) |
+----------+--------+
| C1       |      0 |
| C2       |      2 |
| C3       |      4 |
+----------+--------+
</code>```

Everything fine until now. Sure enough I haven't supressed zero values: If I did, the C1 row would  get removed. Also, let's note that no aggr is needed for whatever reason.

Now, let's add a set analysis to that measure to only sum x for grp='age':

```<code>sum({<grp={'age'}>}x)
</code>```

This hides row C1 from sight:

```<code>+----------+-----------------------+
| custcode | sum({<grp={'age'}>}x) |
+----------+-----------------------+
| C2       |                     1 |
| C3       |                     2 |
+----------+-----------------------+
</code>```

Question 1: Why does set analysis hide the row in this case?

Adding an additional measure with a value of 1 changes nothing. We can be sure this has nothing to do with zero values settings.

Now, let us add this measure:

```<code>aggr(min(0),[custcode])
</code>```

The row got back, even though the new measure is NULL :

```<code>+----------+-----------------------+-------------------------+
| custcode | sum({<grp={'age'}>}x) | aggr(min(0),[custcode]) |
+----------+-----------------------+-------------------------+
| C1       |                     0 |                       - |
| C2       |                     1 |                       - |
| C3       |                     2 |                       - |
+----------+-----------------------+-------------------------+
</code>```

Now, about aggr, here are two strong reasons why I think it should not be neccessary:

If the set analysis measure was wrong and needed to include aggr in some way, this would still be no reason for the engine to hide the rows - it would just return a NULL for having an invalid formula. Also, this measure actually works correct, as we can see

custcode is the field which creates the association between the two tables. But this doesn't seem to be the cause for it to unhide rows; actually, I get the same even with aggr(min(0),[]):

```<code>+----------+-----------------------+-----------------+
| custcode | sum({<grp={'age'}>}x) | aggr(min(0),[]) |
+----------+-----------------------+-----------------+
| C1       |                     0 |               - |
| C2       |                     1 |               - |
| C3       |                     2 |               - |
+----------+-----------------------+-----------------+
</code>```

Question 2: Why does this strange aggr measure unhide the row?

答:
Question 1:
When you only have the one expression and add the set analysis it is like telling Qlik to select the set value.
So picture 1 no selections

picture 2 with the selection

So it's not that the answer is a null, it is that the associative engine has reduced that data out of the data set based on the selection / set rule.

The aggr() should definitely not be necessary there. The dimentionality of the chart will take care of the aggregation across the dimension. aggr() is only needed when you want to use an aggregation that is not controlled by the dimensions.

I do not understand what your aggr(min(0),[]) is trying to achieve and I don;'t get the same result as your table. The expression is just creating nulls because it is can't evaluate

If you want to see all members of the dimension you should tick "Show all values" on the dimensions tab rather than trying to change the expressions

Title: Logic behind show/hide rows in charts

Body:
I am confused about the logic that exists behind the showing and hiding of rows in charts of QlikView/QLik Sense. Here is what I thought was the case:

If, for some row, the value of a dimension is NULL, and for that dimension "Supress NULL" is on (QV) or "Include NULLs" is off(QS), then the row is not shown.

If, for some row, all its expressions/measures are zero or NULL, and the object-level setting "Supress Zero Values" is on (QV), or "Include Zero Values" is off (QS), then the row is not shown.

The rest of the rows are shown.

However, I get a confusing example of a measure which causes rows to disappear even though I have suppress zero values off/ inlude zero values on. Here is a small script of some sample customers and their consultation:

customer:
LOAD * INLINE [
custcode,descr
C1,pan1
C2,pan2
C3,pan3
];

consultation:
LOAD * INLINE [
custcode,grp,val,x
C2,eye,sth1,1
C2,age,20,1
C3,legs,sth2,1
C3,skin,sth5,1
C3,age,20,1
C3,age,30,1
];

As you can see, custcode C1 has no consultation lines. I proceed to create a straight table with custcode as dimension and sum(x) as measure. Here is what I get:

+----------+--------+
| custcode | sum(x) |
+----------+--------+
| C1       |      0 |
| C2       |      2 |
| C3       |      4 |
+----------+--------+

Everything fine until now. Sure enough I haven't supressed zero values: If I did, the C1 row would  get removed. Also, let's note that no aggr is needed for whatever reason.

Now, let's add a set analysis to that measure to only sum x for grp='age':

sum({<grp={'age'}>}x)

This hides row C1 from sight:

+----------+-----------------------+
| custcode | sum({<grp={'age'}>}x) |
+----------+-----------------------+
| C2       |                     1 |
| C3       |                     2 |
+----------+-----------------------+

Question 1: Why does set analysis hide the row in this case?

Adding an additional measure with a value of 1 changes nothing. We can be sure this has nothing to do with zero values settings.

Now, let us add this measure:

aggr(min(0),[custcode])

The row got back, even though the new measure is NULL :

+----------+-----------------------+-------------------------+
| custcode | sum({<grp={'age'}>}x) | aggr(min(0),[custcode]) |
+----------+-----------------------+-------------------------+
| C1       |                     0 |                       - |
| C2       |                     1 |                       - |
| C3       |                     2 |                       - |
+----------+-----------------------+-------------------------+

Now, about aggr, here are two strong reasons why I think it should not be neccessary:

If the set analysis measure was wrong and needed to include aggr in some way, this would still be no reason for the engine to hide the rows - it would just return a NULL for having an invalid formula. Also, this measure actually works correct, as we can see

custcode is the field which creates the association between the two tables. But this doesn't seem to be the cause for it to unhide rows; actually, I get the same even with aggr(min(0),[]):

+----------+-----------------------+-----------------+
| custcode | sum({<grp={'age'}>}x) | aggr(min(0),[]) |
+----------+-----------------------+-----------------+
| C1       |                     0 |               - |
| C2       |                     1 |               - |
| C3       |                     2 |               - |
+----------+-----------------------+-----------------+

Question 2: Why does this strange aggr measure unhide the row?