问:
Jumping scrolling when switching fragments
Inside a ScrollView I am dynamically switching between two fragments with different heights.
Unfortunately that leads to jumping. One can see it in the following animation:

I am scrolling down until I reach the button "show yellow".

Pressing "show yellow" replaces a huge blue fragment with a tiny yellow fragment. When this happens, both buttons jump down to the end of the screen.

I want both buttons to stay at the same position when switching to the yellow fragment. How can that be done?

Source code available at https://github.com/wondering639/stack-dynamiccontent respectively https://github.com/wondering639/stack-dynamiccontent.git

Relevant code snippets:

activity_main.xml

```<code><?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/myScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="800dp"
        android:background="@color/colorAccent"
        android:text="@string/long_text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_fragment1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:text="show blue"
        app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <Button
        android:id="@+id/button_fragment2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="show yellow"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button_fragment1"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button_fragment2">

    </FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
</code>```

MainActivity.kt

```<code>package com.example.dynamiccontent

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // onClick handlers
        findViewById<Button>(R.id.button_fragment1).setOnClickListener {
            insertBlueFragment()
        }

        findViewById<Button>(R.id.button_fragment2).setOnClickListener {
            insertYellowFragment()
        }

        // by default show the blue fragment
        insertBlueFragment()
    }

    private fun insertYellowFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, YellowFragment())
        transaction.commit()
    }

    private fun insertBlueFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, BlueFragment())
        transaction.commit()
    }

}
</code>```

fragment_blue.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#0000ff"
tools:context=".BlueFragment" />
</code>```

fragment_yellow.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#ffff00"
tools:context=".YellowFragment" />
</code>```

HINT

Please note that this is of course a minimum working example to show off my issue. In my real project, I also have views below the @+id/fragment_container. So giving a fixed size to @+id/fragment_container is not an option for me - it would cause a large blank area when switching to the low, yellow fragment.

UPDATE: Overview of proposed solutions

I implemented the proposed solutions for testing purposes and added my personal experiences with them.

answer by Cheticamp, https://stackoverflow.com/a/60323255

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60323255

-> FrameLayout wraps content, short code

answer by Pavneet_Singh, https://stackoverflow.com/a/60310807

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60310807

-> FrameLayout gets the size of the blue fragment. So no content wrapping. When switching to the yellow fragment, there's a gap between it and the content following it (if any content follows it). No additional rendering though!
** update ** a second version was provided showing how to do it without gaps. Check the comments to the answer.

answer by Ben P., https://stackoverflow.com/a/60251036

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60251036

-> FrameLayout wraps content. More code than the solution by Cheticamp. Touching the "show yellow" button twice leads to a "bug" (buttons jump down to the bottom, actually my original issue). One could argue about just disabling the "show yellow" button after switching to it, so I wouldn't consider this a real issue.

答:
Update: To keep the other views right below the framelayout and to handle the scenario automatically, we need to use onMeasure to implement the auto-handling so do the following steps

• Create a custom ConstraintLayout as (or can use MaxHeightFrameConstraintLayout lib):

```<code>import android.content.Context
import android.os.Build
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
import kotlin.math.max

/**
 * Created by Pavneet_Singh on 2020-02-23.
 */

class MaxHeightConstraintLayout @kotlin.jvm.JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr){

    private var _maxHeight: Int = 0

    // required to support the minHeight attribute
    private var _minHeight = attrs?.getAttributeValue(
        "http://schemas.android.com/apk/res/android",
        "minHeight"
    )?.substringBefore(".")?.toInt() ?: 0

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            _minHeight = minHeight
        }

        var maxValue = max(_maxHeight, max(height, _minHeight))

        if (maxValue != 0 && && maxValue > minHeight) {
            minHeight = maxValue
        }
        _maxHeight = maxValue
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

}
</code>```

and use it in your layout in place of ConstraintLayout

```<code><?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.pavneet_singh.temp.MaxHeightConstraintLayout
        android:id="@+id/constraint"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="800dp"
            android:background="@color/colorAccent"
            android:text="Some long text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button_fragment1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:text="show blue"
            app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show yellow"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toEndOf="@+id/button_fragment1"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show green"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toEndOf="@+id/button_fragment2"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/button_fragment3" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="additional text\nMore data"
            android:textSize="24dp"
            app:layout_constraintTop_toBottomOf="@+id/fragment_container" />

    </com.example.pavneet_singh.temp.MaxHeightConstraintLayout>

</androidx.core.widget.NestedScrollView>
</code>```

This will keep track of height and apply it during every fragment change.

Output:

Note: As mentioned in comments before, setting minHeight will result in additional rendering pass and it cannot be avoided in the current version of ConstraintLayout.

Old approach with custom FrameLayout

This is an interesting requirement and my approach is to solve it by creating a custom view.

Idea:

My idea for the solution is to adjust the height of the container by keeping the track of the largest child or total height of children in the container.

Attempts:

My first few attempts were based on modifying the existing behaviour of NestedScrollView by extending it but it doesn't provide access to all the necessary data or methods. Customisation resulted in poor support for all scenarios and edge cases.

Later, I achieved the solution by creating a custom Framelayout with different approach.

Solution Implementation

While implementing the custom behaviour of height measurement phases, I dug deeper and manipulated the height with getSuggestedMinimumHeight while tracking the height of children to implement the most optimised solution as it will not cause any additional or explicit rendering because it will manage the height during the internal rendering cycle so create a custom FrameLayout class to implement the solution and override the getSuggestedMinimumHeight as:

```<code>class MaxChildHeightFrameLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // to keep track of max height
    private var maxHeight: Int = 0

    // required to get support the minHeight attribute
    private val minHeight = attrs?.getAttributeValue(
        "http://schemas.android.com/apk/res/android",
        "minHeight"
    )?.substringBefore(".")?.toInt() ?: 0

    override fun getSuggestedMinimumHeight(): Int {
        var maxChildHeight = 0
        for (i in 0 until childCount) {
            maxChildHeight = max(maxChildHeight, getChildAt(i).measuredHeight)
        }
        if (maxHeight != 0 && layoutParams.height < (maxHeight - maxChildHeight) && maxHeight > maxChildHeight) {
            return maxHeight
        } else if (maxHeight == 0 || maxHeight < maxChildHeight) {
            maxHeight = maxChildHeight
        }
        return if (background == null) minHeight else max(
            minHeight,
            background.minimumHeight
        )
    }

}
</code>```

Now replace the FrameLayout with MaxChildHeightFrameLayout in activity_main.xml as:

```<code><?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="800dp"
            android:background="@color/colorAccent"
            android:text="Some long text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button_fragment1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:text="show blue"
            app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show yellow"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/button_fragment1"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <com.example.pavneet_singh.temp.MaxChildHeightFrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:minHeight="2dp"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@+id/button_fragment2"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</code>```

getSuggestedMinimumHeight() will be used to calculate the height of the view during the view rendering lifecycle.

Output:

With more views, fragment and different height. (400dp, 20dp, 500dp respectively)

Body:
Inside a ScrollView I am dynamically switching between two fragments with different heights.
Unfortunately that leads to jumping. One can see it in the following animation:

I am scrolling down until I reach the button "show yellow".

Pressing "show yellow" replaces a huge blue fragment with a tiny yellow fragment. When this happens, both buttons jump down to the end of the screen.

I want both buttons to stay at the same position when switching to the yellow fragment. How can that be done?

Source code available at https://github.com/wondering639/stack-dynamiccontent respectively https://github.com/wondering639/stack-dynamiccontent.git

Relevant code snippets:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/myScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="0dp"
        android:layout_height="800dp"
        android:background="@color/colorAccent"
        android:text="@string/long_text"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_fragment1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:text="show blue"
        app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <Button
        android:id="@+id/button_fragment2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="show yellow"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button_fragment1"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/button_fragment2">

    </FrameLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt

package com.example.dynamiccontent

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // onClick handlers
        findViewById<Button>(R.id.button_fragment1).setOnClickListener {
            insertBlueFragment()
        }

        findViewById<Button>(R.id.button_fragment2).setOnClickListener {
            insertYellowFragment()
        }

        // by default show the blue fragment
        insertBlueFragment()
    }

    private fun insertYellowFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, YellowFragment())
        transaction.commit()
    }

    private fun insertBlueFragment() {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.fragment_container, BlueFragment())
        transaction.commit()
    }

}

fragment_blue.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#0000ff"
tools:context=".BlueFragment" />

fragment_yellow.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#ffff00"
tools:context=".YellowFragment" />

HINT

Please note that this is of course a minimum working example to show off my issue. In my real project, I also have views below the @+id/fragment_container. So giving a fixed size to @+id/fragment_container is not an option for me - it would cause a large blank area when switching to the low, yellow fragment.

UPDATE: Overview of proposed solutions

I implemented the proposed solutions for testing purposes and added my personal experiences with them.

answer by Cheticamp, https://stackoverflow.com/a/60323255

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60323255

-> FrameLayout wraps content, short code

answer by Pavneet_Singh, https://stackoverflow.com/a/60310807

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60310807

-> FrameLayout gets the size of the blue fragment. So no content wrapping. When switching to the yellow fragment, there's a gap between it and the content following it (if any content follows it). No additional rendering though!
** update ** a second version was provided showing how to do it without gaps. Check the comments to the answer.

answer by Ben P., https://stackoverflow.com/a/60251036

-> available in https://github.com/wondering639/stack-dynamiccontent/tree/60251036

-> FrameLayout wraps content. More code than the solution by Cheticamp. Touching the "show yellow" button twice leads to a "bug" (buttons jump down to the bottom, actually my original issue). One could argue about just disabling the "show yellow" button after switching to it, so I wouldn't consider this a real issue.

Body:
Update: To keep the other views right below the framelayout and to handle the scenario automatically, we need to use onMeasure to implement the auto-handling so do the following steps

• Create a custom ConstraintLayout as (or can use MaxHeightFrameConstraintLayout lib):

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
import kotlin.math.max

/**
 * Created by Pavneet_Singh on 2020-02-23.
 */

class MaxHeightConstraintLayout @kotlin.jvm.JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr){

    private var _maxHeight: Int = 0

    // required to support the minHeight attribute
    private var _minHeight = attrs?.getAttributeValue(
        "http://schemas.android.com/apk/res/android",
        "minHeight"
    )?.substringBefore(".")?.toInt() ?: 0

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            _minHeight = minHeight
        }

        var maxValue = max(_maxHeight, max(height, _minHeight))

        if (maxValue != 0 && && maxValue > minHeight) {
            minHeight = maxValue
        }
        _maxHeight = maxValue
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

}

and use it in your layout in place of ConstraintLayout

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.pavneet_singh.temp.MaxHeightConstraintLayout
        android:id="@+id/constraint"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="800dp"
            android:background="@color/colorAccent"
            android:text="Some long text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button_fragment1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:text="show blue"
            app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show yellow"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toEndOf="@+id/button_fragment1"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show green"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.3"
            app:layout_constraintStart_toEndOf="@+id/button_fragment2"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <FrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@id/button_fragment3" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="additional text\nMore data"
            android:textSize="24dp"
            app:layout_constraintTop_toBottomOf="@+id/fragment_container" />

    </com.example.pavneet_singh.temp.MaxHeightConstraintLayout>

</androidx.core.widget.NestedScrollView>

This will keep track of height and apply it during every fragment change.

Output:

Note: As mentioned in comments before, setting minHeight will result in additional rendering pass and it cannot be avoided in the current version of ConstraintLayout.

Old approach with custom FrameLayout

This is an interesting requirement and my approach is to solve it by creating a custom view.

Idea:

My idea for the solution is to adjust the height of the container by keeping the track of the largest child or total height of children in the container.

Attempts:

My first few attempts were based on modifying the existing behaviour of NestedScrollView by extending it but it doesn't provide access to all the necessary data or methods. Customisation resulted in poor support for all scenarios and edge cases.

Later, I achieved the solution by creating a custom Framelayout with different approach.

Solution Implementation

While implementing the custom behaviour of height measurement phases, I dug deeper and manipulated the height with getSuggestedMinimumHeight while tracking the height of children to implement the most optimised solution as it will not cause any additional or explicit rendering because it will manage the height during the internal rendering cycle so create a custom FrameLayout class to implement the solution and override the getSuggestedMinimumHeight as:

class MaxChildHeightFrameLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // to keep track of max height
    private var maxHeight: Int = 0

    // required to get support the minHeight attribute
    private val minHeight = attrs?.getAttributeValue(
        "http://schemas.android.com/apk/res/android",
        "minHeight"
    )?.substringBefore(".")?.toInt() ?: 0

    override fun getSuggestedMinimumHeight(): Int {
        var maxChildHeight = 0
        for (i in 0 until childCount) {
            maxChildHeight = max(maxChildHeight, getChildAt(i).measuredHeight)
        }
        if (maxHeight != 0 && layoutParams.height < (maxHeight - maxChildHeight) && maxHeight > maxChildHeight) {
            return maxHeight
        } else if (maxHeight == 0 || maxHeight < maxChildHeight) {
            maxHeight = maxChildHeight
        }
        return if (background == null) minHeight else max(
            minHeight,
            background.minimumHeight
        )
    }

}

Now replace the FrameLayout with MaxChildHeightFrameLayout in activity_main.xml as:

<?xml version="1.0" encoding="utf-8"?>

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/myScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="800dp"
            android:background="@color/colorAccent"
            android:text="Some long text"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/button_fragment1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:text="show blue"
            app:layout_constraintEnd_toStartOf="@+id/button_fragment2"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <Button
            android:id="@+id/button_fragment2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            android:text="show yellow"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/button_fragment1"
            app:layout_constraintTop_toBottomOf="@+id/textView" />

        <com.example.pavneet_singh.temp.MaxChildHeightFrameLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:minHeight="2dp"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toBottomOf="@+id/button_fragment2"/>

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

getSuggestedMinimumHeight() will be used to calculate the height of the view during the view rendering lifecycle.

Output:

With more views, fragment and different height. (400dp, 20dp, 500dp respectively)


来源: stackexchange

问:
Running webdriver.io on vsts/Tfs build
I have some webdriver.io tests, and the current build system we use is not jenkins, but microsoft Tfs or vsts. Is there a way to run these on that build system as part of Continuous integration and continuous deployment?</p>

答:
Assuming your webdriverio is using javascript(mocha framework), on Azure DevOps (same as old TFS), Create a new pipeline to run NodeJS, follow these steps in this link: https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/javascript?view=azure-devops

With just a pipeline, I can run my webdriverio mocha-framework tests on the microsoft vm already without setting up extra build environment.

Next, you can add a trigger to your pipeline so it will get kicked off after another pipeline build complete.

ContentLicense: CC BY-SA 4.0

Title: Running webdriver.io on vsts/Tfs build


问:
Is it possible to set Chart options through the Google Sheets API?
I am able to update a "stacked area chart", however I cannot figure out how to set "Treat labels as text" on the Horizontal axis.  (This is done in the UI by clicking "Edit Chart -> Customize -> Horizontal axis -> Treat labels as text")

Does anyone know a way to do this with Sheets API?  Is there another way?

Thanks!!

答:
You want to set Treat labels as text of the chart in the Google Spreadsheet.

You want to achieve this using Sheets API.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Issue and workaround:

Unfortunately, I couldn't find the property for setting Treat labels as text in the request body. And I prepare 2 patterns of the checked Treat labels as text and the unchecked Treat labels as text, and when both patterns are compared with the chart object retrieved with the method of spreadsheets.get, I could find no differences for both. By this, I thought that in the current stage, there is no method for setting Treat labels as text in Sheets API.

So as one of several workarounds, here, I would like to propose to use Web Apps as an API. When Google Apps Script is used, Treat labels as text can be set. This workaround uses this.

Usage:

The usage of this workaround is as follows.

1. Create new project of Google Apps Script.

Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.

If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.

2. Copy and paste script.

Please copy and paste the following script.

```<code>function doGet(e) {
  var spreadsheetId = e.parameter.spreadsheetId;
  var chartId = e.parameter.chartId;
  var treatLabelsAsText = e.parameter.treatLabelsAsText;
  var ss = SpreadsheetApp.openById(spreadsheetId);
  var sheets = ss.getSheets();
  var done = false;
  for (var i = 0; i < sheets.length; i++) {
    var charts = sheets[i].getCharts();
    if (charts.length > 0) {
      for (var j = 0; j < charts.length; j++) {
        if (charts[j].getChartId() == chartId) {
          var modifiedChart = charts[j].modify().setOption('treatLabelsAsText', treatLabelsAsText).build();
          sheets[i].updateChart(modifiedChart);
          done = true;
          break;
        }
      }
      if (done) break;
    }
  }
  return ContentService.createTextOutput("Done.");
}
</code>```

3. Deploy Web Apps.

On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".

Select "Me" for "Execute the app as:".

Select "Anyone, even anonymous" for "Who has access to the app:".

This setting is for testing this workaround.

When "Only myself" is set to "Who has access to the app:", the access token is required to be used.

Click "Deploy" button as new "Project version".

Automatically open a dialog box of "Authorization required".

Click "Review Permissions".

Select own account.

Click "Advanced" at "This app isn't verified".

Click "Go to ### project name ###(unsafe)"

Click "Allow" button.

Click "OK".

Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.

When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.

4. Sample curl.

In order to test to access to the Web Apps, please use the following curl command.

```<code>curl -GL \
  -d "spreadsheetId=###" \
  -d "chartId=###" \
  -d "treatLabelsAsText=true" \
  "https://script.google.com/macros/s/###/exec"
</code>```

If you deployed Web Apps as "Only myself" for "Who has access to the app:", please use your access token as follows.

```<code>curl -GL \
  -H "Authorization: Bearer ###" \
  -d "spreadsheetId=###" \
  -d "chartId=###" \
  -d "treatLabelsAsText=true" \
  "https://script.google.com/macros/s/###/exec"
</code>```

Please set the URL of Web Apps retrieved above and the Spreadsheet ID, the chart ID and the value of treatLabelsAsText.

When above curl command is run, "Treat labels as text" is checked of the specific chart in the Spreadsheet. And you can see Done. at the console.

Note:

When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to Web Apps. Please be careful this.

When you want to use the access token, please include the scope of https://www.googleapis.com/auth/drive.readonly and/or https://www.googleapis.com/auth/drive to the access token.

References:

modify()

setOption()

Web Apps

Taking advantage of Web Apps with Google Apps Script

If I misunderstood your question and this was not the direction you want, I apologize.

Body:
You want to set Treat labels as text of the chart in the Google Spreadsheet.

You want to achieve this using Sheets API.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Issue and workaround:

Unfortunately, I couldn't find the property for setting Treat labels as text in the request body. And I prepare 2 patterns of the checked Treat labels as text and the unchecked Treat labels as text, and when both patterns are compared with the chart object retrieved with the method of spreadsheets.get, I could find no differences for both. By this, I thought that in the current stage, there is no method for setting Treat labels as text in Sheets API.

So as one of several workarounds, here, I would like to propose to use Web Apps as an API. When Google Apps Script is used, Treat labels as text can be set. This workaround uses this.

Usage:

The usage of this workaround is as follows.

1. Create new project of Google Apps Script.

Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.

If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.

2. Copy and paste script.

Please copy and paste the following script.

function doGet(e) {
  var spreadsheetId = e.parameter.spreadsheetId;
  var chartId = e.parameter.chartId;
  var treatLabelsAsText = e.parameter.treatLabelsAsText;
  var ss = SpreadsheetApp.openById(spreadsheetId);
  var sheets = ss.getSheets();
  var done = false;
  for (var i = 0; i < sheets.length; i++) {
    var charts = sheets[i].getCharts();
    if (charts.length > 0) {
      for (var j = 0; j < charts.length; j++) {
        if (charts[j].getChartId() == chartId) {
          var modifiedChart = charts[j].modify().setOption('treatLabelsAsText', treatLabelsAsText).build();
          sheets[i].updateChart(modifiedChart);
          done = true;
          break;
        }
      }
      if (done) break;
    }
  }
  return ContentService.createTextOutput("Done.");
}

3. Deploy Web Apps.

On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".

Select "Me" for "Execute the app as:".

Select "Anyone, even anonymous" for "Who has access to the app:".

This setting is for testing this workaround.

When "Only myself" is set to "Who has access to the app:", the access token is required to be used.

Click "Deploy" button as new "Project version".

Automatically open a dialog box of "Authorization required".

Click "Review Permissions".

Select own account.

Click "Advanced" at "This app isn't verified".

Click "Go to ### project name ###(unsafe)"

Click "Allow" button.

Click "OK".

Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.

When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.

4. Sample curl.

In order to test to access to the Web Apps, please use the following curl command.

curl -GL \
  -d "spreadsheetId=###" \
  -d "chartId=###" \
  -d "treatLabelsAsText=true" \
  "https://script.google.com/macros/s/###/exec"

If you deployed Web Apps as "Only myself" for "Who has access to the app:", please use your access token as follows.

curl -GL \
  -H "Authorization: Bearer ###" \
  -d "spreadsheetId=###" \
  -d "chartId=###" \
  -d "treatLabelsAsText=true" \
  "https://script.google.com/macros/s/###/exec"

Please set the URL of Web Apps retrieved above and the Spreadsheet ID, the chart ID and the value of treatLabelsAsText.

When above curl command is run, "Treat labels as text" is checked of the specific chart in the Spreadsheet. And you can see Done. at the console.

Note:

When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to Web Apps. Please be careful this.

When you want to use the access token, please include the scope of https://www.googleapis.com/auth/drive.readonly and/or https://www.googleapis.com/auth/drive to the access token.

References:

modify()

setOption()

Web Apps

Taking advantage of Web Apps with Google Apps Script

If I misunderstood your question and this was not the direction you want, I apologize.


问:
stackoverflow search api
I would like to use the search method of stackoverflow API to return the json structure of results based on a search keyword and then display those results (title, description and the url) in the SearchResults div.

I am new to C# and my first attempt went something like this:

```<code>    protected void searchStockOverflow(string y)
    {

        var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.stackoverflow.com/1.1/search?intitle="+y);
        httpWebRequest.ContentType = "text/json";
        httpWebRequest.Method = "POST";

        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            string json = "{ \"intitle\": \"" + y + "\"}";

            streamWriter.Write(json);
        }
        var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            var responseText = streamReader.ReadToEnd();

            SearchResults.InnerHtml += "<div style='border:1px solid blue;margin:5px;'>";
            SearchResults.InnerHtml += responseText + "<br />";
            SearchResults.InnerHtml += "</div><br style='clear:both;' />";
        }
    }
</code>```

The issue is that what is returned looks like dingbats rubbish - i guess because it is serialized and need to be deserialized?

答: Unfortunately I'm on my Mac and can't run a test on your code. You might want to check the character encoding of both your page and the response stream coming back. If they don't match; it could cause the characters coming from the response stream to be rendered incorrectly, hence the rubbish you're seeing.</p>

ContentLicense: CC BY-SA 3.0

Title: stackoverflow search api

Body:
I would like to use the search method of stackoverflow API to return the json structure of results based on a search keyword and then display those results (title, description and the url) in the SearchResults div.

I am new to C# and my first attempt went something like this:

    protected void searchStockOverflow(string y)
    {

        var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://api.stackoverflow.com/1.1/search?intitle="+y);
        httpWebRequest.ContentType = "text/json";
        httpWebRequest.Method = "POST";

        using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
        {
            string json = "{ \"intitle\": \"" + y + "\"}";

            streamWriter.Write(json);
        }
        var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            var responseText = streamReader.ReadToEnd();

            SearchResults.InnerHtml += "
";
            SearchResults.InnerHtml += responseText + "
";
            SearchResults.InnerHtml += "

";
        }
    }

The issue is that what is returned looks like dingbats rubbish - i guess because it is serialized and need to be deserialized?


问:
How to exclude or remove specific items from snapshot.data.documents?
```<code>final List<DocumentSnapshot> userList = snapshot.data.documents
.where((DocumentSnapshot documentSnapshot) => documentSnapshot['username'] != "John123145").toList();
</code>```

this works with excluding specific username with value "John123145".

Question is how can I exclude 2 or more username?

```<code>List<String> listitems= ["John", "James"];
final List<DocumentSnapshot> userList = snapshot.data.documents
.where((DocumentSnapshot documentSnapshot) => documentSnapshot['username'] != listitems).toList();
</code>```

Thanks in advance.

答:
Like this: </p>

```<code>List<String> listitems= ["John", "James"];
final List<DocumentSnapshot> userList = snapshot.data.documents.where((DocumentSnapshot documentSnapshot) {
  return !listitems.contains(documentSnapshot['username'])
}).toList();
</code>```

Body:
final List<DocumentSnapshot> userList = snapshot.data.documents
.where((DocumentSnapshot documentSnapshot) => documentSnapshot['username'] != "John123145").toList();

this works with excluding specific username with value "John123145".

Question is how can I exclude 2 or more username?

List<String> listitems= ["John", "James"];
final List<DocumentSnapshot> userList = snapshot.data.documents
.where((DocumentSnapshot documentSnapshot) => documentSnapshot['username'] != listitems).toList();

Thanks in advance.

Body:
Like this:

List<String> listitems= ["John", "James"];
final List<DocumentSnapshot> userList = snapshot.data.documents.where((DocumentSnapshot documentSnapshot) {
  return !listitems.contains(documentSnapshot['username'])
}).toList();


问:
Using python Requests with javascript pages
I am trying to use the Requests framework with python (http://docs.python-requests.org/en/latest/) but the page I am trying to get to uses javascript to fetch the info that I want.

I have tried to search on the web for a solution but the fact that I am searching with the keyword javascript most of the stuff I am getting is how to scrape with the javascript language.

Is there anyway to use the requests framework with pages that use javascript?

答:
its a wrapper around pyppeteer or smth? :( i thought its something different</p>

```<code>    @property
    async def browser(self):
        if not hasattr(self, "_browser"):
            self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)

        return self._browser
</code>```

Body:
its a wrapper around pyppeteer or smth? :( i thought its something different

    @property
    async def browser(self):
        if not hasattr(self, "_browser"):
            self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)

        return self._browser


问:
Central Directory Corrupt deploying Python Azure function
I was previously able to deploy an Azure function written in Python using the command func azure functionapp publish <FunctionAppName>  from my project directory, building it remotely.  It worked until lunchtime yesterday.

I now get the following message.

```<code>Creating archive for current directory...
Performing remote build for functions project.
Deleting the old .python_packages directory
Uploading  [######################################################################################]
Remote build in progress, please wait...
Fetching changes.
Cleaning up temp folders from previous zip deployments and extracting pushed zip file /tmp/zipdeploy/c5e66350-4b87-4e72-9900-b2a1ae4521a8.zip (0.00 MB) to /tmp/zipdeploy/extracted
Central Directory corrupt.
Remote build failed!
</code>```

I've tried the following to see if I can resolve it without any success:

Switching my machine off and on.

Deploying an older version of the code in case I've changed anything.

Deploying from the command prompt in visual studio code.

Reinstalling Azure functions core tools.

Deploying from a different machine on a different network (I read that there are sometimes firewall issues with uploading zip files but my IT manager assures me we have no restrictions and these settings have not been changed).  In doing so, I had to install Azure functions core tools from scratch as it had never been installed on that machine before.

Creating a completely new clean functionapp and deploying there.

Creating a brand new minimal Python application in a clean directory and deploying this to the new functionapp.

I get the same message in each case.

I'm stuck here.  Does anyone have any more information about what the error message might mean is going wrong or any ideas?

Other investigations -

I've tried deploying as a different Azure user (same error).

I've checked for any processes using port 9091 (none were found).

I have also tried to build locally using func azure functionapp publish IncidentProcessing4 --build local

I got some different error messages

```<code>Performing local build for functions project.
Directory .python_packages already in sync with requirements.txt. Skipping restoring dependencies...
Uploading package...
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 1 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 2 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 3 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
</code>```

I noticed that in my \users\name\appdata\local\temp directory 2 files had been created by the build, called temp374D.tmp and tmp374E.tmp.  The first of these was 0KB in size and the 2nd 8KB in size.

My suspicion is something is causing the first file to be created and something on the server is attempting and failing to unzip it.

More additional information - "Deploy to Function App" from Visual Studio code deploys, but when the Azure function runs, I get errors about modules referenced by the function not being loaded.    If it's possible to deploy the modules in requirements.txt with the function app that will be a work around.

答:
This may not apply, given your exhaustive set of things you did trying to diagnose the issue, but I'll throw it out there. I have run into this if my function is running, either in a terminal window (via func host start) or even via the VSCode functions extension.

It would seem like it should be obvious to see if anything's running, but I've seen VSCode leave behind function host processes in a running state. To check, you could check netstat (netstat -a -n | grep 9091) or lsof (lsof -nP -iTCP:9091 | grep LISTEN). The latter gives you the pid that has the port open.

Body:
I was previously able to deploy an Azure function written in Python using the command func azure functionapp publish <FunctionAppName>  from my project directory, building it remotely.  It worked until lunchtime yesterday.

I now get the following message.

Creating archive for current directory...
Performing remote build for functions project.
Deleting the old .python_packages directory
Uploading  [######################################################################################]
Remote build in progress, please wait...
Fetching changes.
Cleaning up temp folders from previous zip deployments and extracting pushed zip file /tmp/zipdeploy/c5e66350-4b87-4e72-9900-b2a1ae4521a8.zip (0.00 MB) to /tmp/zipdeploy/extracted
Central Directory corrupt.
Remote build failed!

I've tried the following to see if I can resolve it without any success:

Switching my machine off and on.

Deploying an older version of the code in case I've changed anything.

Deploying from the command prompt in visual studio code.

Reinstalling Azure functions core tools.

Deploying from a different machine on a different network (I read that there are sometimes firewall issues with uploading zip files but my IT manager assures me we have no restrictions and these settings have not been changed).  In doing so, I had to install Azure functions core tools from scratch as it had never been installed on that machine before.

Creating a completely new clean functionapp and deploying there.

Creating a brand new minimal Python application in a clean directory and deploying this to the new functionapp.

I get the same message in each case.

I'm stuck here.  Does anyone have any more information about what the error message might mean is going wrong or any ideas?

Other investigations -

I've tried deploying as a different Azure user (same error).

I've checked for any processes using port 9091 (none were found).

I have also tried to build locally using func azure functionapp publish IncidentProcessing4 --build local

I got some different error messages

Performing local build for functions project.
Directory .python_packages already in sync with requirements.txt. Skipping restoring dependencies...
Uploading package...
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 1 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 2 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.
Retry: 3 of 3
Uploading 0 B [###################################################################################]
Attempted to divide by zero.

I noticed that in my \users\name\appdata\local\temp directory 2 files had been created by the build, called temp374D.tmp and tmp374E.tmp.  The first of these was 0KB in size and the 2nd 8KB in size.

My suspicion is something is causing the first file to be created and something on the server is attempting and failing to unzip it.

More additional information - "Deploy to Function App" from Visual Studio code deploys, but when the Azure function runs, I get errors about modules referenced by the function not being loaded.    If it's possible to deploy the modules in requirements.txt with the function app that will be a work around.


问:
heroku.com page can't be found - app is rails api
I have a rails api with react client. my rails api works fine locally.
When i pushed it to heroku it deployed but when went to view it said my page couldn't be found.
i added a root route which is what it was asking for(?) but to no avail... any help would be appreciated!
i also tested heroku by deploying test rails apps.
If they were made with --api, the page once again couldn't be found.
I made one without --api, it worked initially but when tried to migrate db it resulted in debug #4 errors...</p>

```<code>                               Prefix Verb   URI Pattern                                                                              Controller#Action
                         api_v1_users GET    /api/v1/users(.:format)                                                                  api/v1/users#index
                                      POST   /api/v1/users(.:format)                                                                  api/v1/users#create
                          api_v1_user GET    /api/v1/users/:id(.:format)                                                              api/v1/users#show
                                      PATCH  /api/v1/users/:id(.:format)                                                              api/v1/users#update
                                      PUT    /api/v1/users/:id(.:format)                                                              api/v1/users#update
                                      DELETE /api/v1/users/:id(.:format)                                                              api/v1/users#destroy
                          api_v1_pets GET    /api/v1/pets(.:format)                                                                   api/v1/pets#index
                                      POST   /api/v1/pets(.:format)                                                                   api/v1/pets#create
                           api_v1_pet GET    /api/v1/pets/:id(.:format)                                                               api/v1/pets#show
                                      PATCH  /api/v1/pets/:id(.:format)                                                               api/v1/pets#update
                                      PUT    /api/v1/pets/:id(.:format)                                                               api/v1/pets#update
                                      DELETE /api/v1/pets/:id(.:format)                                                               api/v1/pets#destroy
                               api_v1 PATCH  /api/v1/pets/:id/toggle_adopt(.:format)                                                  api/v1/pets#toggle_adopt
                                      POST   /api/v1/pets/:id/adopt(.:format)                                                         api/v1/pets#adopt
                                      POST   /api/v1/users/:id/get_pet(.:format)                                                      api/v1/users#get_pet
                                      GET    /api/v1(.:format)                                                                        api/v1/pets#index
                         api_v1_login POST   /api/v1/login(.:format)                                                                  api/v1/auth#login
                    api_v1_auto_login GET    /api/v1/auto_login(.:format)                                                             api/v1/auth#auto_login
        rails_mandrill_inbound_emails POST   /rails/action_mailbox/mandrill/inbound_emails(.:format)                                  action_mailbox/ingresses/mandrill/inbound_emails#create
        rails_postmark_inbound_emails POST   /rails/action_mailbox/postmark/inbound_emails(.:format)                                  action_mailbox/ingresses/postmark/inbound_emails#create
           rails_relay_inbound_emails POST   /rails/action_mailbox/relay/inbound_emails(.:format)                                     action_mailbox/ingresses/relay/inbound_emails#create
        rails_sendgrid_inbound_emails POST   /rails/action_mailbox/sendgrid/inbound_emails(.:format)                                  action_mailbox/ingresses/sendgrid/inbound_emails#create
         rails_mailgun_inbound_emails POST   /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)                              action_mailbox/ingresses/mailgun/inbound_emails#create
       rails_conductor_inbound_emails GET    /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#index
                                      POST   /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#create
        rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#show
                                      PATCH  /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      PUT    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#destroy
rails_conductor_inbound_email_reroute POST   /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)                      rails/conductor/action_mailbox/reroutes#create
                   rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
            rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
                   rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
            update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
                 rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create
</code>```

```<code>// ♥ heroku logs
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack (2.2.2) lib/rack/runtime.rb:22:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/configuration.rb:228:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:681:in `handle_request'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:472:in `process_client'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:328:in `block in run'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
2020-02-19T17:22:24.570026+00:00 heroku[web.1]: Idling
2020-02-19T17:22:24.573775+00:00 heroku[web.1]: State changed from up to down
2020-02-19T17:22:25.738188+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T17:22:25.771134+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T17:22:25.773522+00:00 app[web.1]: === puma shutdown: 2020-02-19 17:22:25 +0000 ===
2020-02-19T17:22:25.773546+00:00 app[web.1]: - Goodbye!
2020-02-19T17:22:25.866786+00:00 heroku[web.1]: Process exited with status 143
2020-02-19T18:47:00.519301+00:00 heroku[web.1]: Unidling
2020-02-19T18:47:00.536382+00:00 heroku[web.1]: State changed from down to starting
2020-02-19T18:47:03.058431+00:00 heroku[web.1]: Starting process with command `bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}`
2020-02-19T18:47:05.399248+00:00 app[web.1]: Puma starting in single mode...
2020-02-19T18:47:05.399262+00:00 app[web.1]: * Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
2020-02-19T18:47:05.399263+00:00 app[web.1]: * Min threads: 5, max threads: 5
2020-02-19T18:47:05.399263+00:00 app[web.1]: * Environment: production
2020-02-19T18:47:11.357442+00:00 app[web.1]: * Listening on tcp://0.0.0.0:54444
2020-02-19T18:47:11.357812+00:00 app[web.1]: Use Ctrl-C to stop
2020-02-19T18:47:11.926899+00:00 heroku[web.1]: State changed from starting to up
2020-02-19T18:47:12.591966+00:00 heroku[router]: at=info method=OPTIONS path="/api/v1/auto_login" host=boiling-garden-61294.herokuapp.com request_id=63546cfe-0db6-4273-88ff-652097e7432c fwd="184.153.22.244" dyno=web.1 connect=1ms service=1ms status=200 bytes=307 protocol=https
2020-02-19T19:02:50.855756+00:00 app[web.1]: I, [2020-02-19T19:02:50.855651 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Started GET "/api/v1/auto_login" for 184.153.22.244 at 2020-02-19 19:02:50 +0000
2020-02-19T19:02:50.857404+00:00 app[web.1]: I, [2020-02-19T19:02:50.857329 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Processing by Api::V1::AuthController#auto_login as */*
2020-02-19T19:02:52.341221+00:00 app[web.1]: D, [2020-02-19T19:02:52.341059 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5]   User Load (17.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
2020-02-19T19:02:52.426916+00:00 app[web.1]: D, [2020-02-19T19:02:52.426791 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5]   CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
2020-02-19T19:02:52.473014+00:00 app[web.1]: D, [2020-02-19T19:02:52.472882 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] [active_model_serializers]   Pet Load (35.6ms)  SELECT "pets".* FROM "pets" WHERE "pets"."owner_id" = $1  [["owner_id", 4]]
2020-02-19T19:02:52.493448+00:00 app[web.1]: I, [2020-02-19T19:02:52.493334 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] [active_model_serializers] Rendered UserSerializer with ActiveModelSerializers::Adapter::Attributes (65.55ms)
2020-02-19T19:02:52.493828+00:00 app[web.1]: I, [2020-02-19T19:02:52.493752 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Completed 200 OK in 1636ms (Views: 23.2ms | ActiveRecord: 1558.9ms | Allocations: 17956)
2020-02-19T19:02:52.495894+00:00 heroku[router]: at=info method=GET path="/api/v1/auto_login" host=boiling-garden-61294.herokuapp.com request_id=3c337a3b-162b-4362-8d16-0ed2f50318c5 fwd="184.153.22.244" dyno=web.1 connect=0ms service=1641ms status=304 bytes=636 protocol=https
2020-02-19T19:38:32.700667+00:00 heroku[web.1]: Idling
2020-02-19T19:38:32.705096+00:00 heroku[web.1]: State changed from up to down
2020-02-19T19:38:33.831696+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T19:38:33.852410+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T19:38:33.858074+00:00 app[web.1]: === puma shutdown: 2020-02-19 19:38:33 +0000 ===
2020-02-19T19:38:33.858355+00:00 app[web.1]: - Goodbye!
2020-02-19T19:38:33.969920+00:00 heroku[web.1]: Process exited with status 143
2020-02-19T20:07:07.613633+00:00 heroku[web.1]: Unidling
2020-02-19T20:07:07.628601+00:00 heroku[web.1]: State changed from down to starting
2020-02-19T20:07:10.629524+00:00 heroku[web.1]: Starting process with command `bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}`
2020-02-19T20:07:13.443149+00:00 app[web.1]: Puma starting in single mode...
2020-02-19T20:07:13.443242+00:00 app[web.1]: * Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
2020-02-19T20:07:13.443243+00:00 app[web.1]: * Min threads: 5, max threads: 5
2020-02-19T20:07:13.443244+00:00 app[web.1]: * Environment: production
2020-02-19T20:07:19.064575+00:00 app[web.1]: * Listening on tcp://0.0.0.0:26954
2020-02-19T20:07:19.065126+00:00 app[web.1]: Use Ctrl-C to stop
2020-02-19T20:07:19.389039+00:00 heroku[web.1]: State changed from starting to up
2020-02-19T20:07:21.691904+00:00 app[web.1]: I, [2020-02-19T20:07:21.691780 #4]  INFO -- : [de344029-a862-437f-8eeb-e7c3092c3894] Started GET "/" for 184.153.22.244 at 2020-02-19 20:07:21 +0000
2020-02-19T20:07:21.693363+00:00 app[web.1]: F, [2020-02-19T20:07:21.693281 #4] FATAL -- : [de344029-a862-437f-8eeb-e7c3092c3894]
2020-02-19T20:07:21.693364+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] ActionController::RoutingError (No route matches [GET] "/"):
2020-02-19T20:07:21.693365+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894]
2020-02-19T20:07:21.693379+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
2020-02-19T20:07:21.693379+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
2020-02-19T20:07:21.693380+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
2020-02-19T20:07:21.693380+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
2020-02-19T20:07:21.693383+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack (2.2.2) lib/rack/runtime.rb:22:in `call'
2020-02-19T20:07:21.693384+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
2020-02-19T20:07:21.693386+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
2020-02-19T20:07:21.693386+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/configuration.rb:228:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:681:in `handle_request'
2020-02-19T20:07:21.693388+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:472:in `process_client'
2020-02-19T20:07:21.693388+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:328:in `block in run'
2020-02-19T20:07:21.693389+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
2020-02-19T20:07:21.695902+00:00 heroku[router]: at=info method=GET path="/" host=boiling-garden-61294.herokuapp.com request_id=de344029-a862-437f-8eeb-e7c3092c3894 fwd="184.153.22.244" dyno=web.1 connect=1ms service=7ms status=404 bytes=191 protocol=https
2020-02-19T20:38:22.500446+00:00 heroku[web.1]: Idling
2020-02-19T20:38:22.505029+00:00 heroku[web.1]: State changed from up to down
2020-02-19T20:38:23.149591+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T20:38:23.150452+00:00 app[web.1]: === puma shutdown: 2020-02-19 20:38:23 +0000 ===
2020-02-19T20:38:23.150454+00:00 app[web.1]: - Goodbye!
2020-02-19T20:38:23.141795+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T20:38:23.197413+00:00 heroku[web.1]: Process exited with status 143```
</code>```

答:
This is a normal behavior in --api only applications, simply rails doesn't know what to serve. In API only applications ApplicationController inherits from ActionController::API instead of ActionController::Base which removes some functionality required by browsers.

An API Controller is different from a normal controller in the sense that by default it doesn't include some features that are usually required by browser access only: layouts and templates rendering, flash, assets, and so on. This makes the entire controller stack thinner, suitable for API applications. It doesn't mean you won't have such features if you need them: they're all available for you to include in your application, they're just not part of the default API controller stack.

Source: https://api.rubyonrails.org/classes/ActionController/API.html

If you have designed the application as json api, all json format urls should work fine.

Body:
I have a rails api with react client. my rails api works fine locally.
When i pushed it to heroku it deployed but when went to view it said my page couldn't be found.
i added a root route which is what it was asking for(?) but to no avail... any help would be appreciated!
i also tested heroku by deploying test rails apps.
If they were made with --api, the page once again couldn't be found.
I made one without --api, it worked initially but when tried to migrate db it resulted in debug #4 errors...

                               Prefix Verb   URI Pattern                                                                              Controller#Action
                         api_v1_users GET    /api/v1/users(.:format)                                                                  api/v1/users#index
                                      POST   /api/v1/users(.:format)                                                                  api/v1/users#create
                          api_v1_user GET    /api/v1/users/:id(.:format)                                                              api/v1/users#show
                                      PATCH  /api/v1/users/:id(.:format)                                                              api/v1/users#update
                                      PUT    /api/v1/users/:id(.:format)                                                              api/v1/users#update
                                      DELETE /api/v1/users/:id(.:format)                                                              api/v1/users#destroy
                          api_v1_pets GET    /api/v1/pets(.:format)                                                                   api/v1/pets#index
                                      POST   /api/v1/pets(.:format)                                                                   api/v1/pets#create
                           api_v1_pet GET    /api/v1/pets/:id(.:format)                                                               api/v1/pets#show
                                      PATCH  /api/v1/pets/:id(.:format)                                                               api/v1/pets#update
                                      PUT    /api/v1/pets/:id(.:format)                                                               api/v1/pets#update
                                      DELETE /api/v1/pets/:id(.:format)                                                               api/v1/pets#destroy
                               api_v1 PATCH  /api/v1/pets/:id/toggle_adopt(.:format)                                                  api/v1/pets#toggle_adopt
                                      POST   /api/v1/pets/:id/adopt(.:format)                                                         api/v1/pets#adopt
                                      POST   /api/v1/users/:id/get_pet(.:format)                                                      api/v1/users#get_pet
                                      GET    /api/v1(.:format)                                                                        api/v1/pets#index
                         api_v1_login POST   /api/v1/login(.:format)                                                                  api/v1/auth#login
                    api_v1_auto_login GET    /api/v1/auto_login(.:format)                                                             api/v1/auth#auto_login
        rails_mandrill_inbound_emails POST   /rails/action_mailbox/mandrill/inbound_emails(.:format)                                  action_mailbox/ingresses/mandrill/inbound_emails#create
        rails_postmark_inbound_emails POST   /rails/action_mailbox/postmark/inbound_emails(.:format)                                  action_mailbox/ingresses/postmark/inbound_emails#create
           rails_relay_inbound_emails POST   /rails/action_mailbox/relay/inbound_emails(.:format)                                     action_mailbox/ingresses/relay/inbound_emails#create
        rails_sendgrid_inbound_emails POST   /rails/action_mailbox/sendgrid/inbound_emails(.:format)                                  action_mailbox/ingresses/sendgrid/inbound_emails#create
         rails_mailgun_inbound_emails POST   /rails/action_mailbox/mailgun/inbound_emails/mime(.:format)                              action_mailbox/ingresses/mailgun/inbound_emails#create
       rails_conductor_inbound_emails GET    /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#index
                                      POST   /rails/conductor/action_mailbox/inbound_emails(.:format)                                 rails/conductor/action_mailbox/inbound_emails#create
        rails_conductor_inbound_email GET    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#show
                                      PATCH  /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      PUT    /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#update
                                      DELETE /rails/conductor/action_mailbox/inbound_emails/:id(.:format)                             rails/conductor/action_mailbox/inbound_emails#destroy
rails_conductor_inbound_email_reroute POST   /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format)                      rails/conductor/action_mailbox/reroutes#create
                   rails_service_blob GET    /rails/active_storage/blobs/:signed_id/*filename(.:format)                               active_storage/blobs#show
            rails_blob_representation GET    /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
                   rails_disk_service GET    /rails/active_storage/disk/:encoded_key/*filename(.:format)                              active_storage/disk#show
            update_rails_disk_service PUT    /rails/active_storage/disk/:encoded_token(.:format)                                      active_storage/disk#update
                 rails_direct_uploads POST   /rails/active_storage/direct_uploads(.:format)                                           active_storage/direct_uploads#create

// ♥ heroku logs
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
2020-02-19T16:44:53.897044+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
2020-02-19T16:44:53.897045+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
2020-02-19T16:44:53.897046+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack (2.2.2) lib/rack/runtime.rb:22:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
2020-02-19T16:44:53.897047+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/configuration.rb:228:in `call'
2020-02-19T16:44:53.897048+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:681:in `handle_request'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:472:in `process_client'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/server.rb:328:in `block in run'
2020-02-19T16:44:53.897049+00:00 app[web.1]: [0e32db7c-e3cb-4afb-a003-d73b769ce813] puma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
2020-02-19T17:22:24.570026+00:00 heroku[web.1]: Idling
2020-02-19T17:22:24.573775+00:00 heroku[web.1]: State changed from up to down
2020-02-19T17:22:25.738188+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T17:22:25.771134+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T17:22:25.773522+00:00 app[web.1]: === puma shutdown: 2020-02-19 17:22:25 +0000 ===
2020-02-19T17:22:25.773546+00:00 app[web.1]: - Goodbye!
2020-02-19T17:22:25.866786+00:00 heroku[web.1]: Process exited with status 143
2020-02-19T18:47:00.519301+00:00 heroku[web.1]: Unidling
2020-02-19T18:47:00.536382+00:00 heroku[web.1]: State changed from down to starting
2020-02-19T18:47:03.058431+00:00 heroku[web.1]: Starting process with command `bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}`
2020-02-19T18:47:05.399248+00:00 app[web.1]: Puma starting in single mode...
2020-02-19T18:47:05.399262+00:00 app[web.1]: * Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
2020-02-19T18:47:05.399263+00:00 app[web.1]: * Min threads: 5, max threads: 5
2020-02-19T18:47:05.399263+00:00 app[web.1]: * Environment: production
2020-02-19T18:47:11.357442+00:00 app[web.1]: * Listening on tcp://0.0.0.0:54444
2020-02-19T18:47:11.357812+00:00 app[web.1]: Use Ctrl-C to stop
2020-02-19T18:47:11.926899+00:00 heroku[web.1]: State changed from starting to up
2020-02-19T18:47:12.591966+00:00 heroku[router]: at=info method=OPTIONS path="/api/v1/auto_login" host=boiling-garden-61294.herokuapp.com request_id=63546cfe-0db6-4273-88ff-652097e7432c fwd="184.153.22.244" dyno=web.1 connect=1ms service=1ms status=200 bytes=307 protocol=https
2020-02-19T19:02:50.855756+00:00 app[web.1]: I, [2020-02-19T19:02:50.855651 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Started GET "/api/v1/auto_login" for 184.153.22.244 at 2020-02-19 19:02:50 +0000
2020-02-19T19:02:50.857404+00:00 app[web.1]: I, [2020-02-19T19:02:50.857329 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Processing by Api::V1::AuthController#auto_login as */*
2020-02-19T19:02:52.341221+00:00 app[web.1]: D, [2020-02-19T19:02:52.341059 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5]   User Load (17.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
2020-02-19T19:02:52.426916+00:00 app[web.1]: D, [2020-02-19T19:02:52.426791 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5]   CACHE User Load (0.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 4], ["LIMIT", 1]]
2020-02-19T19:02:52.473014+00:00 app[web.1]: D, [2020-02-19T19:02:52.472882 #4] DEBUG -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] [active_model_serializers]   Pet Load (35.6ms)  SELECT "pets".* FROM "pets" WHERE "pets"."owner_id" = $1  [["owner_id", 4]]
2020-02-19T19:02:52.493448+00:00 app[web.1]: I, [2020-02-19T19:02:52.493334 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] [active_model_serializers] Rendered UserSerializer with ActiveModelSerializers::Adapter::Attributes (65.55ms)
2020-02-19T19:02:52.493828+00:00 app[web.1]: I, [2020-02-19T19:02:52.493752 #4]  INFO -- : [3c337a3b-162b-4362-8d16-0ed2f50318c5] Completed 200 OK in 1636ms (Views: 23.2ms | ActiveRecord: 1558.9ms | Allocations: 17956)
2020-02-19T19:02:52.495894+00:00 heroku[router]: at=info method=GET path="/api/v1/auto_login" host=boiling-garden-61294.herokuapp.com request_id=3c337a3b-162b-4362-8d16-0ed2f50318c5 fwd="184.153.22.244" dyno=web.1 connect=0ms service=1641ms status=304 bytes=636 protocol=https
2020-02-19T19:38:32.700667+00:00 heroku[web.1]: Idling
2020-02-19T19:38:32.705096+00:00 heroku[web.1]: State changed from up to down
2020-02-19T19:38:33.831696+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T19:38:33.852410+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T19:38:33.858074+00:00 app[web.1]: === puma shutdown: 2020-02-19 19:38:33 +0000 ===
2020-02-19T19:38:33.858355+00:00 app[web.1]: - Goodbye!
2020-02-19T19:38:33.969920+00:00 heroku[web.1]: Process exited with status 143
2020-02-19T20:07:07.613633+00:00 heroku[web.1]: Unidling
2020-02-19T20:07:07.628601+00:00 heroku[web.1]: State changed from down to starting
2020-02-19T20:07:10.629524+00:00 heroku[web.1]: Starting process with command `bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}`
2020-02-19T20:07:13.443149+00:00 app[web.1]: Puma starting in single mode...
2020-02-19T20:07:13.443242+00:00 app[web.1]: * Version 4.3.1 (ruby 2.6.5-p114), codename: Mysterious Traveller
2020-02-19T20:07:13.443243+00:00 app[web.1]: * Min threads: 5, max threads: 5
2020-02-19T20:07:13.443244+00:00 app[web.1]: * Environment: production
2020-02-19T20:07:19.064575+00:00 app[web.1]: * Listening on tcp://0.0.0.0:26954
2020-02-19T20:07:19.065126+00:00 app[web.1]: Use Ctrl-C to stop
2020-02-19T20:07:19.389039+00:00 heroku[web.1]: State changed from starting to up
2020-02-19T20:07:21.691904+00:00 app[web.1]: I, [2020-02-19T20:07:21.691780 #4]  INFO -- : [de344029-a862-437f-8eeb-e7c3092c3894] Started GET "/" for 184.153.22.244 at 2020-02-19 20:07:21 +0000
2020-02-19T20:07:21.693363+00:00 app[web.1]: F, [2020-02-19T20:07:21.693281 #4] FATAL -- : [de344029-a862-437f-8eeb-e7c3092c3894]
2020-02-19T20:07:21.693364+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] ActionController::RoutingError (No route matches [GET] "/"):
2020-02-19T20:07:21.693365+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894]
2020-02-19T20:07:21.693379+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:36:in `call'
2020-02-19T20:07:21.693379+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
2020-02-19T20:07:21.693380+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:38:in `call_app'
2020-02-19T20:07:21.693380+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `block in call'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `block in tagged'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:28:in `tagged'
2020-02-19T20:07:21.693381+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/tagged_logging.rb:80:in `tagged'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/rack/logger.rb:26:in `call'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
2020-02-19T20:07:21.693382+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/request_id.rb:27:in `call'
2020-02-19T20:07:21.693383+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack (2.2.2) lib/rack/runtime.rb:22:in `call'
2020-02-19T20:07:21.693384+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] activesupport (6.0.2.1) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/executor.rb:14:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/static.rb:126:in `call'
2020-02-19T20:07:21.693385+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack (2.2.2) lib/rack/sendfile.rb:110:in `call'
2020-02-19T20:07:21.693386+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] actionpack (6.0.2.1) lib/action_dispatch/middleware/host_authorization.rb:77:in `call'
2020-02-19T20:07:21.693386+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] rack-cors (1.1.1) lib/rack/cors.rb:100:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] railties (6.0.2.1) lib/rails/engine.rb:526:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/configuration.rb:228:in `call'
2020-02-19T20:07:21.693387+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:681:in `handle_request'
2020-02-19T20:07:21.693388+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:472:in `process_client'
2020-02-19T20:07:21.693388+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/server.rb:328:in `block in run'
2020-02-19T20:07:21.693389+00:00 app[web.1]: [de344029-a862-437f-8eeb-e7c3092c3894] puma (4.3.1) lib/puma/thread_pool.rb:134:in `block in spawn_thread'
2020-02-19T20:07:21.695902+00:00 heroku[router]: at=info method=GET path="/" host=boiling-garden-61294.herokuapp.com request_id=de344029-a862-437f-8eeb-e7c3092c3894 fwd="184.153.22.244" dyno=web.1 connect=1ms service=7ms status=404 bytes=191 protocol=https
2020-02-19T20:38:22.500446+00:00 heroku[web.1]: Idling
2020-02-19T20:38:22.505029+00:00 heroku[web.1]: State changed from up to down
2020-02-19T20:38:23.149591+00:00 app[web.1]: - Gracefully stopping, waiting for requests to finish
2020-02-19T20:38:23.150452+00:00 app[web.1]: === puma shutdown: 2020-02-19 20:38:23 +0000 ===
2020-02-19T20:38:23.150454+00:00 app[web.1]: - Goodbye!
2020-02-19T20:38:23.141795+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2020-02-19T20:38:23.197413+00:00 heroku[web.1]: Process exited with status 143```


问:
FASTCGI process has failed frequently recently. Try the request again in a while
We have setup a Wordpress Website on IIS 10 which was working fine. But suddenly it stops working and i got this error

"FASTCGI process has failed frequently recently. Try the request again
  in a while"

Restarting IIS fixed this problem.

Anybody tell me why this issue has occurred and how we can fix this ?

Thanks

答:
You need to maximize "Instance MaxRequest" at FASTCGI Configuration. Just clic en IIS root -> FastCGI Settings, select you php-cgi.exe for WP and clic Edit. Then increise Instance MaxRequests

[IIS FastCGI Settings]


问:
Deploying GWT application without using the google app engine
I created a project without using the "google app engine" (by unchecking the checkbox when I created the project).

When I debug the application, everything works fine but when I start deploying it to the webserver, I can't do any RPC calls (the onFailure method is executed).

Now my question is, if I have to add any *.jars into the tomcat server before I can deploy it.

Best regards, Stefan

答:
You can deploy your GWT project inside a WAR file. It works perfectly.

Doing a search in google you'll find multiple solutions, like this one: http://blog.elitecoderz.net/gwt-and-tomcat-create-war-using-eclipse-to-deploy-war-on-tomcat/2009/12/